![]()
「C:」などのドライブレターと接続されているデバイスとを関連付ける方法にはいくつかある。ここではDEVINSTを返すCM_系APIを利用した。この方法を利用するとDeviceIoControlに渡すためのハンドルをCreateFileで取得できる。
#include "winioctl.h"
#include "cfgmgr32.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;
}
//
// DEVINSTのプロパティ文字列取得
//
//CM_Get_DevNode_Registry_Propertyにより文字列データを取得する
//
bool GetDevNodeRegistryProperty(DEVINST devInst,ULONG nProperty,CAtlString* pstrText)
{
ULONG nDataSize;
BYTE* pData;
CONFIGRET ret;
if(pstrText == NULL)
return false;
*pstrText = _T("");
nDataSize = 0;
ret = ::CM_Get_DevNode_Registry_Property(devInst,nProperty,NULL,NULL,&nDataSize,0);
pData = new BYTE[nDataSize];
ret = ::CM_Get_DevNode_Registry_Property(devInst,nProperty,NULL,pData,&nDataSize,0);
if(ret == CR_SUCCESS)
*pstrText = (TCHAR*)pData;
if(pData)
delete pData;
return (ret == CR_SUCCESS) ? true : false;
}
//
// DEVINSTデバイス検索例
//
//「C:」などのドライブレターからQueryDosDeviceで取得できる文字列と同じ場所を示すDEVINSTを探す
//
bool SearchDEVINSTDevice(LPCTSTR pszPhysicalDeviceName)
{
bool ret;
DEVINST devInst;
DEVINST devInstNext;
CONFIGRET cRet;
CAtlString strText;
cRet = ::CM_Locate_DevNode(&devInst,NULL,0);
if(cRet != CR_SUCCESS)
return false;
while(1)
{
ret = GetDevNodeRegistryProperty(devInst,CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME,&strText);
if(ret == false || strText != pszPhysicalDeviceName)
{
cRet = ::CM_Get_Child(&devInstNext,devInst,0);
if(cRet == CR_SUCCESS)
{
devInst = devInstNext;
continue;
}
while(1)
{
cRet = ::CM_Get_Sibling(&devInstNext,devInst,0);
if(cRet == CR_SUCCESS)
{
devInst = devInstNext;
break;
}
cRet = ::CM_Get_Parent(&devInstNext,devInst,0);
if(cRet != CR_SUCCESS)
return false;
devInst = devInstNext;
}
continue;
}
//デバイスが見つかったときの処理例(ここから)
{
CAtlString strBuff;
CAtlString strMessage;
//プロパティをいくつか取得してメッセージボックスに表示
ret = GetDevNodeRegistryProperty(devInst,CM_DRP_DEVICEDESC,&strText);
if(ret)
{
strBuff.Format(_T("CM_DRP_DEVICEDESC:%s\n"),strText);
strMessage += strBuff;
}
ret = GetDevNodeRegistryProperty(devInst,CM_DRP_HARDWAREID,&strText);
if(ret)
{
strBuff.Format(_T("CM_DRP_HARDWAREID:%s\n"),strText);
strMessage += strBuff;
}
ret = GetDevNodeRegistryProperty(devInst,CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME,&strText);
if(ret)
{
strBuff.Format(_T("CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:%s\n"),strText);
strMessage += strBuff;
}
{
//デバイスIDを取得してCreateFileで開く
TCHAR pszDeviceID[2048];
cRet = ::CM_Get_Device_ID(devInst,pszDeviceID,2048,0);
if(cRet == CR_SUCCESS)
{
strBuff.Format(_T("CM_Get_Device_ID:%s\n"),pszDeviceID);
strMessage += strBuff;
}
if(cRet == CR_SUCCESS)
{
int nFind;
HANDLE hDevice;
CAtlString strDevice;
//開けるのデバイスIDに_??_が含まれているもののみ?
//_??_以降を取り出して先頭に\\\\?\\を付加してCreateFileで開く
strDevice = pszDeviceID;
nFind = strDevice.Find(_T("_??_"));
if(nFind > 0)
{
strDevice = strDevice.Right(strDevice.GetLength() - nFind - 4);
strDevice = _T("\\\\?\\") + strDevice;
hDevice = CreateFile(strDevice,GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hDevice != INVALID_HANDLE_VALUE)
{
//ハンドルを取得できた(DeviceIoControlで利用可能)
::CloseHandle(hDevice);
}
}
}
}
::MessageBox(NULL,strMessage,_T(""),MB_OK);
}
//デバイスが見つかったときの処理例(ここまで)
return true;
}
return false;
}
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 = SearchDEVINSTDevice(pszTargetPath);
}
return true;
}
