⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dostorageenum.cpp

📁 Device IO Control StorageEnum.zip
💻 CPP
字号:
#include "stdafx.h"#include "DoStorageEnum.h"

// SetupDiGetInterfaceDeviceDetail所需要的输出长度
#define INTERFACE_DETAIL_SIZE	(1024)

// IOCTL_STORAGE_GET_MEDIA_TYPES_EX可能返回不止一条DEVICE_MEDIA_INFO,故定义足够的空间
#define MEDIA_INFO_SIZE		(sizeof(GET_MEDIA_TYPES) + sizeof(DEVICE_MEDIA_INFO) * 15)


// 从GUID获得设备路径
// lpGuid: GUID指针
// pszDevicePath: 设备路径指针的指针
// 返回值: 成功得到的设备路径个数
int GetDevicePath(LPGUID lpGuid, LPTSTR* pszDevicePath)
{
	HDEVINFO hDevInfoSet;
	SP_DEVICE_INTERFACE_DATA ifdata;
	PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
	int nCount;
	BOOL bResult;

	// 取得一个该GUID相关的设备信息集句柄
	hDevInfoSet = ::SetupDiGetClassDevs(lpGuid, 	// class GUID 
			NULL,									// 无关键字 
			NULL,									// 不指定父窗口句柄 
			DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);	// 目前存在的设备

	// 失败...
	if(hDevInfoSet == INVALID_HANDLE_VALUE)
	{
		return 0;
	}

	// 申请设备接口数据空间
	pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, INTERFACE_DETAIL_SIZE);
	
	pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

	nCount = 0;
	bResult = TRUE;
	
	// 设备序号=0,1,2... 逐一测试设备接口,到失败为止
	while (bResult)
	{
		ifdata.cbSize=sizeof(ifdata);
	
		// 枚举符合该GUID的设备接口
		bResult = ::SetupDiEnumDeviceInterfaces(
				hDevInfoSet,			// 设备信息集句柄
				NULL,					// 不需额外的设备描述
				lpGuid,					// GUID
				(ULONG)nCount,			// 设备信息集里的设备序号
				&ifdata);				// 设备接口信息

		if(bResult)
		{
			// 取得该设备接口的细节(设备路径)
			bResult = SetupDiGetInterfaceDeviceDetail(
					hDevInfoSet,			// 设备信息集句柄
					&ifdata,				// 设备接口信息
					pDetail,				// 设备接口细节(设备路径)
					INTERFACE_DETAIL_SIZE,	// 输出缓冲区大小
					NULL,					// 不需计算输出缓冲区大小(直接用设定值)
					NULL);					// 不需额外的设备描述

			if(bResult)
			{
				// 复制设备路径到输出缓冲区
				::strcpy(pszDevicePath[nCount], pDetail->DevicePath);

				// 调整计数值
				nCount++;
			}
		}
	}

	// 释放设备接口数据空间
	::GlobalFree(pDetail);

	// 关闭设备信息集句柄
	::SetupDiDestroyDeviceInfoList(hDevInfoSet);

	return nCount;
}

// 打开设备
// pszDevicePath: 设备的路径
HANDLE OpenDevice(LPCTSTR pszDevicePath)
{
	HANDLE hDevice;

	// 打开设备
	hDevice= ::CreateFile(pszDevicePath,			// 设备路径
			GENERIC_READ | GENERIC_WRITE,			// 读写方式
			FILE_SHARE_READ | FILE_SHARE_WRITE,		// 共享方式
			NULL,									// 默认的安全描述符
			OPEN_EXISTING,							// 创建方式
			0,										// 不需设置文件属性
			NULL);									// 不需参照模板文件

	return hDevice;
}

// hDevice -- 设备句柄
// pGeometry -- 参数缓冲区指针
BOOL GetDriveGeometry(HANDLE hDevice, PDISK_GEOMETRY pGeometry)
{
	PGET_MEDIA_TYPES pMediaTypes;	// 内部用的输出缓冲区
	DWORD dwOutBytes;				// 输出数据长度
	BOOL bResult;					// DeviceIoControl的返回结果

	// 申请内部用的输出缓冲区
	pMediaTypes = (PGET_MEDIA_TYPES)::GlobalAlloc(LMEM_ZEROINIT, MEDIA_INFO_SIZE);

	// 用IOCTL_STORAGE_GET_MEDIA_TYPES_EX取介质类型参数
	bResult = ::DeviceIoControl(hDevice,			// 设备句柄
			IOCTL_STORAGE_GET_MEDIA_TYPES_EX,		// 取介质类型参数
			NULL, 0,								// 不需要输入数据
			pMediaTypes, MEDIA_INFO_SIZE,			// 输出数据缓冲区
			&dwOutBytes,							// 输出数据长度
			(LPOVERLAPPED)NULL);					// 用同步I/O	

	if(bResult)
	{
		// 注意到结构DEVICE_MEDIA_INFO是在结构DISK_GEOMETRY的基础上扩充的
		// 为简化程序,用memcpy代替如下多条赋值语句:
		// pGeometry->MediaType = (MEDIA_TYPE)pMediaTypes->MediaInfo[0].DeviceSpecific.DiskInfo.MediaType;
		// pGeometry->Cylinders = pMediaTypes->MediaInfo[0].DeviceSpecific.DiskInfo.Cylinders;
		// pGeometry->TracksPerCylinder = pMediaTypes->MediaInfo[0].DeviceSpecific.DiskInfo.TracksPerCylinder;
		// ... ...
		::memcpy(pGeometry, pMediaTypes->MediaInfo, sizeof(DISK_GEOMETRY));
	}

	// 释放内部缓冲区
	::GlobalFree(pMediaTypes);

	return bResult;
}

// 取设备属性信息
// hDevice -- 设备句柄
// pDevDesc -- 输出的设备描述和属性信息缓冲区指针(包含连接在一起的两部分)
BOOL GetDriveProperty(HANDLE hDevice, PSTORAGE_DEVICE_DESCRIPTOR pDevDesc)
{
	STORAGE_PROPERTY_QUERY	Query;	// 查询输入参数
	DWORD dwOutBytes;				// IOCTL输出数据长度
	BOOL bResult;					// IOCTL返回值

	// 指定查询方式
	Query.PropertyId = StorageDeviceProperty;
	Query.QueryType = PropertyStandardQuery;

	// 用IOCTL_STORAGE_QUERY_PROPERTY取设备属性信息
	bResult = ::DeviceIoControl(hDevice,			// 设备句柄
			IOCTL_STORAGE_QUERY_PROPERTY,			// 取设备属性信息
			&Query, sizeof(STORAGE_PROPERTY_QUERY),	// 输入数据缓冲区
			pDevDesc, pDevDesc->Size,				// 输出数据缓冲区
			&dwOutBytes,							// 输出数据长度
			(LPOVERLAPPED)NULL);					// 用同步I/O	

	return bResult;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -