获取关于Windows7 32位系统上磁盘驱动器的信息结果

3
当我在32位的Windows XP上运行以下代码时,我得到了以下结果。
我只插入了一个USB闪存驱动器。
On Windows XP - 32 Bit
-----------------------

Drive C:
    ProductId: ST3160215AS
    ProductRevision: 3.AAD
    DeviceType: 7, DeviceNumber: 0, PartitionNumber: 1
    DevicePath: \\?\ide#diskst3160215as_____________________________3.aad___#5&2
7db0ed4&0&0.0.0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: DiskDrive
    Hardware ID: IDE\DiskST3160215AS_____________________________3.AAD___
    Friendly Name: ST3160215AS
    Physical Device Object Name: \Device\Ide\IdeDeviceP2T0L0-5
    Device Description: Disk drive
    Parent Device Instance ID: PCIIDE\IDECHANNEL\4&1C1E8A11&0&0
    Parent of Parent Device Instance ID: PCI\VEN_8086&DEV_27C0&SUBSYS_72671462&R
EV_01\3&11583659&0&FA
    DeviceInstanceId: IDE\DISKST3160215AS_____________________________3.AAD___\5
&27DB0ED4&0&0.0.0
Drive D:
    ProductId: ST3160215AS
    ProductRevision: 3.AAD
    DeviceType: 7, DeviceNumber: 0, PartitionNumber: 2
    DevicePath: \\?\ide#diskst3160215as_____________________________3.aad___#5&2
7db0ed4&0&0.0.0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: DiskDrive
    Hardware ID: IDE\DiskST3160215AS_____________________________3.AAD___
    Friendly Name: ST3160215AS
    Physical Device Object Name: \Device\Ide\IdeDeviceP2T0L0-5
    Device Description: Disk drive
    Parent Device Instance ID: PCIIDE\IDECHANNEL\4&1C1E8A11&0&0
    Parent of Parent Device Instance ID: PCI\VEN_8086&DEV_27C0&SUBSYS_72671462&R
EV_01\3&11583659&0&FA
    DeviceInstanceId: IDE\DISKST3160215AS_____________________________3.AAD___\5
&27DB0ED4&0&0.0.0
Drive E:
    ProductId: ST3160215AS
    ProductRevision: 3.AAD
    DeviceType: 7, DeviceNumber: 0, PartitionNumber: 3
    DevicePath: \\?\ide#diskst3160215as_____________________________3.aad___#5&2
7db0ed4&0&0.0.0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: DiskDrive
    Hardware ID: IDE\DiskST3160215AS_____________________________3.AAD___
    Friendly Name: ST3160215AS
    Physical Device Object Name: \Device\Ide\IdeDeviceP2T0L0-5
    Device Description: Disk drive
    Parent Device Instance ID: PCIIDE\IDECHANNEL\4&1C1E8A11&0&0
    Parent of Parent Device Instance ID: PCI\VEN_8086&DEV_27C0&SUBSYS_72671462&R
EV_01\3&11583659&0&FA
    DeviceInstanceId: IDE\DISKST3160215AS_____________________________3.AAD___\5
&27DB0ED4&0&0.0.0
Drive F:
    ProductId: ST3160215AS
    ProductRevision: 3.AAD
    DeviceType: 7, DeviceNumber: 0, PartitionNumber: 4
    DevicePath: \\?\ide#diskst3160215as_____________________________3.aad___#5&2
7db0ed4&0&0.0.0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: DiskDrive
    Hardware ID: IDE\DiskST3160215AS_____________________________3.AAD___
    Friendly Name: ST3160215AS
    Physical Device Object Name: \Device\Ide\IdeDeviceP2T0L0-5
    Device Description: Disk drive
    Parent Device Instance ID: PCIIDE\IDECHANNEL\4&1C1E8A11&0&0
    Parent of Parent Device Instance ID: PCI\VEN_8086&DEV_27C0&SUBSYS_72671462&R
EV_01\3&11583659&0&FA
    DeviceInstanceId: IDE\DISKST3160215AS_____________________________3.AAD___\5
&27DB0ED4&0&0.0.0
Drive G:
    VendorId: JetFlash
    ProductId: Transcend 2GB
    ProductRevision: 8.07
    DeviceType: 7, DeviceNumber: 1, PartitionNumber: 1
    DevicePath: \\?\usbstor#disk&ven_jetflash&prod_transcend_2gb&rev_8.07#e3o29u
13&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: DiskDrive
    Hardware ID: USBSTOR\DiskJetFlashTranscend_2GB___8.07
    Friendly Name: JetFlash Transcend 2GB USB Device
    Physical Device Object Name: \Device\00000080
    Device Description: Disk drive
    Parent Device Instance ID: USB\VID_058F&PID_6387\E3O29U13
    Parent of Parent Device Instance ID: USB\ROOT_HUB20\4&2B6971CE&0
    DeviceInstanceId: USBSTOR\DISK&VEN_JETFLASH&PROD_TRANSCEND_2GB&REV_8.07\E3O2
9U13&0
    Drive G: is removeable
Drive X:

When i run the below code on windows7 - 32 , i get the below result

i have plugged the same usb pen drive which is used on windows xp - 32 bit...

On Windows 7 - 32 Bit
-----------------------

Drive C:
    ProductId: Hitachi HDS721616PLA380
    ProductRevision: P22OAB3A
    DeviceType: 7, DeviceNumber: 0, PartitionNumber: 2
    DevicePath: \\?\ide#diskhitachi_hds721616pla380_________________p22oab3a#5&4
be38f&0&0.0.0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: DiskDrive
    Hardware ID: USBSTOR\DiskJetFlashTranscend_2GB___8.07
    Friendly Name: JetFlash Transcend 2GB USB Device
    Physical Device Object Name: \Device\0000006f
    Device Description: Disk drive
    Parent Device Instance ID: USB\VID_058F&PID_6387\E3O29U13
    Parent of Parent Device Instance ID: USB\ROOT_HUB20\4&4E31217&0
    DeviceInstanceId: USBSTOR\DISK&VEN_JETFLASH&PROD_TRANSCEND_2GB&REV_8.07\E3O2
