-
Notifications
You must be signed in to change notification settings - Fork 19
Fix PARTITION_INFORMATION_GPT structure (in according to pinvoke) #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
I find it very odd that the description of placement of the guids should have an effect. I've tried out the following:
I cannot reproduce a (simple) case where the guid would be read differently. Could you try to fetch out the data you're seeing? (Use Test code. using System;
using System.Runtime.InteropServices;
namespace ConsoleApp17
{
class Program
{
static void Main(string[] args)
{
PARTITION_INFORMATION_GPT orig = new PARTITION_INFORMATION_GPT
{
Attributes = 500,
Name = "Test",
PartitionId = new Guid("ebd0a0a2-b9e5-4433-87c0-68b6b72699c7"),
PartitionType = new Guid("ebd0a0a2-b9e5-4433-87c0-68b6b72699c7")
};
var size = Marshal.SizeOf<PARTITION_INFORMATION_GPT>();
var ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(orig,ptr,false);
var asOld = Marshal.PtrToStructure<PARTITION_INFORMATION_GPT>(ptr);
var asNew = Marshal.PtrToStructure<PARTITION_INFORMATION_GPT_NEW>(ptr);
Console.WriteLine("Old guid: " + asOld.PartitionType);
Console.WriteLine("New guid: " + asNew.PartitionType);
}
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
public struct PARTITION_INFORMATION_GPT
{
[FieldOffset(0)]
public Guid PartitionType;
[FieldOffset(16)]
public Guid PartitionId;
[FieldOffset(32)]
[MarshalAs(UnmanagedType.U8)]
public ulong Attributes;
[FieldOffset(40)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 36)]
public string Name;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct PARTITION_INFORMATION_GPT_NEW
{
public Guid PartitionType;
public Guid PartitionId;
[MarshalAs(UnmanagedType.U8)]
public ulong Attributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 36)]
public string Name;
}
} |
I tried to test your code. It works well without any problem. My case is the next: I just use your example, (ExampleDiskIO method) but with string driveName = @"\\.\C:";. And then I see such problem. If I use PARTITION_INFORMATION_GPT_NEW I see problem with Attributes (strange value 4914476011590058402). |
Well, to be fair, I didn't include the Enum value in my short test. |
Don't know if it's relevant anymore, but I've pinpointed the issue @DamirAinullin originally stated. Making the struct Sequential didn't work for me, because I started getting runtime errors about misaligned memory positions. It starts with the PARTITION_INFORMATION_UNION file, where the same offset is assigned to After some research, structures that are used in a union, have to be decorated with Once setting the above, you can isolate the error to the members From experimenting, GPT struct seems to be allocated first, and MBR afterwards. My guessing is that since bool type is somewhat strange for marshaling (look into this post https://stackoverflow.com/a/44884332), and MBR has 2 of them, they are incorrectly overwritting the bytes shared by both structs, in those particular positions. You can swap the position of both structs in PARTITION_INFORMATION_UNION and watch the opposite: GUIDs for gpt type are correct now, and boolean fields on the MBR struct make no sense. Making both bool fields, of byte types, seems to solve the GUID issue, since byte is blittable, but I'm not able to test with a MBR partition to make sure it doesn't break all hell loose. |
In regarding to the comment by @Vengariel, I can say that I am working on a similar project, using By changing the I see this is still in the Open state, I don't use this project in any way (I only found it by googling the GUID), but contained enough information to solve my problem, so that it might be useful for you also in deciding what to do here. Otherwise, there's really not very much information that I could find either. // Must be set to explicit, else it won't overlap with PARTITION_INFORMATION_MBR.
// See these resources:
// - https://stackoverflow.com/questions/14128093/marshaling-error-in-x64
// - https://stackoverflow.com/questions/35786764/creating-multiple-partitions-on-usb-using-c-sharp/35792276
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
public struct PARTITION_INFORMATION_GPT
{
[FieldOffset(0)]
public Guid PartitionType;
[FieldOffset(16)]
public Guid PartitionId;
[FieldOffset(32)]
[MarshalAs(UnmanagedType.U8)]
public EFIPartitionAttributes Attributes;
[FieldOffset(40)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 36)]
public string Name;
}
[StructLayout(LayoutKind.Sequential)]
public struct PARTITION_INFORMATION_MBR
{
public byte PartitionType;
// The BootIndicator and RecognizedPartition have to be of type 'byte', as 'bool' is not blittable. Using:
// [MarshalAs(UnmanagedType.U1)] bool BootIndicator
// will actually overwrite the GUID PartitionType fields for bytes 2 and 3 to be the value 01 (which, as
// this is a union type, those two bytes in the GUID have the same location as the next two 'bool' fields).
public byte BootIndicator;
public byte RecognizedPartition;
public uint HiddenSectors;
}
[StructLayout(LayoutKind.Explicit)]
public struct PARTITION_INFORMATION_UNION
{
[FieldOffset(0)]
public PARTITION_INFORMATION_GPT Gpt;
[FieldOffset(0)]
public PARTITION_INFORMATION_MBR Mbr;
}
[StructLayout(LayoutKind.Sequential)]
public struct PARTITION_INFORMATION_EX
{
[MarshalAs(UnmanagedType.U4)]
public PartitionStyle PartitionStyle;
public long StartingOffset;
public long PartitionLength;
public int PartitionNumber;
public bool RewritePartition;
public PARTITION_INFORMATION_UNION DriveLayoutInformaiton;
} So my contribution to saying thanks - you helped me solve my own problem. And I did test with MBR, it appears to work (of course, you'll need to do your own check to see if the value is zero or not to convert it to a bool). |
Fix PARTITION_INFORMATION_GPT structure according to url. Works better for my case, for example I get correct partitionType Guid = ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 instead of wrong eb0101a2-b9e5-4433-87c0-68b6b72699c7.