2011-03-31 119 views
4

我試圖在Windows 7上從CDROM驅動器的盤符中查找物理驅動器號(例如,我需要N\\.\PhysicalDriveN中打開塊設備進行讀取)。This page指示IOCTL_STORAGE_GET_DEVICE_NUMBER應該起作用,但是C:和D:(其中D:是可移動驅動器)的驅動器編號返回0,所以不能正確。還建議使用IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,但在D:上會出現ERROR_INVALID_FUNCTION失敗。如何從Windows 7的驅動器號中獲取可移動設備的物理驅動器號?

我不禁感到我錯過了某個關鍵概念。

這裏是我的代碼:

#include "stdafx.h" 
#include "Windows.h" 


void printLastError(){ 
    DWORD lastError; 
    DWORD bytesReturned; 
    WCHAR outbuf[2048]; 

    lastError = GetLastError(); 

    bytesReturned = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 
    NULL, lastError, LANG_USER_DEFAULT, outbuf, 2048, NULL); 

    if (bytesReturned > 0){ 
    wprintf(outbuf); 
    } else { 
    printf("Error %d while formatting error %d\n", GetLastError(),  lastError); 
    } 
} 

void readDeviceNumberByExtents(HANDLE hFile){ 
    BOOL ioctlSuccess; 
    DWORD bytesReturned; 

    VOLUME_DISK_EXTENTS vde; 

    ioctlSuccess = DeviceIoControl(hFile, 
    IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, 
    NULL, 0, &vde, sizeof(vde), &bytesReturned, NULL); 

    if (ioctlSuccess != 0){ 
     printf("%d\n", vde.Extents->DiskNumber); 
    } else { 
     printLastError(); 
    } 
} 

void readDeviceNumberByStorage(HANDLE hFile){ 
    BOOL ioctlSuccess; 
    DWORD bytesReturned; 

    STORAGE_DEVICE_NUMBER sdn; 

    ioctlSuccess = DeviceIoControl(hFile, 
    IOCTL_STORAGE_GET_DEVICE_NUMBER, 
    NULL, 0, &sdn, sizeof(sdn), &bytesReturned, NULL); 

    if (ioctlSuccess != 0){ 
    printf("%d\n", sdn.DeviceNumber); 
    } else { 
    printLastError(); 
    } 
} 

void runTest(WCHAR* driveName){ 
    HANDLE driveHandle; 
    DWORD diskNumber; 

    driveHandle = CreateFile(driveName, 
    0, 
    FILE_SHARE_READ | FILE_SHARE_WRITE, 
    NULL, 
    OPEN_EXISTING, 
    FILE_ATTRIBUTE_NORMAL, 
    NULL); 

    if (driveHandle != INVALID_HANDLE_VALUE){ 
    wprintf(L"Opened %s\n", driveName); 

    printf("Device number by extents: "); 
    readDeviceNumberByExtents(driveHandle); 
    printf("Device number by storage: "); 
    readDeviceNumberByStorage(driveHandle); 

    CloseHandle(driveHandle); 
    } else { 
    printf("Failure!\n"); 
    } 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    runTest(L"\\\\.\\C:"); 
    printf("\n"); 
    runTest(L"\\\\.\\D:"); 

    getc(stdin); 
    return 0; 
} 

...和輸出,當我運行它,無論是作爲管理員或不:

Opened \\.\C: 
Device number by extents: 0 
Device number by storage: 0 

Opened \\.\D: 
Device number by extents: Incorrect function. 
Device number by storage: 0 

回答

5

"\\.\PhysicalDriveN"僅適用於(東西像)硬盤,而不是可移動磁盤。如果某些行爲類似可移動磁盤(或軟盤,CD-ROM等),"\\.\X:"將打開原始驅動器(其他驅動器不支持分區,因此"\\.\x:""\\.\PhysicalDiskN"之間的區別對它們不存在)。您通常要使用GetDriveType來確定您擁有哪種磁盤,並且只有當您說明它是DRIVE_FIXED時,纔會嘗試查找驅動器編號並使用"\\.\PhysicalDriveN"

+0

啊,哈!這似乎是至關重要的概念:-) – regularfry 2011-03-31 16:37:47

+1

這是完全正確的,我需要原始訪問USB驅動器(這是可移動的類型),但打開\\。\ X:只給我的USB驅動器上的第一個分區 - 我正在尋找一種從X:\映射到\\。\ PhysicalDriveX的方式,並且看起來像這是否正常工作,這是我的答案 – 2011-08-18 09:50:16

+0

您可以告訴我你閱讀的源代碼是否爲\\。\ PhysicalDriveX創建的源代碼可卸除的設備?我建立在這個假設之上,現在我有一個錯誤,並且必須重新設計這部分軟件,因爲Windows似乎爲USB筆驅動創建了\\。\ PhysicalDriveX條目,並且在移除筆驅動時留下了編號方面的空白。 .. – Calmarius 2013-09-03 10:59:40

2

這是C#.NET代碼,但是這是我寫來完成這項工作:

using System.Management; //Add in a reference to this as well in the project settings 
public static string GetPhysicalDevicePath(char DriveLetter) 
{ 
    ManagementClass devs = new ManagementClass(@"Win32_Diskdrive"); 
    { 
     ManagementObjectCollection moc = devs.GetInstances(); 
     foreach(ManagementObject mo in moc) 
     { 
      foreach (ManagementObject b in mo.GetRelated("Win32_DiskPartition")) 
      { 
       foreach (ManagementBaseObject c in b.GetRelated("Win32_LogicalDisk")) 
       { 
        string DevName = string.Format("{0}", c["Name"]); 
        if (DevName[0] == DriveLetter) 
         return string.Format("{0}", mo["DeviceId"]); 
       } 
      } 
     } 
    } 
    return ""; 
} 
相關問題