デバイス削除要求の処理
システム内の機能が指定されたデバイスの削除を決定した場合、アプリケーションは DBT_DEVICEQUERYREMOVE デバイス イベントを受け取ります。 アプリケーションがこのイベントを受け取ると、指定されたデバイスを使用しているかどうかを判断し、削除をキャンセルするか削除の準備を行う必要があります。
次の例では、FileName によって表されるファイルまたはデバイスに対する、開いているハンドル hFile がアプリケーションに維持されています。 アプリケーションは、RegisterDeviceNotification 関数を呼び出して、DBT_DEVTYP_HANDLE 型の通知フィルターを使用し、フィルターの dbch_handle メンバーに hFile 変数を指定することにより、基になるデバイスでデバイス イベント通知を登録します。
アプリケーションは、削除するデバイスに対して開いているファイル ハンドルを閉じることにより、DBT_DEVICEQUERYREMOVE デバイス イベントを処理します。 このデバイスの削除が取り消された場合、アプリケーションは DBT_DEVICEQUERYREMOVEFAILED デバイス イベントを処理して、デバイスへのハンドルを再度開きます。 デバイスがシステムから削除されると、アプリケーションは、デバイスのその通知ハンドルの登録を解除して、デバイスに対してまだ開いているハンドルを閉じることによって、DBT_DEVICEREMOVECOMPLETE デバイス イベントと DBT_DEVICEREMOVEPENDING デバイス イベントを処理します。
#include <windows.h>
#include <dbt.h>
#include <strsafe.h>
// ...
INT_PTR WINAPI WinProcCallback( HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam )
{
LPCTSTR FileName = NULL; // path to the file or device of interest
HANDLE hFile = INVALID_HANDLE_VALUE; // handle to the file or device
PDEV_BROADCAST_HDR pDBHdr;
PDEV_BROADCAST_HANDLE pDBHandle;
TCHAR szMsg[80];
switch (message)
{
//...
case WM_DEVICECHANGE:
switch (wParam)
{
case DBT_DEVICEQUERYREMOVE:
pDBHdr = (PDEV_BROADCAST_HDR) lParam;
switch (pDBHdr->dbch_devicetype)
{
case DBT_DEVTYP_HANDLE:
// A request has been made to remove the device;
// close any open handles to the file or device
pDBHandle = (PDEV_BROADCAST_HANDLE) pDBHdr;
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
}
return TRUE;
case DBT_DEVICEQUERYREMOVEFAILED:
pDBHdr = (PDEV_BROADCAST_HDR) lParam;
switch (pDBHdr->dbch_devicetype)
{
case DBT_DEVTYP_HANDLE:
// Removal of the device has failed;
// reopen a handle to the file or device
pDBHandle = (PDEV_BROADCAST_HANDLE) pDBHdr;
hFile = CreateFile(FileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
StringCchPrintf( szMsg, sizeof(szMsg)/sizeof(szMsg[0]),
TEXT("CreateFile failed: %lx.\n"),
GetLastError());
MessageBox(hWnd, szMsg, TEXT("CreateFile"), MB_OK);
}
}
return TRUE;
case DBT_DEVICEREMOVEPENDING:
pDBHdr = (PDEV_BROADCAST_HDR) lParam;
switch (pDBHdr->dbch_devicetype)
{
case DBT_DEVTYP_HANDLE:
// The device is being removed;
// close any open handles to the file or device
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
}
return TRUE;
case DBT_DEVICEREMOVECOMPLETE:
pDBHdr = (PDEV_BROADCAST_HDR) lParam;
switch (pDBHdr->dbch_devicetype)
{
case DBT_DEVTYP_HANDLE:
pDBHandle = (PDEV_BROADCAST_HANDLE) pDBHdr;
// The device has been removed from the system;
// unregister its notification handle
UnregisterDeviceNotification(
pDBHandle->dbch_hdevnotify);
// The device has been removed;
// close any remaining open handles to the file or device
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
}
return TRUE;
default:
return TRUE;
}
}
default:
return TRUE;
}
関連トピック