USBメモリに書込後、「抜いてもいいよ。」のところまで、アプリケーションで制御した
いです。
「ハードウエアの安全な切り離し」→「ハードウエアデバイスの停止」
のように、
「USBメモリの停止」をアプリケーションで行うにはどのようにすればよいでしょう。
API等で可能でしょうか?
使用環境はWindows XP/Vistaで、VC++ で開発しております。
よろしくお願いします。
>「USBメモリの停止」をアプリケーションで行うにはどのようにすればよいでしょう。
> API等で可能でしょうか?
原則的に不可能です。
APIで「DeviceIoControl」という関数があるのでデバイスが特定できれば
可能だと思います。
すべての「USBメモリ」となると不可能だと思います。
返答ありがとうございます。参考になります。
「DeviceIoControl」で、たとえば、E~Zドライブを順になめていって、
「イジェクト」処理をすればいいのかな。などふと考えました。
>たとえば、E~Zドライブを順になめていって…
FDDもZ:とかに変更出来なかったっけ?
>FDDもZ:とかに変更出来なかったっけ?
逆ですが、リムーバブルドライブをB:に割り当て可能ですね。
SDリーダメライタをB:にしています。(XP Pro SP3にて)
# 仮想メモリの変更しようとするとエラーが出ますが。メディア入っていないから。
んで、USBデバイスの停止自体は可能です。
面倒ですけど。
http://winofsql.jp/VA003334/usb080803163310.htm
http://d.hatena.ne.jp/deraw/20060818/1155852407
API名など出てくるのでググって下さい。
あんましきれいなコードではありませんが…
# インデント深かったりその他…
BOOL USBDriveRemove(TCHAR Drive)
{
BOOL fResult = FALSE;
Drive = static_cast<TCHAR>(_totupper(static_cast<unsigned int>(Drive)));
if((GetLogicalDrives() & (1 << (Drive - _T('A'))))) {
TCHAR szMountedDevicesName[] = { _T(\\DosDevices\\A:) };
HKEY hRegKey = NULL;
TCHAR szCheckStr[MAX_PATH] = {0}, szTemp[MAX_PATH] = {0}, szTemp2[MAX_PATH],
szDeviceId[MAX_PATH] = {0};
DWORD dwType, dwSize = MAX_PATH;
LPBYTE lpData = NULL;
szMountedDevicesName[_tcslen(szMountedDevicesName) - _tcslen(_T(A:))] = Drive;
RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(SYSTEM\\MountedDevices), 0,
KEY_ALL_ACCESS, &hRegKey);
dwType = REG_BINARY;
RegQueryValueEx(hRegKey, szMountedDevicesName, NULL, &dwType, NULL, &dwSize);
lpData = reinterpret_cast<LPBYTE>(HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize
+ sizeof(TCHAR))); // '\0'分を付加
RegQueryValueEx(hRegKey, szMountedDevicesName, NULL, &dwType, lpData, &dwSize);
RegCloseKey(hRegKey);
hRegKey = NULL;
// REG_BINARY(WCHAR_T?)から文字列へ(UNICODEの場合は別…か?)
WideCharToMultiByte(CP_ACP, 0, reinterpret_cast<LPCWSTR>(lpData), dwSize,
szTemp, MAX_PATH, NULL, NULL);
HeapFree(hHeap, 0, lpData);
lpData = NULL;
// 取得した文字列から取り除き
if(_tcsstr(szTemp, _T(STORAGE#RemovableMedia#)) != NULL && _tcsstr(szTemp,
_T(&RM#{)) != NULL) {
static_cast<TCHAR>(*(_tcsstr(szTemp, _T(&RM#{)))) = '\0';
_tcscpy(szCheckStr, _tcsstr(szTemp, _T(STORAGE#RemovableMedia#)) +
_tcslen(_T(STORAGE#RemovableMedia#)));
}
// 取得できたら…
if(_tcslen(szCheckStr) != 0) {
TCHAR szEnumNo[16];
DWORD dwLoopCnt, dwCount;
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
_T(SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum), 0, KEY_ALL_ACCESS, &hRegKey);
if(hRegKey) {
dwSize = sizeof(DWORD);
dwType = REG_DWORD;
RegQueryValueEx(hRegKey, _T(Count), NULL, &dwType,
reinterpret_cast<LPBYTE>(&dwCount), &dwSize);
for(dwLoopCnt = 0;dwLoopCnt < dwCount;dwLoopCnt++) {
wsprintf(szEnumNo, %d, dwLoopCnt);
dwSize = MAX_PATH;
dwType = REG_SZ;
RegQueryValueEx(hRegKey, szEnumNo, NULL, &dwType,
reinterpret_cast<LPBYTE>(szTemp2), &dwSize);
if(_tcsstr(szTemp2, _T(USBSTOR\\Disk&)) != NULL) {
HKEY hQueryKey = NULL;
_tcscpy(szTemp, _T(SYSTEM\\CurrentControlSet\\Enum\\));
_tcscat(szTemp, szTemp2);
RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTemp, 0, KEY_READ, &hQueryKey);
dwSize = MAX_PATH;
dwType = REG_SZ;
RegQueryValueEx(hQueryKey, _T(ParentIdPrefix), NULL, &dwType,
reinterpret_cast<LPBYTE>(szTemp2), &dwSize);
RegCloseKey(hQueryKey);
if(_tcscmp(szCheckStr, szTemp2) == 0) {
_tsplitpath(szTemp, NULL, NULL, szCheckStr, NULL);
static_cast<TCHAR>(*(_tcschr (szCheckStr, _T('&')))) = '\0';
break;
}
}
}
if(dwLoopCnt == dwCount) {
ZeroMemory(szCheckStr, sizeof(szCheckStr));
}
}
RegCloseKey(hRegKey);
↓次に続く
↓上から続き
if(_tcslen(szCheckStr) != 0) {
HDEVINFO hDevInfo;
hDevInfo = SetupDiGetClassDevs( NULL, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES );
if(hDevInfo != INVALID_HANDLE_VALUE) {
SP_DEVINFO_DATA DeviceInfoData = {sizeof(SP_DEVINFO_DATA)};
for (dwCount=0; SetupDiEnumDeviceInfo(hDevInfo, dwCount, &DeviceInfoData);
dwCount++) {
// デバイスのステータスを取得
ULONG status = 0;
ULONG problem = 0;
CONFIGRET cr = CM_Get_DevNode_Status(&status, &problem,
DeviceInfoData.DevInst, 0);
if (cr == CR_SUCCESS) {
if ((status & DN_DISABLEABLE)) {
BOOL ret = FALSE;
BYTE* value = NULL;
DWORD type;
DWORD size = 0;
while(1)
{
ret = SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData,
SPDRP_SERVICE, &type, value, size, &size);
if(ret || (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
break;
}
if (value) {
HeapFree(hHeap, 0, value);
value = NULL;
}
value = reinterpret_cast<BYTE *>(HeapAlloc(hHeap, 0, size));
}
if(value && _tcscmp(reinterpret_cast<TCHAR *>(value), _T(USBSTOR)) ==
0 && DeviceInfoData.DevInst > 0) {
CM_Get_Device_ID(DeviceInfoData.DevInst, szTemp, MAX_PATH, 0);
_tsplitpath(szTemp, NULL, NULL, szDeviceId, NULL);
if(_tcscmp(szCheckStr, szDeviceId) == 0 &&
CM_Request_Device_Eject(DeviceInfoData.DevInst, NULL, NULL, 0, 0) == CR_SUCCESS) {
// 取り外し成功
fResult = TRUE;
} else {
// 取り外し失敗
}
}
if (value) {
HeapFree(hHeap, 0, value);
value = NULL;
}
}
}
}
}
}
}
}
return fResult;
}
グローバルとしてヒープハンドルなhHeapが必要です。
setupapi.libのリンク、setupapi.hとcfgmgr32.hのインクルードも必要。
# 使用しているAPIで他にもたぶん必要。
レジストリも参照していたりします。
WinXP Pro SP2にVS2008EEで動作確認しました。