9U13&0
    Drive C: is removeable
Drive D:
    ProductId: Hitachi HDS721616PLA380
    ProductRevision: P22OAB3A
    DeviceType: 7, DeviceNumber: 0, PartitionNumber: 3
    DevicePath: \\?\ide#diskhitachi_hds721616pla380_________________p22oab3a#5&4
be38f&0&0.0.0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: DiskDrive
    Hardware ID: USBSTOR\DiskJetFlashTranscend_2GB___8.07
    Friendly Name: JetFlash Transcend 2GB USB Device
    Physical Device Object Name: \Device\0000006f
    Device Description: Disk drive
    Parent Device Instance ID: USB\VID_058F&PID_6387\E3O29U13
    Parent of Parent Device Instance ID: USB\ROOT_HUB20\4&4E31217&0
    DeviceInstanceId: USBSTOR\DISK&VEN_JETFLASH&PROD_TRANSCEND_2GB&REV_8.07\E3O2
9U13&0
    Drive D: is removeable
Drive E:
    ProductId: Hitachi HDS721616PLA380
    ProductRevision: P22OAB3A
    DeviceType: 7, DeviceNumber: 0, PartitionNumber: 4
    DevicePath: \\?\ide#diskhitachi_hds721616pla380_________________p22oab3a#5&4
be38f&0&0.0.0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: DiskDrive
    Hardware ID: USBSTOR\DiskJetFlashTranscend_2GB___8.07
    Friendly Name: JetFlash Transcend 2GB USB Device
    Physical Device Object Name: \Device\0000006f
    Device Description: Disk drive
    Parent Device Instance ID: USB\VID_058F&PID_6387\E3O29U13
    Parent of Parent Device Instance ID: USB\ROOT_HUB20\4&4E31217&0
    DeviceInstanceId: USBSTOR\DISK&VEN_JETFLASH&PROD_TRANSCEND_2GB&REV_8.07\E3O2
9U13&0
    Drive E: is removeable
Drive F:
    ProductId: Hitachi HDS721616PLA380
    ProductRevision: P22OAB3A
    DeviceType: 7, DeviceNumber: 0, PartitionNumber: 5
    DevicePath: \\?\ide#diskhitachi_hds721616pla380_________________p22oab3a#5&4
be38f&0&0.0.0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: DiskDrive
    Hardware ID: USBSTOR\DiskJetFlashTranscend_2GB___8.07
    Friendly Name: JetFlash Transcend 2GB USB Device
    Physical Device Object Name: \Device\0000006f
    Device Description: Disk drive
    Parent Device Instance ID: USB\VID_058F&PID_6387\E3O29U13
    Parent of Parent Device Instance ID: USB\ROOT_HUB20\4&4E31217&0
    DeviceInstanceId: USBSTOR\DISK&VEN_JETFLASH&PROD_TRANSCEND_2GB&REV_8.07\E3O2
9U13&0
    Drive F: is removeable
Drive G:
    VendorId: JetFlash
    ProductId: Transcend 2GB
    ProductRevision: 8.07
    DeviceType: 7, DeviceNumber: 1, PartitionNumber: 1
    DevicePath: \\?\usbstor#disk&ven_jetflash&prod_transcend_2gb&rev_8.07#e3o29u
13&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: DiskDrive
    Hardware ID: IDE\DiskHitachi_HDS721616PLA380_________________P22OAB3A
    Friendly Name: Hitachi HDS721616PLA380 ATA Device
    Physical Device Object Name: \Device\Ide\IdeDeviceP1T0L0-1
    Device Description: Disk drive
    Parent Device Instance ID: PCIIDE\IDECHANNEL\4&35CD87E&0&0
    Parent of Parent Device Instance ID: PCI\VEN_8086&DEV_27C0&SUBSYS_27C08086&R
EV_01\3&2411E6FE&1&FA
    DeviceInstanceId: IDE\DISKHITACHI_HDS721616PLA380_________________P22OAB3A\5
&4BE38F&0&0.0.0
    Drive G: is removeable
Drive Z:

块引用

---------------------------------------------------------------------------------

请看以下两个结果...

我在XP和Windows7系统上插入了同一个USB设备,但结果有所不同...

请检查两个操作系统上G驱动器的结果...

Drive G: ( On Windows 7 - 32 bit )
-----------------------------------

VendorId: JetFlash
    ProductId: Transcend 2GB
    ProductRevision: 8.07
    DeviceType: 7, DeviceNumber: 1, PartitionNumber: 1
    DevicePath: \\?\usbstor#disk&ven_jetflash&prod_transcend_2gb&rev_8.07#e3o29u
13&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: DiskDrive
    Hardware ID: IDE\DiskHitachi_HDS721616PLA380_________________P22OAB3A
    Friendly Name: Hitachi HDS721616PLA380 ATA Device
    Physical Device Object Name: \Device\Ide\IdeDeviceP1T0L0-1
    Device Description: Disk drive
    Parent Device Instance ID: PCIIDE\IDECHANNEL\4&35CD87E&0&0
    Parent of Parent Device Instance ID: PCI\VEN_8086&DEV_27C0&SUBSYS_27C08086&R
EV_01\3&2411E6FE&1&FA
    DeviceInstanceId: IDE\DISKHITACHI_HDS721616PLA380_________________P22OAB3A\5
&4BE38F&0&0.0.0
    Drive G: is removeable

Drive G: ( On Windows XP - 32 bit )
-----------------------------------
VendorId: JetFlash
    ProductId: Transcend 2GB
    ProductRevision: 8.07
    DeviceType: 7, DeviceNumber: 1, PartitionNumber: 1
    DevicePath: \\?\usbstor#disk&ven_jetflash&prod_transcend_2gb&rev_8.07#e3o29u
13&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: DiskDrive
    Hardware ID: USBSTOR\DiskJetFlashTranscend_2GB___8.07
    Friendly Name: JetFlash Transcend 2GB USB Device
    Physical Device Object Name: \Device\00000080
    Device Description: Disk drive
    Parent Device Instance ID: USB\VID_058F&PID_6387\E3O29U13
    Parent of Parent Device Instance ID: USB\ROOT_HUB20\4&2B6971CE&0
    DeviceInstanceId: USBSTOR\DISK&VEN_JETFLASH&PROD_TRANSCEND_2GB&REV_8.07\E3O2
9U13&0
    Drive G: is removeable

感谢您的帮助。
1个回答

26
我用C语言编写了一个程序,演示了如何接收所需的信息。
#include <windows.h>
#include <devguid.h>    // for GUID_DEVCLASS_CDROM etc
#include <setupapi.h>
#include <cfgmgr32.h>   // for MAX_DEVICE_ID_LEN, CM_Get_Parent and CM_Get_Device_ID
#include <tchar.h>
#include <stdio.h>

#define ARRAY_SIZE(arr)     (sizeof(arr)/sizeof(arr[0]))

#pragma comment (lib, "setupapi.lib")

//
// Define the various device characteristics flags (defined in wdm.h)
//
#define FILE_REMOVABLE_MEDIA                    0x00000001
#define FILE_READ_ONLY_DEVICE                   0x00000002
#define FILE_FLOPPY_DISKETTE                    0x00000004
#define FILE_WRITE_ONCE_MEDIA                   0x00000008
#define FILE_REMOTE_DEVICE                      0x00000010
#define FILE_DEVICE_IS_MOUNTED                  0x00000020
#define FILE_VIRTUAL_VOLUME                     0x00000040
#define FILE_AUTOGENERATED_DEVICE_NAME          0x00000080
#define FILE_DEVICE_SECURE_OPEN                 0x00000100
#define FILE_CHARACTERISTIC_PNP_DEVICE          0x00000800
#define FILE_CHARACTERISTIC_TS_DEVICE           0x00001000
#define FILE_CHARACTERISTIC_WEBDAV_DEVICE       0x00002000

#pragma warning (disable: 4201)
typedef struct _IO_STATUS_BLOCK {
    union {
        NTSTATUS Status;
        PVOID Pointer;
    } DUMMYUNIONNAME;

    ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
#pragma warning (default: 4201)

typedef enum _FSINFOCLASS {
    FileFsVolumeInformation       = 1,
    FileFsLabelInformation,      // 2
    FileFsSizeInformation,       // 3
    FileFsDeviceInformation,     // 4
    FileFsAttributeInformation,  // 5
    FileFsControlInformation,    // 6
    FileFsFullSizeInformation,   // 7
    FileFsObjectIdInformation,   // 8
    FileFsDriverPathInformation, // 9
    FileFsVolumeFlagsInformation,// 10
    FileFsMaximumInformation
} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;

typedef struct _FILE_FS_DEVICE_INFORMATION {
    DEVICE_TYPE DeviceType;
    ULONG Characteristics;
} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION;

typedef NTSTATUS (NTAPI *LPFN_NT_QUERY_VOLUME_INFORMATION_FILE) (HANDLE FileHandle,
                                                                 PIO_STATUS_BLOCK IoStatusBlock,
                                                                 PVOID FsInformation, ULONG Length,
                                                                 FS_INFORMATION_CLASS FsInformationClass);

BOOL GetDriveTypeAndCharacteristics (HANDLE hDevice, DEVICE_TYPE *pDeviceType, ULONG *pCharacteristics)
{
    HMODULE hNtDll;
    LPFN_NT_QUERY_VOLUME_INFORMATION_FILE lpfnNtQueryVolumeInformationFile;
    NTSTATUS ntStatus;
    IO_STATUS_BLOCK IoStatusBlock;
    FILE_FS_DEVICE_INFORMATION FileFsDeviceInfo;
    BOOL bSuccess = FALSE;

    hNtDll = GetModuleHandle (TEXT("ntdll.dll"));
    if (hNtDll == NULL)
        return FALSE;

    lpfnNtQueryVolumeInformationFile = (LPFN_NT_QUERY_VOLUME_INFORMATION_FILE)GetProcAddress (hNtDll, "NtQueryVolumeInformationFile");
    if (lpfnNtQueryVolumeInformationFile == NULL)
        return FALSE;

    ntStatus = lpfnNtQueryVolumeInformationFile (hDevice, &IoStatusBlock,
                                                 &FileFsDeviceInfo, sizeof(FileFsDeviceInfo),
                                                 FileFsDeviceInformation);
    if (ntStatus == NO_ERROR) {
        bSuccess = TRUE;
        *pDeviceType = FileFsDeviceInfo.DeviceType;
        *pCharacteristics = FileFsDeviceInfo.Characteristics;
    }

    return bSuccess;
}

void FildVolumeName (LPCTSTR pszDeviceName)
{
    TCHAR szVolumeName[MAX_PATH] = TEXT("");
    TCHAR szDeviceName[MAX_PATH] = TEXT("");
    HANDLE hFind = INVALID_HANDLE_VALUE;
    DWORD dwCharCount;
    BOOL bSuccess;

    hFind = FindFirstVolume (szVolumeName, ARRAYSIZE(szVolumeName));
    if (hFind == INVALID_HANDLE_VALUE) return;

    while(TRUE) {
        //  Skip the \\?\ prefix and remove the trailing backslash.
        size_t Index = lstrlen(szVolumeName) - 1;
        if (szVolumeName[0]     != TEXT('\\') ||
            szVolumeName[1]     != TEXT('\\') ||
            szVolumeName[2]     != TEXT('?')  ||
            szVolumeName[3]     != TEXT('\\') ||
            szVolumeName[Index] != TEXT('\\')) return; // error

        //  QueryDosDeviceW doesn't allow a trailing backslash,
        //  so temporarily remove it.
        szVolumeName[Index] = TEXT('\0');
        dwCharCount = QueryDosDevice (&szVolumeName[4], szDeviceName, ARRAYSIZE(szDeviceName));
        szVolumeName[Index] = TEXT('\\');
        if (dwCharCount == 0) return; // error

        if (lstrcmp (pszDeviceName, szDeviceName) == 0) {
            _tprintf (TEXT("    Volume Device Name: %s\n"), szVolumeName);
            return;
        }

        bSuccess = FindNextVolume (hFind, szVolumeName, ARRAYSIZE(szVolumeName));
        if (!bSuccess) {
            DWORD dwErrorCode = GetLastError();
            if (dwErrorCode == ERROR_NO_MORE_ITEMS)
                break;
            else 
                break;  // ERROR!!!
        }
    }
}

void DumpVidPidMi (LPCTSTR pszDeviceInstanceId)
{
    TCHAR szDeviceInstanceId[MAX_DEVICE_ID_LEN];
    const static LPCTSTR arPrefix[3] = {TEXT("VID_"), TEXT("PID_"), TEXT("MI_")};
    LPTSTR pszToken, pszNextToken;
    int j;

    lstrcpy (szDeviceInstanceId, pszDeviceInstanceId);

    pszToken = _tcstok_s (szDeviceInstanceId , TEXT("\\#&"), &pszNextToken);
    while(pszToken != NULL) {
        for (j = 0; j < 3; j++) {
            if (_tcsncmp(pszToken, arPrefix[j], lstrlen(arPrefix[j])) == 0) {
                switch(j) {
                    case 0:
                        _tprintf (TEXT("        vid: \"%s\"\n"), pszToken + lstrlen(arPrefix[j]));
                        break;
                    case 1:
                        _tprintf (TEXT("        pid: \"%s\"\n"), pszToken + lstrlen(arPrefix[j]));
                        break;
                    case 2:
                        _tprintf (TEXT("        mi: \"%s\"\n"), pszToken + lstrlen(arPrefix[j]));
                        break;
                    default:
                        break;
                }
            }
        }
        pszToken = _tcstok_s (NULL, TEXT("\\#&"), &pszNextToken);
    }
}

BOOL FindDiInfos (LPCGUID pGuidInferface, LPCGUID pGuidClass, LPCTSTR pszEnumerator,
                  DEVICE_TYPE DeviceType, DWORD DeviceNumber,
                  DWORD dwDeviceInstanceIdSize,     // MAX_DEVICE_ID_LEN
                  OUT LPTSTR pszDeviceInstanceId,
                  OUT PDWORD pdwRemovalPolicy)
//#define CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL             1
//#define CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL        2
//#define CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL       3
{
    HDEVINFO hIntDevInfo = NULL;
    DWORD dwIndex;
    BOOL bFound = FALSE; 
    HANDLE hDev = INVALID_HANDLE_VALUE;
    PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;

    // set defaults
    *pdwRemovalPolicy = 0;
    pszDeviceInstanceId[0] = TEXT('\0');

    __try {
        hIntDevInfo = SetupDiGetClassDevs (pGuidInferface, pszEnumerator, NULL,
                                           pGuidInferface != NULL? DIGCF_PRESENT | DIGCF_DEVICEINTERFACE:
                                                                   DIGCF_ALLCLASSES | DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
        if (hIntDevInfo == INVALID_HANDLE_VALUE)
            __leave;

        for (dwIndex = 0; ;dwIndex ++) {
            SP_DEVICE_INTERFACE_DATA interfaceData;
            SP_DEVINFO_DATA deviceInfoData;
            DWORD dwDataType, dwRequiredSize;
            BOOL bSuccess;

            ZeroMemory (&interfaceData, sizeof(interfaceData));
            interfaceData.cbSize = sizeof(interfaceData);
            bSuccess = SetupDiEnumDeviceInterfaces (hIntDevInfo, NULL, pGuidInferface, dwIndex, &interfaceData);
            if (!bSuccess) {
                DWORD dwErrorCode = GetLastError();
                if (dwErrorCode == ERROR_NO_MORE_ITEMS)
                    break;
                else 
                    break;  // ERROR!!!
            }

            dwRequiredSize = 0;
            bSuccess = SetupDiGetDeviceInterfaceDetail (hIntDevInfo, &interfaceData, NULL, 0, &dwRequiredSize, NULL);
            if ((!bSuccess && GetLastError() != ERROR_INSUFFICIENT_BUFFER) || dwRequiredSize == 0)
                continue;  // ERROR!!!

            if (pInterfaceDetailData)
                pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) LocalFree (pInterfaceDetailData);

            pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) LocalAlloc (LPTR, dwRequiredSize);
            pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
            ZeroMemory (&deviceInfoData, sizeof(deviceInfoData));
            deviceInfoData.cbSize = sizeof(deviceInfoData);
            bSuccess = SetupDiGetDeviceInterfaceDetail (hIntDevInfo, &interfaceData,
                                                        pInterfaceDetailData, dwRequiredSize, &dwRequiredSize, &deviceInfoData);
            if (!bSuccess)
                continue;

            hDev = CreateFile (pInterfaceDetailData->DevicePath, 
                               0,                                   // no access to the drive
                               FILE_SHARE_READ | FILE_SHARE_WRITE,  // share mode
                               NULL,                                // default security attributes
                               OPEN_EXISTING,                       // disposition
                               0,                                   // file attributes
                               NULL);                               // do not copy file attributes
            if (hDev != INVALID_HANDLE_VALUE) {
                STORAGE_DEVICE_NUMBER sdn;
                DWORD cbBytesReturned;
                bSuccess = DeviceIoControl (hDev,                           // device to be queried
                                            IOCTL_STORAGE_GET_DEVICE_NUMBER, 
                                            NULL, 0,                        // no input buffer
                                            (LPVOID)&sdn, sizeof(sdn),      // output buffer
                                            &cbBytesReturned,               // # bytes returned
                                            (LPOVERLAPPED) NULL);           // synchronous I/O
                if (bSuccess) {
                    if (sdn.DeviceType == DeviceType &&
                        sdn.DeviceNumber == DeviceNumber) {

                        DEVINST dnDevInstParent, dnDevInstParentParent;
                        CONFIGRET ret;
                        // device found !!!
                        TCHAR szBuffer[4096];

                        _tprintf (TEXT("    DevicePath: %s\n"), pInterfaceDetailData->DevicePath);

                        bSuccess = SetupDiGetDeviceInstanceId (hIntDevInfo, &deviceInfoData, pszDeviceInstanceId,
                                                               dwDeviceInstanceIdSize, &dwRequiredSize);
                        if (dwRequiredSize > MAX_DEVICE_ID_LEN)
                            continue;

                        bSuccess = SetupDiGetDeviceRegistryProperty (hIntDevInfo, &deviceInfoData, SPDRP_REMOVAL_POLICY, &dwDataType,
                                                                     (PBYTE)pdwRemovalPolicy, sizeof(DWORD), &dwRequiredSize);
                        // SPDRP_CHARACTERISTICS - Device characteristics
                        //         FILE_FLOPPY_DISKETTE, FILE_REMOVABLE_MEDIA, and FILE_WRITE_ONCE_MEDIA characteristics 
                        //         FILE_READ_ONLY_DEVICE
                        bSuccess = SetupDiGetDeviceRegistryProperty (hIntDevInfo, &deviceInfoData, SPDRP_CLASS, &dwDataType,
                                                                     (PBYTE)szBuffer, sizeof(szBuffer), &dwRequiredSize);
                        if (bSuccess)
                            _tprintf (TEXT("    Class: \"%s\"\n"), szBuffer);
                        bSuccess = SetupDiGetDeviceRegistryProperty (hIntDevInfo, &deviceInfoData, SPDRP_HARDWAREID, &dwDataType,
                                                                     (PBYTE)szBuffer, sizeof(szBuffer), &dwRequiredSize);
                        if (bSuccess) {
                            LPCTSTR pszId;
                            _tprintf (TEXT("    Hardware IDs:\n"));
                            for (pszId=szBuffer;
                                 *pszId != TEXT('\0') && pszId + dwRequiredSize/sizeof(TCHAR) <= szBuffer + ARRAYSIZE(szBuffer);
                                 pszId += lstrlen(pszId)+1) {

                                _tprintf (TEXT("        \"%s\"\n"), pszId);
                            }
                        }
                        bSuccess = SetupDiGetDeviceRegistryProperty (hIntDevInfo, &deviceInfoData, SPDRP_FRIENDLYNAME, &dwDataType,
                                                                     (PBYTE)szBuffer, sizeof(szBuffer), &dwRequiredSize);
                        if (bSuccess)
                            _tprintf (TEXT("    Friendly Name: \"%s\"\n"), szBuffer);

                        bSuccess = SetupDiGetDeviceRegistryProperty (hIntDevInfo, &deviceInfoData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, &dwDataType,
                                                                     (PBYTE)szBuffer, sizeof(szBuffer), &dwRequiredSize);
                        if (bSuccess)
                            _tprintf (TEXT("    Physical Device Object Name: \"%s\"\n"), szBuffer);

                        bSuccess = SetupDiGetDeviceRegistryProperty (hIntDevInfo, &deviceInfoData, SPDRP_DEVICEDESC, &dwDataType,
                                                                     (PBYTE)szBuffer, sizeof(szBuffer), &dwRequiredSize);
                        if (bSuccess)
                            _tprintf (TEXT("    Device Description: \"%s\"\n"), szBuffer);
                        bFound = TRUE;

                        ret = CM_Get_Parent (&dnDevInstParent, deviceInfoData.DevInst, 0);
                        if (ret == CR_SUCCESS) {
                            TCHAR szDeviceInstanceID[MAX_DEVICE_ID_LEN];
                            ret = CM_Get_Device_ID (dnDevInstParent, szDeviceInstanceID, ARRAY_SIZE(szDeviceInstanceID), 0);
                            if (ret == CR_SUCCESS) {
                                _tprintf (TEXT("    Parent Device Instance ID: %s\n"), szDeviceInstanceID);
                                DumpVidPidMi (szDeviceInstanceID);
                                ret = CM_Get_Parent (&dnDevInstParentParent, dnDevInstParent, 0);
                                if (ret == CR_SUCCESS) {
                                    ret = CM_Get_Device_ID (dnDevInstParentParent, szDeviceInstanceID, ARRAY_SIZE(szDeviceInstanceID), 0);
                                    if (ret == CR_SUCCESS)
                                        _tprintf (TEXT("    Parent of Parent Device Instance ID: %s\n"), szDeviceInstanceID);
                                }
                            }
                        }
                        break;
                    }
                }

                CloseHandle (hDev);
                hDev = INVALID_HANDLE_VALUE;
            }
        }
    }
    __finally {
        if (pInterfaceDetailData)
            pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) LocalFree (pInterfaceDetailData);

        if (hDev != INVALID_HANDLE_VALUE)
            CloseHandle (hDev);

        if (hIntDevInfo)
            SetupDiDestroyDeviceInfoList (hIntDevInfo);
    }

    return bFound;
}

LPCTSTR DumpBusTypeAsString (STORAGE_BUS_TYPE type)
{
    const static LPCTSTR arStorageBusTypeNames[] = {
        TEXT("Unknown"),                    // BusTypeUnknown = 0
        TEXT("SCSI"),                       // BusTypeScsi = 1
        TEXT("ATAPI"),                      // BusTypeAtapi = 2
        TEXT("ATA"),                        // BusTypeAta = 3
        TEXT("IEEE-1394"),                  // BusType1394 = 4
        TEXT("SSA"),                        // BusTypeSsa = 5
        TEXT("Fibre Channel"),              // BusTypeFibre = 6
        TEXT("USB"),                        // BusTypeUsb = 7
        TEXT("RAID"),                       // BusTypeRAID = 8
        TEXT("iSCSI"),                      // BusTypeiScsi = 9
        TEXT("Serial Attached SCSI (SAS)"), // BusTypeSas = 10
        TEXT("SATA"),                       // BusTypeSata = 11
        TEXT("SD"),                         // BusTypeSd = 12
        TEXT("MMC"),                        // BusTypeMmc = 13
        TEXT("Virtual"),                    // BusTypeVirtual = 14
        TEXT("FileBackedVirtual")           // BusTypeFileBackedVirtual = 15
    };

    if (type <= BusTypeFileBackedVirtual)
        return arStorageBusTypeNames[type];
    else
        return NULL;
}

