[StructLayout(LayoutKind.Sequential)]
struct STORAGE_DEVICE_NUMBER
{
public int DeviceType;
public int DeviceNumber;
public int PartitionNumber;
}
Structure STORAGE_DEVICE_NUMBER
Public TODO
End Structure
None.
When used with a drive letter, the path should not have a trailing backslash ("\\.\C:")
public const uint OPEN_EXISTING = 3;
public const uint INVALID_HANDLE_VALUE = 0;
public const int IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x2D1080;
/// <summary>
/// Win32 CreateFile function, look for complete information at Platform SDK
/// </summary>
/// <param name="FileName">In order to read CD data FileName must be "\\.\\D:" where D is the CDROM drive letter</param>
/// <param name="DesiredAccess">Must be GENERIC_READ for CDROMs others access flags are not important in this case</param>
/// <param name="ShareMode">O means exlusive access, FILE_SHARE_READ allow open the CDROM</param>
/// <param name="lpSecurityAttributes">See Platform SDK documentation for details. NULL pointer could be enough</param>
/// <param name="CreationDisposition">Must be OPEN_EXISTING for CDROM drives</param>
/// <param name="dwFlagsAndAttributes">0 in fine for this case</param>
/// <param name="hTemplateFile">NULL handle in this case</param>
/// <returns>INVALID_HANDLE_VALUE on error or the handle to file if success</returns>
[System.Runtime.InteropServices.DllImport("Kernel32.dll", SetLastError = true)]
public extern static IntPtr CreateFile(string FileName, uint DesiredAccess,
uint ShareMode, IntPtr lpSecurityAttributes,
uint CreationDisposition, uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
/// <summary>
/// The CloseHandle function closes an open object handle.
/// </summary>
/// <param name="hObject">Handle to an open object.</param>
/// <returns>If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError.</returns>
[System.Runtime.InteropServices.DllImport("Kernel32.dll", SetLastError = true)]
public extern static int CloseHandle(IntPtr hObject);
[System.Runtime.InteropServices.DllImport("Kernel32.dll", SetLastError = true)]
public extern static bool DeviceIoControl(IntPtr hDevice, uint IoControlCode,
IntPtr InMediaRemoval, uint InBufferSize,
IntPtr OutBuffer, int OutBufferSize,
out int BytesReturned,
IntPtr Overlapped);
// return a unique device number for the given device path
int GetDeviceNumber(string DevicePath)
{
int ans = -1;
IntPtr h = CreateFile(DevicePath.TrimEnd('\\'), 0, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
if (h.ToInt32() != INVALID_HANDLE_VALUE)
{
int requiredSize;
STORAGE_DEVICE_NUMBER Sdn = new STORAGE_DEVICE_NUMBER();
int nBytes = Marshal.SizeOf(Sdn);
IntPtr ptrSdn = Marshal.AllocHGlobal(nBytes);
if (DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, IntPtr.Zero, 0, ptrSdn, nBytes, out requiredSize, IntPtr.Zero))
{
Sdn = (STORAGE_DEVICE_NUMBER)Marshal.PtrToStructure(ptrSdn, typeof(STORAGE_DEVICE_NUMBER));
// just my way of combining the relevant parts of the
// STORAGE_DEVICE_NUMBER into a single number
ans = (Sdn.DeviceType << 8) + Sdn.DeviceNumber;
}
Marshal.FreeHGlobal(ptrSdn);
CloseHandle(h);
}
return ans;
}