ドライブ名からデバイス情報を取得する

test105.gif
「C:」などのドライブ名からSetup APIを利用して「汎用ボリューム」といったデバイス名などを取得する。「こんな処理何に使うの?」と聞かれると答えに窮するが...

ドライブ名とHDEVINFO系を関連付けるためにQueryDosDeviceを利用している。

依存環境:ATL
#include <winioctl.h>
#include <setupapi.h>
#pragma	comment(lib,"setupapi.lib")

#include "atlstr.h"


//
//	使用中のドライブレター取得
//
//ドライブ名が文字列として列挙されて返る。例:AとC、Dドライブが使われているなら"ACD"
//
bool	GetUsedDriveLetter(TCHAR* pszLetter,int nSize)
{
	int		i;
	int		nIndex;
	TCHAR	cbDrive;
	DWORD	dwDrives;

	if(pszLetter == NULL || nSize <= 0)
		return	false;

	dwDrives = ::GetLogicalDrives();

	ZeroMemory(pszLetter,sizeof(TCHAR) * nSize);
	nIndex = 0;
	cbDrive = _T('A');
	for(i = 0; i <= 'Z' - 'A'; i++)
	{
		if(! ((1 << i) & dwDrives))
			continue;

		pszLetter[nIndex++] = cbDrive + i;
		if(nIndex < nSize)
			continue;

		return	(dwDrives << (i+1)) ? false : true;
	}

	return	true;
}



//
//	HDEVINFO(SP_DEVINFO_DATA)のプロパティ文字列取得
//
//SetupDiGetDeviceRegistryPropertyにより文字列データを取得する
//
bool	GetDeviceRegistryPropertyString(HDEVINFO hDeviceInfoSet,PSP_DEVINFO_DATA pDeviceInfoData,DWORD dwProperty,CAtlString* pstrText)
{
	BOOL	ret;
	DWORD	dwDataType;
	DWORD	dwDataSize;
	BYTE*	pData;

	if(pstrText == NULL)
		return	false;
	*pstrText = _T("");

	pData = NULL;
	dwDataSize = 0;
	while(1)
	{
		ret = ::SetupDiGetDeviceRegistryProperty(hDeviceInfoSet,pDeviceInfoData,dwProperty,&dwDataType,pData,dwDataSize,&dwDataSize);
		if(ret || ::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
			break;

		if(pData)
			delete	pData;
		pData = new BYTE[dwDataSize];
	}
	if(ret && pData)
	{
		//TODO:REG_MULTI_SZも1つの文字列として扱っている!
		if(dwDataType == REG_EXPAND_SZ || dwDataType == REG_MULTI_SZ || dwDataType == REG_SZ)
			*pstrText = (TCHAR*)pData;
	}
	if(pData)
		delete	pData;

	return	(ret && pData) ? true : false;
}



//
//	HDEVINFOデバイス検索例
//
//「C:」などのドライブレターからQueryDosDeviceで取得できる文字列と同じ場所を示すHDEVINFOを探す
//
bool	SearchHDEVINFODevice(LPCTSTR pszPhysicalDeviceName)
{
	bool		bRet;
	BOOL		ret;
	DWORD		i;
	HDEVINFO	hDevInfo;
	CAtlString	strProperty;
	SP_DEVINFO_DATA	sDeviceInfoData;

	hDevInfo = ::SetupDiGetClassDevs(NULL,0,0,DIGCF_PRESENT | DIGCF_ALLCLASSES);
	if(hDevInfo == INVALID_HANDLE_VALUE)
		return	false;

	i = 0;
	sDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	while(1)
	{
		ret = ::SetupDiEnumDeviceInfo(hDevInfo,i,&sDeviceInfoData);
		if(ret == FALSE)
			break;
		i++;

		bRet = GetDeviceRegistryPropertyString(hDevInfo,&sDeviceInfoData,SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,&strProperty);
		if(bRet == false)
			continue;

		//一致するデバイスかどうかチェック
		if(strProperty != pszPhysicalDeviceName)
			continue;

		//デバイスが見つかった!
		//ここではいくつかのプロパティをメッセージボックスで表示
		{
			CAtlString	strBuff;
			CAtlString	strMessage;

			bRet = GetDeviceRegistryPropertyString(hDevInfo,&sDeviceInfoData,SPDRP_DEVICEDESC,&strProperty);
			if(bRet)
			{
				strBuff.Format(_T("SPDRP_DEVICEDESC:%s\n"),strProperty);
				strMessage += strBuff;
			}
			bRet = GetDeviceRegistryPropertyString(hDevInfo,&sDeviceInfoData,SPDRP_HARDWAREID,&strProperty);
			if(bRet)
			{
				strBuff.Format(_T("SPDRP_HARDWAREID:%s\n"),strProperty);
				strMessage += strBuff;
			}
			bRet = GetDeviceRegistryPropertyString(hDevInfo,&sDeviceInfoData,SPDRP_CLASS,&strProperty);
			if(bRet)
			{
				strBuff.Format(_T("SPDRP_CLASS:%s\n"),strProperty);
				strMessage += strBuff;
			}
			bRet = GetDeviceRegistryPropertyString(hDevInfo,&sDeviceInfoData,SPDRP_DRIVER,&strProperty);
			if(bRet)
			{
				strBuff.Format(_T("SPDRP_DRIVER:%s\n"),strProperty);
				strMessage += strBuff;
			}
			bRet = GetDeviceRegistryPropertyString(hDevInfo,&sDeviceInfoData,SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,&strProperty);
			if(bRet)
			{
				strBuff.Format(_T("SPDRP_PHYSICAL_DEVICE_OBJECT_NAME:%s\n"),strProperty);
				strMessage += strBuff;
			}
			bRet = GetDeviceRegistryPropertyString(hDevInfo,&sDeviceInfoData,SPDRP_DEVTYPE,&strProperty);
			if(bRet)
			{
				strBuff.Format(_T("SPDRP_DEVTYPE:%s\n"),strProperty);
				strMessage += strBuff;
			}
			::MessageBox(NULL,strMessage,_T(""),MB_OK);
		}
	}
	::SetupDiDestroyDeviceInfoList(hDevInfo);

	return	true;;
}





bool	Test()
{
	bool	ret;
	size_t	i;
	size_t	nSize;
	TCHAR	pszDrives[256];

	//使われている全ドライブを取得
	ret = GetUsedDriveLetter(pszDrives,256);
	if(ret == false)
		return	false;

	//ドライブごとに処理
	nSize = ::_tcslen(pszDrives);
	for(i = 0; i < nSize; i++)
	{
		DWORD		dwRet;
		TCHAR		pszTargetPath[MAX_PATH];
		CAtlString	strDrive;

		strDrive.Format(_T("%c:"),pszDrives[i]);
		dwRet = ::QueryDosDevice(strDrive,pszTargetPath,MAX_PATH);
		if(dwRet == 0)
			continue;

		ret = SearchHDEVINFODevice(pszTargetPath);
	}

	return	true;
}

プロジェクトファイルをダウンロード


カテゴリー「システム情報」 のエントリー