int main()
{
    HANDLE hDevice; 
    DWORD cbBytesReturned;
    STORAGE_DEVICE_NUMBER sdn;
    BOOL bSuccess;
    LPTSTR pszLogicalDrives, pszDriveRoot;
    TCHAR szDeviceInstanceId[MAX_DEVICE_ID_LEN];
    GUID *pGuidInferface = NULL, *pGuidClass = NULL;
    LPCTSTR pszEnumerator = NULL;
    TCHAR szVolumeName[MAX_PATH+1], szFileSystemName[MAX_PATH+1], szNtDeviceName[MAX_PATH+1];
    //TCHAR szVolumeSerialNumber[1024];
    DWORD dwVolumeSerialNumber, dwMaximumComponentLength, dwFileSystemFlags;
    //HMODULE hm = LoadLibrary (TEXT("C:\\Program Files\\Microsoft Office\\Office14\\OUTLOOK.EXE"));

    __try {
        //pszEnumerator = TEXT("USB");

        cbBytesReturned = GetLogicalDriveStrings (0, NULL);
        pszLogicalDrives = (LPTSTR) LocalAlloc (LMEM_ZEROINIT,
                                                cbBytesReturned*sizeof(TCHAR));
        cbBytesReturned = GetLogicalDriveStrings (cbBytesReturned,
                                                  pszLogicalDrives);
        for (pszDriveRoot = pszLogicalDrives; *pszDriveRoot != TEXT('\0');
             pszDriveRoot += lstrlen(pszDriveRoot) + 1) {

            TCHAR szDeviceName[7] = TEXT("\\\\.\\");
            BOOL bIsRemoveable = FALSE;
            DWORD dwRemovalPolicy;
            STORAGE_PROPERTY_QUERY spq;
            BYTE byBuffer[4096];
            //ULONG ulOutBuffer;

            szDeviceName[4] = pszDriveRoot[0];
            szDeviceName[5] = TEXT(':');
            szDeviceName[6] = TEXT('\0');
            _tprintf (TEXT("Drive %c:\n"), pszDriveRoot[0]);

            // see http://msdn.microsoft.com/en-us/library/cc542456.aspx
            // how to find Volume name: \\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}\
            // for the Paths:  C:\
            // or device name like \Device\HarddiskVolume2 or \Device\CdRom0
            cbBytesReturned = QueryDosDevice (&szDeviceName[4], szNtDeviceName, ARRAYSIZE(szNtDeviceName));
            if (cbBytesReturned) {
                _tprintf (TEXT("    Dos Device Name: %s\n"), szNtDeviceName);
                FildVolumeName(szNtDeviceName);
            }

            bSuccess = GetVolumeInformation (pszDriveRoot, szVolumeName, ARRAYSIZE(szVolumeName),
                &dwVolumeSerialNumber, &dwMaximumComponentLength, &dwFileSystemFlags,
                szFileSystemName, ARRAYSIZE(szFileSystemName));
            if (bSuccess) {
                _tprintf (TEXT("    Volume Name: \"%s\"\n"), szVolumeName);
            }

            hDevice = CreateFile (szDeviceName,
                                  //FILE_READ_DATA, //0 - no access to the drive, for IOCTL_STORAGE_CHECK_VERIFY is FILE_READ_DATA needed
                                  FILE_READ_ATTRIBUTES, // for IOCTL_STORAGE_CHECK_VERIFY2
                                  FILE_SHARE_READ | FILE_SHARE_WRITE,   // share mode
                                  NULL, OPEN_EXISTING, 0, NULL);
            if (hDevice == INVALID_HANDLE_VALUE)
                __leave;

            bIsRemoveable = FALSE;

            spq.PropertyId = StorageDeviceProperty;
            spq.QueryType = PropertyStandardQuery;
            spq.AdditionalParameters[0] = 0;
            bSuccess = DeviceIoControl (hDevice,                         // device to be queried
                                        IOCTL_STORAGE_QUERY_PROPERTY,    // operation to perform
                                        &spq, sizeof(spq),               // input buffer
                                        &byBuffer, sizeof(byBuffer),     // output buffer
                                        &cbBytesReturned,                // # bytes returned
                                        (LPOVERLAPPED) NULL);            // synchronous I/O
            if (bSuccess) {
                STORAGE_DEVICE_DESCRIPTOR *psdp = (STORAGE_DEVICE_DESCRIPTOR *)byBuffer;
                LPCTSTR pszBusType = DumpBusTypeAsString(psdp->BusType);
                if (pszBusType)
                    _tprintf (TEXT("    Bus Type: %s\n"), pszBusType);
                else
                    _tprintf (TEXT("    Bus Type: Unknown (%d)\n"), psdp->BusType);
                if (psdp->VendorIdOffset)
                    _tprintf (TEXT("    VendorId: \"%hs\"\n"), (LPCSTR)((PBYTE)psdp + psdp->VendorIdOffset));
                if (psdp->ProductIdOffset)
                    _tprintf (TEXT("    ProductId: \"%hs\"\n"), (LPCSTR)((PBYTE)psdp + psdp->ProductIdOffset));
                if (psdp->ProductRevisionOffset)
                    _tprintf (TEXT("    ProductRevision: \"%hs\"\n"), (LPCSTR)((PBYTE)psdp + psdp->ProductRevisionOffset));

                if (psdp->RemovableMedia)
                    bIsRemoveable = TRUE;
            }

            cbBytesReturned = 0;
            bSuccess = DeviceIoControl (hDevice,                     // device to be queried
                                        IOCTL_STORAGE_CHECK_VERIFY2,
                                        NULL, 0,                     // no input buffer
                                        NULL, 0,                     // no output buffer
                                        &cbBytesReturned,            // # bytes returned
                                        (LPOVERLAPPED) NULL);        // synchronous I/O
            if (bSuccess)
                _tprintf (TEXT("    the device media are accessible\n"));
            else if (GetLastError() == ERROR_NOT_READY)
                _tprintf (TEXT("    the device media are not accessible\n"));

            bSuccess = DeviceIoControl (hDevice,                         // device to be queried
                                        IOCTL_STORAGE_GET_DEVICE_NUMBER, 
                                        NULL, 0,                         // no input buffer
                                        (LPVOID)&sdn, sizeof(sdn),       // output buffer
                                        &cbBytesReturned,                // # bytes returned
                                        (LPOVERLAPPED) NULL);            // synchronous I/O
            // GetLastError of ERROR_MORE_DATA indicates to the caller that the buffer was not large enough to accommodate the data requested
            if (!bSuccess) __leave;
            _tprintf (TEXT("    DeviceType: %d, DeviceNumber: %d, PartitionNumber: %d\n"), sdn.DeviceType, sdn.DeviceNumber, sdn.PartitionNumber);

            pGuidInferface = NULL;
            pGuidClass = NULL;
            if (sdn.DeviceType == FILE_DEVICE_CD_ROM || sdn.DeviceType == FILE_DEVICE_DVD) {
                pGuidInferface = (GUID*)&GUID_DEVINTERFACE_CDROM;
                pGuidClass = (GUID*)&GUID_DEVCLASS_CDROM;
            }
            else if (sdn.DeviceType == FILE_DEVICE_DISK) {
                DEVICE_TYPE DeviceType;
                ULONG ulCharacteristics;
                bSuccess = GetDriveTypeAndCharacteristics (hDevice, &DeviceType, &ulCharacteristics);
                if (bSuccess) {
                    if ((ulCharacteristics & FILE_FLOPPY_DISKETTE) == FILE_FLOPPY_DISKETTE) {
                        pGuidInferface = (GUID*)&GUID_DEVINTERFACE_FLOPPY;
                        pGuidClass = (GUID*)&GUID_DEVCLASS_FLOPPYDISK;
                    }
                    else {
                        pGuidInferface = (GUID*)&GUID_DEVINTERFACE_DISK;
                        pGuidClass = (GUID*)&GUID_DEVCLASS_DISKDRIVE;
                    }

                    if ((ulCharacteristics & FILE_REMOVABLE_MEDIA) == FILE_REMOVABLE_MEDIA)
                        bIsRemoveable = TRUE;
                }
            }
            // GUID_DEVCLASS_MEDIUM_CHANGER

            if (CloseHandle (hDevice))
                hDevice = INVALID_HANDLE_VALUE;

            bSuccess = FindDiInfos (pGuidInferface, pGuidClass, pszEnumerator, sdn.DeviceType, sdn.DeviceNumber,
                                    ARRAY_SIZE(szDeviceInstanceId),     // MAX_DEVICE_ID_LEN
                                    szDeviceInstanceId,
                                    &dwRemovalPolicy);
            if (bSuccess) {
                if (dwRemovalPolicy == CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL ||
                    dwRemovalPolicy == CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL)
                    bIsRemoveable = TRUE;
                _tprintf (TEXT("    DeviceInstanceId: %s\n"), szDeviceInstanceId);
                if (bIsRemoveable)
                    _tprintf (TEXT("    Drive %c: is removeable\n"), pszDriveRoot[0]);
            }
        }
    }
    __finally {
        if (pszLogicalDrives)
            pszLogicalDrives = (LPTSTR) LocalFree (pszLogicalDrives);
        if (hDevice != INVALID_HANDLE_VALUE)
            bSuccess = CloseHandle (hDevice);
    }

    return 0;
}

