又一种枚举当前系统中硬盘的方法(2)

这次使用 SetupDiGetClassDevs 和 SetupDiEnumDeviceInterfaces 函数直接查询系统中的硬盘信息。具体的解释,请参考

http://cutebunny.blog.51cto.com/301216/625577 《windows的磁盘操作之七——获取当前所有的物理磁盘号》 这是非常好的文章。

枚举的结果并非 \\.\PhysicalDriveX 而是类似 \\?\usbstor#disk&ven_adata&prod_usb_flash_drive&rev_1.00#000000000000000922&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b} 这样的字符串。(天杀同学指出:这种符号连接,是链接到atapi生成的设备,比如\device\ide\idedeviceP0TTolo-3这种设备上的,这个设备上面会附加\Device\Harddisk0\DR0,应用程序打开\\?\ide#xxxx这个,就和打开\\.\PhysicalDrive0一样了,因为请求在驱动里面都是从上层往下层传递的. )同样可以直接给CreateFile作为参数使用。

另外,这个程序如果直接运行,会出现打印出来上述字符串,然后又显示 “CreateFile() Error: 5”的问题。这个错误表示 “Access denied”.

它是由于在程序中使用CreateFile而没有相应的权限导致的。

程序中使用了很多C语言的变长数组,这在我看起来无比诡异…….

编译中需要加入 lib,具体方式请参考下图

setting

运行结果如下图,可以看到,最后还给出了硬盘号。

phy2

这样的方法更精确一些,在很多硬盘的情况下会节省查询的时间,但是和1中的方法相比,复杂度提高了很多倍。

代码如下

// phylist1.cpp : Defines the entry point for the console application.
//

#include   "stdafx.h"
#include   <windows.h>
#include   <stdio.h>   
#include   <conio.h> 
#include   <winioctl.h>
#include   <setupapi.h>

#define MAX_DEVICE  10
#define INTERFACE_DETAIL_SIZE    (1024)
DEFINE_GUID(GUID_DEVINTERFACE_DISK,   0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);

/******************************************************************************
* Function: get device path from GUID
* input: lpGuid, GUID pointer
* output: pszDevicePath, device paths
* return: Succeed, the amount of found device paths
*         Fail, -1
******************************************************************************/
DWORD GetDevicePath(LPGUID lpGuid, WCHAR **pszDevicePath)
{
    HDEVINFO hDevInfoSet;
    SP_DEVICE_INTERFACE_DATA ifdata;
    PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
    DWORD nCount;
    BOOL result;
 
    //get a handle to a device information set
    hDevInfoSet = SetupDiGetClassDevs(
                    lpGuid,      // class GUID
                    NULL,        // Enumerator
                    NULL,        // hwndParent
                    DIGCF_PRESENT | DIGCF_DEVICEINTERFACE    // present devices
                    );
 
    //fail...
    if (hDevInfoSet == INVALID_HANDLE_VALUE)
    {
        fprintf(stderr, "IOCTL_STORAGE_GET_DEVICE_NUMBER Error: %ld\n", GetLastError());
        return (DWORD)-1;
    }
 
    pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(INTERFACE_DETAIL_SIZE);
    if (pDetail == NULL)
    {
        return (DWORD)-1;
    }
    pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
 
    nCount = 0;
    result = TRUE;
 
    // device index = 0, 1, 2... test the device interface one by one
    while (result)
    {
        ifdata.cbSize = sizeof(ifdata);
 
        //enumerates the device interfaces that are contained in a device information set
        result = SetupDiEnumDeviceInterfaces(
                    hDevInfoSet,     // DeviceInfoSet
                    NULL,            // DeviceInfoData
                    lpGuid,          // GUID
                    nCount,   // MemberIndex
                    &ifdata        // DeviceInterfaceData
                    );
        if (result)
        {
            // get details about a device interface
            result = SetupDiGetDeviceInterfaceDetail(
                        hDevInfoSet,    // DeviceInfoSet
                        &ifdata,        // DeviceInterfaceData
                        pDetail,        // DeviceInterfaceDetailData
                        INTERFACE_DETAIL_SIZE,    // DeviceInterfaceDetailDataSize
                        NULL,           // RequiredSize
                        NULL          // DeviceInfoData
                        );
            if (result)
            {
                // copy the path to output buffer
                wcscpy(pszDevicePath[nCount], pDetail->DevicePath);
                printf("%ws\n", pDetail->DevicePath);
                nCount++;
            }
        }
    }
 
    free(pDetail);
    (void)SetupDiDestroyDeviceInfoList(hDevInfoSet);
 
    return nCount;
}

