DoStorageEnum.cpp
上传用户:posgewe
上传日期:2022-07-05
资源大小:164k
文件大小:5k
源码类别:

系统编程

开发平台:

Visual C++

  1. #include "stdafx.h" #include "DoStorageEnum.h"
  2. // SetupDiGetInterfaceDeviceDetail所需要的输出长度
  3. #define INTERFACE_DETAIL_SIZE (1024)
  4. // IOCTL_STORAGE_GET_MEDIA_TYPES_EX可能返回不止一条DEVICE_MEDIA_INFO,故定义足够的空间
  5. #define MEDIA_INFO_SIZE (sizeof(GET_MEDIA_TYPES) + sizeof(DEVICE_MEDIA_INFO) * 15)
  6. // 从GUID获得设备路径
  7. // lpGuid: GUID指针
  8. // pszDevicePath: 设备路径指针的指针
  9. // 返回值: 成功得到的设备路径个数
  10. int GetDevicePath(LPGUID lpGuid, LPTSTR* pszDevicePath)
  11. {
  12. HDEVINFO hDevInfoSet;
  13. SP_DEVICE_INTERFACE_DATA ifdata;
  14. PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
  15. int nCount;
  16. BOOL bResult;
  17. // 取得一个该GUID相关的设备信息集句柄
  18. hDevInfoSet = ::SetupDiGetClassDevs(lpGuid,  // class GUID 
  19. NULL, // 无关键字 
  20. NULL, // 不指定父窗口句柄 
  21. DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备
  22. // 失败...
  23. if(hDevInfoSet == INVALID_HANDLE_VALUE)
  24. {
  25. return 0;
  26. }
  27. // 申请设备接口数据空间
  28. pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, INTERFACE_DETAIL_SIZE);
  29. pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  30. nCount = 0;
  31. bResult = TRUE;
  32. // 设备序号=0,1,2... 逐一测试设备接口,到失败为止
  33. while (bResult)
  34. {
  35. ifdata.cbSize=sizeof(ifdata);
  36. // 枚举符合该GUID的设备接口
  37. bResult = ::SetupDiEnumDeviceInterfaces(
  38. hDevInfoSet, // 设备信息集句柄
  39. NULL, // 不需额外的设备描述
  40. lpGuid, // GUID
  41. (ULONG)nCount, // 设备信息集里的设备序号
  42. &ifdata); // 设备接口信息
  43. if(bResult)
  44. {
  45. // 取得该设备接口的细节(设备路径)
  46. bResult = SetupDiGetInterfaceDeviceDetail(
  47. hDevInfoSet, // 设备信息集句柄
  48. &ifdata, // 设备接口信息
  49. pDetail, // 设备接口细节(设备路径)
  50. INTERFACE_DETAIL_SIZE, // 输出缓冲区大小
  51. NULL, // 不需计算输出缓冲区大小(直接用设定值)
  52. NULL); // 不需额外的设备描述
  53. if(bResult)
  54. {
  55. // 复制设备路径到输出缓冲区
  56. ::strcpy(pszDevicePath[nCount], pDetail->DevicePath);
  57. // 调整计数值
  58. nCount++;
  59. }
  60. }
  61. }
  62. // 释放设备接口数据空间
  63. ::GlobalFree(pDetail);
  64. // 关闭设备信息集句柄
  65. ::SetupDiDestroyDeviceInfoList(hDevInfoSet);
  66. return nCount;
  67. }
  68. // 打开设备
  69. // pszDevicePath: 设备的路径
  70. HANDLE OpenDevice(LPCTSTR pszDevicePath)
  71. {
  72. HANDLE hDevice;
  73. // 打开设备
  74. hDevice= ::CreateFile(pszDevicePath, // 设备路径
  75. GENERIC_READ | GENERIC_WRITE, // 读写方式
  76. FILE_SHARE_READ | FILE_SHARE_WRITE, // 共享方式
  77. NULL, // 默认的安全描述符
  78. OPEN_EXISTING, // 创建方式
  79. 0, // 不需设置文件属性
  80. NULL); // 不需参照模板文件
  81. return hDevice;
  82. }
  83. // hDevice -- 设备句柄
  84. // pGeometry -- 参数缓冲区指针
  85. BOOL GetDriveGeometry(HANDLE hDevice, PDISK_GEOMETRY pGeometry)
  86. {
  87. PGET_MEDIA_TYPES pMediaTypes; // 内部用的输出缓冲区
  88. DWORD dwOutBytes; // 输出数据长度
  89. BOOL bResult; // DeviceIoControl的返回结果
  90. // 申请内部用的输出缓冲区
  91. pMediaTypes = (PGET_MEDIA_TYPES)::GlobalAlloc(LMEM_ZEROINIT, MEDIA_INFO_SIZE);
  92. // 用IOCTL_STORAGE_GET_MEDIA_TYPES_EX取介质类型参数
  93. bResult = ::DeviceIoControl(hDevice, // 设备句柄
  94. IOCTL_STORAGE_GET_MEDIA_TYPES_EX, // 取介质类型参数
  95. NULL, 0, // 不需要输入数据
  96. pMediaTypes, MEDIA_INFO_SIZE, // 输出数据缓冲区
  97. &dwOutBytes, // 输出数据长度
  98. (LPOVERLAPPED)NULL); // 用同步I/O
  99. if(bResult)
  100. {
  101. // 注意到结构DEVICE_MEDIA_INFO是在结构DISK_GEOMETRY的基础上扩充的
  102. // 为简化程序,用memcpy代替如下多条赋值语句:
  103. // pGeometry->MediaType = (MEDIA_TYPE)pMediaTypes->MediaInfo[0].DeviceSpecific.DiskInfo.MediaType;
  104. // pGeometry->Cylinders = pMediaTypes->MediaInfo[0].DeviceSpecific.DiskInfo.Cylinders;
  105. // pGeometry->TracksPerCylinder = pMediaTypes->MediaInfo[0].DeviceSpecific.DiskInfo.TracksPerCylinder;
  106. // ... ...
  107. ::memcpy(pGeometry, pMediaTypes->MediaInfo, sizeof(DISK_GEOMETRY));
  108. }
  109. // 释放内部缓冲区
  110. ::GlobalFree(pMediaTypes);
  111. return bResult;
  112. }
  113. // 取设备属性信息
  114. // hDevice -- 设备句柄
  115. // pDevDesc -- 输出的设备描述和属性信息缓冲区指针(包含连接在一起的两部分)
  116. BOOL GetDriveProperty(HANDLE hDevice, PSTORAGE_DEVICE_DESCRIPTOR pDevDesc)
  117. {
  118. STORAGE_PROPERTY_QUERY Query; // 查询输入参数
  119. DWORD dwOutBytes; // IOCTL输出数据长度
  120. BOOL bResult; // IOCTL返回值
  121. // 指定查询方式
  122. Query.PropertyId = StorageDeviceProperty;
  123. Query.QueryType = PropertyStandardQuery;
  124. // 用IOCTL_STORAGE_QUERY_PROPERTY取设备属性信息
  125. bResult = ::DeviceIoControl(hDevice, // 设备句柄
  126. IOCTL_STORAGE_QUERY_PROPERTY, // 取设备属性信息
  127. &Query, sizeof(STORAGE_PROPERTY_QUERY), // 输入数据缓冲区
  128. pDevDesc, pDevDesc->Size, // 输出数据缓冲区
  129. &dwOutBytes, // 输出数据长度
  130. (LPOVERLAPPED)NULL); // 用同步I/O
  131. return bResult;
  132. }