该程序可以在没有安装Windows DDK的情况下进行编译(只需要安装Windows SDK,例如与Visual Studio一起安装)。 该程序会生成以下输出:

....
Drive L:
    Dos Device Name: \Device\CdRom2
    Volume Device Name: \\?\Volume{2c5f6a93-2b50-11df-aa6a-005056c00008}\
    Volume Name: "SONYPICTUTIL"
    Bus Type: USB
    VendorId: "HL-DT-ST"
    ProductId: "DVDRAM GE20LU11 "
    ProductRevision: "CL01"
    the device media are accessible
    DeviceType: 2, DeviceNumber: 2, PartitionNumber: -1
    DevicePath: \\?\usbstor#cdrom&ven_hl-dt-st&prod_dvdram_ge20lu11&rev_cl01#0010101640008b615&0#{53f56308-b6bf-11d0-94f2-00a0c91efb8b}
    Class: "CDROM"
    Hardware IDs:
        "USBSTOR\CdRomHL-DT-STDVDRAM_GE20LU11_CL01"
        "USBSTOR\CdRomHL-DT-STDVDRAM_GE20LU11_"
        "USBSTOR\CdRomHL-DT-ST"
        "USBSTOR\HL-DT-STDVDRAM_GE20LU11_C"
        "HL-DT-STDVDRAM_GE20LU11_C"
        "USBSTOR\GenCdRom"
        "GenCdRom"
    Friendly Name: "HL-DT-ST DVDRAM GE20LU11 USB Device"
    Physical Device Object Name: "\Device\00000096"
    Device Description: "CD-ROM Drive"
    Parent Device Instance ID: USB\VID_152E&PID_1640\0010101640008B615
        vid: "152E"
        pid: "1640"
    Parent of Parent Device Instance ID: USB\ROOT_HUB20\4&29A1BD9B&0
    DeviceInstanceId: USBSTOR\CDROM&VEN_HL-DT-ST&PROD_DVDRAM_GE20LU11&REV_CL01\0010101640008B615&0
    Drive L: is removeable