/******************************************************************************
* Function: get all present disks' physical number
* input: N/A
* output: ppDisks, array of disks' physical number
* return: Succeed, the amount of present disks
*         Fail, -1
******************************************************************************/
DWORD GetAllPresentDisks(DWORD **ppDisks)
{
    WCHAR *szDevicePath[MAX_DEVICE];        // device path
    DWORD nDevice;
    HANDLE hDevice;
    STORAGE_DEVICE_NUMBER number;
    BOOL result;
    DWORD readed;
    WORD i, j;
 
    for (i = 0; i < MAX_DEVICE; i++)
    {
        szDevicePath[i] = (WCHAR *)malloc(INTERFACE_DETAIL_SIZE);
        if (NULL == szDevicePath[i])
        {
            for (j = 0; j < i; j++)
            {
                free(szDevicePath[i]);
            }
            return (DWORD)-1;
        }
    }
 
    // get the device paths
    nDevice = GetDevicePath(const_cast<LPGUID>(&GUID_DEVINTERFACE_DISK), szDevicePath);
    if ((DWORD)-1 == nDevice)
    {
        for (i = 0; i < MAX_DEVICE; i++)
        {
            free(szDevicePath[i]);
        }
        return (DWORD)-1;
    }
 
    *ppDisks = (DWORD *)malloc(sizeof(DWORD) * nDevice);

    // get the disk's physical number one by one
    for (i = 0; i < nDevice; i++)
    {
        hDevice = CreateFile(
                    szDevicePath[i], // drive to open
                    GENERIC_READ | GENERIC_WRITE,     // 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 attribute
                    );
        if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
        {
            for (j = 0; j < MAX_DEVICE; j++)
            {
                free(szDevicePath[j]);
            }
            free(*ppDisks);
            fprintf(stderr, "CreateFile() Error: %ld\n", GetLastError());
            return DWORD(-1);
        }
        result = DeviceIoControl(
                    hDevice,                // handle to device
                    IOCTL_STORAGE_GET_DEVICE_NUMBER, // dwIoControlCode
                    NULL,                            // lpInBuffer
                    0,                               // nInBufferSize
                    &number,           // output buffer
                    sizeof(number),         // size of output buffer
                    &readed,       // number of bytes returned
                    NULL      // OVERLAPPED structure
                    );
        if (!result) // fail
        {
            fprintf(stderr, "IOCTL_STORAGE_GET_DEVICE_NUMBER Error: %ld\n", GetLastError());
            for (j = 0; j < MAX_DEVICE; j++)
            {
                free(szDevicePath[j]);
            }
            free(*ppDisks);
            (void)CloseHandle(hDevice);
            return (DWORD)-1;
        }
        *(*ppDisks + i) = number.DeviceNumber;
		// printf("%d\n",number.DeviceNumber);
        (void)CloseHandle(hDevice);
    }
 
    for (i = 0; i < MAX_DEVICE; i++)
    {
        free(szDevicePath[i]);
    }
    return nDevice;
}

int _tmain(int argc, _TCHAR* argv[])
{
	DWORD *pDisk;
	int t,j;
	t=GetAllPresentDisks(&pDisk);
	for (j=0; j<t;j++)
	{
      printf("%d \n", *pDisk++);
	}

	_getch(); 
	return 0;
}

 

完整代码下载

Phylist2

发表评论

电子邮件地址不会被公开。 必填项已用*标注