USBメモリーの切り離し

[戻る]
よっしぃ 2009/05/09(土) 18:47:37
USBメモリに書込後、「抜いてもいいよ。」のところまで、アプリケーションで制御した
いです。

「ハードウエアの安全な切り離し」→「ハードウエアデバイスの停止」
のように、
「USBメモリの停止」をアプリケーションで行うにはどのようにすればよいでしょう。
API等で可能でしょうか?

使用環境はWindows XP/Vistaで、VC++ で開発しております。

よろしくお願いします。

ITO 2009/05/09(土) 19:19:01
>「USBメモリの停止」をアプリケーションで行うにはどのようにすればよいでしょう。
> API等で可能でしょうか?
原則的に不可能です。
 APIで「DeviceIoControl」という関数があるのでデバイスが特定できれば
可能だと思います。
 すべての「USBメモリ」となると不可能だと思います。

よっしぃ 2009/05/09(土) 20:54:06
返答ありがとうございます。参考になります。

「DeviceIoControl」で、たとえば、E〜Zドライブを順になめていって、
「イジェクト」処理をすればいいのかな。などふと考えました。

... 2009/05/09(土) 22:28:49
>たとえば、E〜Zドライブを順になめていって…
FDDもZ:とかに変更出来なかったっけ?

瀬戸っぷ [E-Mail] 2009/05/09(土) 22:42:24
>FDDもZ:とかに変更出来なかったっけ?

逆ですが、リムーバブルドライブをB:に割り当て可能ですね。
SDリーダメライタをB:にしています。(XP Pro SP3にて)
# 仮想メモリの変更しようとするとエラーが出ますが。メディア入っていないから。

んで、USBデバイスの停止自体は可能です。
面倒ですけど。

http://winofsql.jp/VA003334/usb080803163310.htm
http://d.hatena.ne.jp/deraw/20060818/1155852407

API名など出てくるのでググって下さい。

瀬戸っぷ [E-Mail] 2009/05/12(火) 00:47:36
あんましきれいなコードではありませんが…
# インデント深かったりその他…

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);

↓次に続く

瀬戸っぷ [E-Mail] 2009/05/12(火) 00:48:02
↓上から続き
            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で動作確認しました。

ZCH 2009/05/12(火) 23:58:28
WMI を使えば比較的簡単なコードでできます。

http://blog701.seesaa.net/article/104160698.html
とかどうでしょうか。

古いスレッドには追加発言できません。