Drive N:
    Dos Device Name: \Device\HarddiskVolume8
    Volume Device Name: \\?\Volume{ae08a3c8-71cf-11de-bc1d-005056c00008}\
    Volume Name: ""
    Bus Type: USB
    VendorId: "SanDisk "
    ProductId: "Cruzer          "
    ProductRevision: "8.01"
    the device media are accessible
    DeviceType: 7, DeviceNumber: 5, PartitionNumber: 1
    DevicePath: \\?\usbstor#disk&ven_sandisk&prod_cruzer&rev_8.01#1740030578903736&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
    Class: "DiskDrive"
    Hardware IDs:
        "USBSTOR\DiskSanDisk_Cruzer__________8.01"
        "USBSTOR\DiskSanDisk_Cruzer__________"
        "USBSTOR\DiskSanDisk_"
        "USBSTOR\SanDisk_Cruzer__________8"
        "SanDisk_Cruzer__________8"
        "USBSTOR\GenDisk"
        "GenDisk"
    Friendly Name: "SanDisk Cruzer USB Device"
    Physical Device Object Name: "\Device\000000aa"
    Device Description: "Disk drive"
    Parent Device Instance ID: USB\VID_0781&PID_5406\1740030578903736
        vid: "0781"
        pid: "5406"
    Parent of Parent Device Instance ID: USB\ROOT_HUB20\4&128079C2&0
    DeviceInstanceId: USBSTOR\DISK&VEN_SANDISK&PROD_CRUZER&REV_8.01\1740030578903736&0
    Drive N: is removeable

因为我们只对可以通过驱动器字母访问的设备感兴趣,所以该程序从使用GetLogicalDriveStrings函数枚举系统中所有逻辑驱动器开始。对于每个驱动器,我们可以使用IOCTL_STORAGE_QUERY_PROPERTY获取像VendorIdProductIdProductRevision这样的信息。使用IOCTL_STORAGE_GET_DEVICE_NUMBER可以使我们获取驱动器类型(如CD/DVD或Disk/Floppy)。此外,两个数字:DeviceTypeDeviceNumber在系统中是唯一的,我们可以使用它们作为查找驱动器的设备实例的基础(使用SetupDi-函数)。

由于软盘和硬盘设备具有相同的设备类型FILE_DEVICE_DISK,我演示了另一个函数NtQueryVolumeInformationFile,其中包含FileFsDeviceInformation参数,用于获取所谓的Characteristics。Characteristic是区分软盘和其他磁盘并选择相应的类和接口GUID进行设备枚举(GUID_DEVINTERFACE_FLOPPYGUID_DEVINTERFACE_DISK)的最佳方法。我们使用SetupDi API枚举所有设备的DeviceType和DeviceNumber。这样我们就可以找到每个设备所对应的驱动器字母。

还有一件重要的事情是设备的层次结构:父子关系。为了演示这一点,我在代码示例中使用CM_Get_ParentCM_Get_Device_ID函数。这样我们就可以看到哪个USB设备具有哪个存储设备作为子设备。

我显示了一些有关找到的设备的信息。如果需要,您可以将示例中的API与IOCTL_MOUNTMGR_QUERY_POINTS(请参见Using IOCTL_MOUNTMGR_QUERY_POINTS)或FindFirstVolumeWFindNextVolumeWGetVolumePathNamesForVolumeNameW(请参见http://msdn.microsoft.com/en-us/library/cc542456(VS.85).aspx)相结合,以获取更详细的信息。

更新:顺便提一下,IOCTL_STORAGE_QUERY_PROPERTY返回的缓冲区还有其他字段,如STORAGE_BUS_TYPE BusTypeBusTypeUsbBusTypeFibreBusTypeSd等)。您还可以使用IOCTL_STORAGE_QUERY_PROPERTY来获取其他信息,例如StorageDeviceUniqueIdPropertyStorageDeviceUniqueIdProperty等。如果您想获得更多关于USB的特定信息,我建议您参考http://www.emmet-gray.com/Articles/USB_SerialNumbers.htm,其中展示了如何使用IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EXIOCTL_USB_GET_NODE_INFORMATIONIOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION更新2:由于stackoverflow.com的消息大小限制,我将程序的扩展版本放在http://www.ok-soft-gmbh.com/ForStackOverflow/EnumMassStorage.c,测试输出如下http://www.ok-soft-gmbh.com/ForStackOverflow/EnumMassStorage.txt 更新3:我发现了一个错误并更新了代码。请使用最新版本的代码,并验证您的问题是否已解决。

请查看上面的帖子... 我已经在上面的帖子中粘贴了两个系统(XP和Windows 7)的结果... 我运行相同的代码,但是对于同一设备,我得到不同的输出... - user198725878
请尝试使用修复后的版本。我希望现在程序能够正确运行。 - Oleg
两个地方都有新代码:我的答案中的代码和http://www.ok-soft-gmbh.com/ForStackOverflow/EnumMassStorage.c中的代码。 - Oleg
如果卷是磁盘管理中的镜像或其他RAID阵列,则此代码无法正常工作。例如:我使用两个相同的虚拟硬盘设置了VirtualBox。然后我在第一个驱动器上安装了Windows 7。安装Windows 7后,我转到磁盘管理,将其转换为动态磁盘,然后将系统分区镜像到第二个驱动器。结果并不美观:Oleg网站发布的代码仅打印“卷名称”,没有更进一步。随后的CreateFile或IOCTL_STORAGE_QUERY_PROPERTY必须失败... - James Johnston
从逻辑上讲是有道理的 - 卷跨越多个磁盘,那么如何获取组成卷的每个磁盘的信息呢?发布的代码没有显示...(顺便说一句,我不是指系统BIOS提供的RAID,而是指Windows中的RAID功能)。 - James Johnston
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接