// these struct definitions are in the class IOWrap
[StructLayout(LayoutKind.Sequential)]
public struct STORAGE_PROPERTY_QUERY
{
public STORAGE_PROPERTY_ID PropertyId; // ID of the property being retrieved
public STORAGE_QUERY_TYPE QueryType; // Flags indicating the type of query being performed
public byte[] AdditionalParameters; // Space for additional parameters if necessary
}
[StructLayout(LayoutKind.Sequential)]
public struct STORAGE_DEVICE_DESCRIPTOR
{
ulong Version;
ulong Size;
byte DeviceType;
byte DeviceTypeModifier;
bool RemovableMedia;
bool CommandQueueing;
ulong ProductIdOffset;
ulong ProductRevisionOffset
ulong SerialNumberOffset;
STORAGE_BUS_TYPE BusType; device.
ulong RawPropertiesLength;
byte RawDeviceProperties;
}
[StructLayout(LayoutKind.Sequential)]
public struct STORAGE_ADAPTER_DESCRIPTOR
{
public uint Version;
public uint Size;
public uint MaximumTransferLength;
public uint MaximumPhysicalPages;
public uint AlignmentMask;
public bool AdapterUsesPio;
public bool AdapterScansDown;
public bool CommandQueueing;
public bool AcceleratedTransfer;
public byte BusType;
public ushort BusMajorVersion;
public ushort BusMinorVersion;
}
[StructLayout(LayoutKind.Sequential)]
public struct DRIVE_LAYOUT_INFORMATION
{
public uint PartitionCount;
public uint Signature;
public PARTITION_INFORMATION PartitionEntry;
}
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public extern static bool DeviceIoControl(IntPtr hDevice,
uint IoControlCode,
IntPtr lpInBuffer,
int InBufferSize,
IntPtr lpOutBuffer,
int OutBufferSize,
ref int lpBytesReturned,
IntPtr lpOverlapped);
STORAGE_PROPERTY_QUERY query = new STORAGE_PROPERTY_QUERY();
query.PropertyId = STORAGE_PROPERTY_ID.StorageDeviceProperty;
query.QueryType = STORAGE_QUERY_TYPE.PropertyStandardQuery;
query.AdditionalParameters = new byte[1];
int returnedLength = 0;
int nPtrQryBytes = Marshal.SizeOf(query);
IntPtr ptrQry = Marshal.AllocHGlobal(nPtrQryBytes);
STORAGE_DEVICE_DESCRIPTOR device = new STORAGE_DEVICE_DESCRIPTOR();
int nDevicePtrBytes = Marshal.SizeOf(device);
IntPtr ptrDevice = Marshal.AllocHGlobal(nDevicePtrBytes);
bool status = IOWrap.DeviceIoControl(hDevice, IOWrap.IOCTL_STORAGE_QUERY_PROPERTY,
ptrQry, nPtrQryBytes,
ptrDevice, 512, //nDevicePtrBytes,
ref returnedLength,
IntPtr.Zero);
string errMsg = new Win32Exception(Marshal.GetLastWin32Error()).Message;
// this errMsg says "The operation completed successfully" HOWEVER, the value for returnedLength is 0 and the ptrDevice buffer has not been populated
STORAGE_PROPERTY_QUERY query = new STORAGE_PROPERTY_QUERY();
query.PropertyId = STORAGE_PROPERTY_ID.StorageAdapterProperty;
query.QueryType = STORAGE_QUERY_TYPE.PropertyStandardQuery;
query.AdditionalParameters = new byte[1];
// create ptr to query for DeviceIoControl
int nPtrQryBytes = Marshal.SizeOf(query);
IntPtr ptrQuery = Marshal.AllocHGlobal(nPtrQryBytes);
STORAGE_ADAPTER_DESCRIPTOR adpDesc = new STORAGE_ADAPTER_DESCRIPTOR();
int nAdpDescBytes = Marshal.SizeOf(adpDesc);
IntPtr ptrAdpDesc = Marshal.AllocHGlobal(nAdpDescBytes);
status = IOWrap.DeviceIoControl(hDevice,
IOWrap.IOCTL_STORAGE_QUERY_PROPERTY, ptrQuery,
nPtrQryBytes,
ptrAdpDesc, 512,
ref returnedLen, I
ntPtr.Zero);
string errMsg = new Win32Exception(Marshal.GetLastWin32Error()).Message;
// note this call returns the following error - "An attempt was made to reference a token that does not exist"
// This following call works successfully every time
IOWrap.DISK_GEOMETRY diskGeometry = new IOWrap.DISK_GEOMETRY();
int nBytes = Marshal.SizeOf(diskGeometry);
IntPtr pDiskGeometry = Marshal.AllocHGlobal(nBytes);
status = IOWrap.DeviceIoControl(hDevice, (uint)IOWrap.EIOControlCode.DiskGetDriveGeometry,
IntPtr.Zero, 0,
pDiskGeometry, nBytes,
ref returnedLength, IntPtr.Zero);
IOWrap.DRIVE_LAYOUT_INFORMATION layoutInfo = new IOWrap.DRIVE_LAYOUT_INFORMATION();
nBytes = Marshal.SizeOf(layoutInfo);
IntPtr pLayoutInfo = Marshal.AllocHGlobal(nBytes);
returnedLength = 0;
status = IOWrap.DeviceIoControl(hDevice, (uint)IOWrap.EIOControlCode.DiskGetDriveLayout,
IntPtr.Zero, 0,
pLayoutInfo, 512,
ref returnedLength,
IntPtr.Zero);
// the following call sometimes works and sometimes throws an OutOfMemory Exception
IOWrap.DRIVE_LAYOUT_INFORMATION layoutInfo = new IOWrap.DRIVE_LAYOUT_INFORMATION();
nBytes = Marshal.SizeOf(layoutInfo);
IntPtr pLayoutInfo = Marshal.AllocHGlobal(nBytes);
returnedLength = 0;
status = IOWrap.DeviceIoControl(hDevice, (uint)IOWrap.EIOControlCode.DiskGetDriveLayout,
IntPtr.Zero, 0,
pLayoutInfo, 512,
ref returnedLength,
IntPtr.Zero);
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
by: TheLearnedOnePosted on 2009-08-30 at 07:49:19ID: 25217840
Rather than use Win32 API calls that need to be marshalled, there might be an easier way to approach your problem with native C# code, but that would require understanding what the code is doing.