DeviceIOControl
我遇到了一些问题。我正在尝试从物理驱动器读取磁盘几何,但从未设置输出缓冲区。
以下是我的代码示例,这是一个简单的函数,可以获取磁盘几何结构并返回磁盘是否可移动:
public static bool IsDeviceRemovable(int DriveNo) {
string Filename=@"\\.\Physicaldrive"+DriveNo;
SafeFileHandle drive=CreateFile(
Filename,
FileAccess_e.None,
FileShare_e.Write|FileShare_e.Read,
IntPtr.Zero,
CreationDisposition_e.OpenExisting,
FileAttributes_e.None,
IntPtr.Zero
);
if(drive.IsInvalid) {
throw new IOException("Unable to access drive. Win32 Error Code: "+Marshal.GetLastWin32Error());
}
uint bytesReturned=0;
DISK_GEOMETRY dg=new DISK_GEOMETRY();
if(!DeviceIoControl(
drive,
IOControlCode_e.DiskGetDriveGeometry,
IntPtr.Zero,
0,
dg,
(uint)Marshal.SizeOf(dg),
ref bytesReturned,
IntPtr.Zero
)) {
throw new Exception("Unable to get properties from device. Win32 Error Code: "+Marshal.GetLastWin32Error());
}
drive.Close();
return dg.MediaType==MEDIA_TYPE.RemovableMedia;
}
以及一些数据结构:
[DllImport("Kernel32.dll", SetLastError=false, CharSet=CharSet.Auto)]
private static extern bool DeviceIoControl(
SafeFileHandle hDevice,
IOControlCode_e IoControlCode,
[MarshalAs(UnmanagedType.AsAny)]
[In] object InBuffer,
uint nInBufferSize,
[MarshalAs(UnmanagedType.AsAny)]
[Out] object OutBuffer,
uint nOutBufferSize,
ref uint pBytesReturned,
IntPtr Overlapped
);
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
private static extern SafeFileHandle CreateFile(
string lpFileName,
FileAccess_e dwDesiredAccess,
FileShare_e dwShareMode,
IntPtr lpSecurityAttributes,
CreationDisposition_e dwCreationDisposition,
FileAttributes_e dwFlagsAndAttributes,
IntPtr hTemplateFile
);
private enum MEDIA_TYPE {
Unknown=0x00,
F5_1Pt2_512=0x01,
F3_1Pt44_512=0x02,
F3_2Pt88_512=0x03,
F3_20Pt8_512=0x04,
F3_720_512=0x05,
F5_360_512=0x06,
F5_320_512=0x07,
F5_320_1024=0x08,
F5_180_512=0x09,
F5_160_512=0x0a,
RemovableMedia=0x0b,
FixedMedia=0x0c,
F3_120M_512=0x0d,
F3_640_512=0x0e,
F5_640_512=0x0f,
F5_720_512=0x10,
F3_1Pt2_512=0x11,
F3_1Pt23_1024=0x12,
F5_1Pt23_1024=0x13,
F3_128Mb_512=0x14,
F3_230Mb_512=0x15,
F8_256_128=0x16,
F3_200Mb_512=0x17,
F3_240M_512=0x18,
F3_32M_512=0x19
}
[StructLayout(LayoutKind.Sequential)]
private struct DISK_GEOMETRY {
public Int64 Cylinders;
public MEDIA_TYPE MediaType;
public Int32 TracksPerCylinder;
public Int32 SectorsPerTrack;
public Int32 BytesPerSector;
}
我从
获得的枚举 bytesReturned
变量已设置(在本例中为24),但dg
变量全为零。
我尝试了DeviceIoControl
的其他几个函数,结果相同:bytesReturned
已设置,但输出缓冲区全为零。
我的测试环境
答案 0 :(得分:3)
DISK_GEOMETRY声明是问题所在。它被封送为一个对象,但它被声明为一个结构。这意味着它将装箱,只有盒装副本将通过pinvoke调用更新。您正在读取原始值,因此全部为零。
简单的解决方法是将其声明为类而不是结构。