디바이스 제거 요청 처리
시스템의 기능이 지정된 디바이스를 제거하기로 결정하면 애플리케이션이 DBT_DEVICEQUERYREMOVE 디바이스 이벤트를 받습니다. 애플리케이션이 이 이벤트를 수신하면 지정된 디바이스를 사용하고 있는지 여부를 확인하고 제거를 취소하거나 준비해야 합니다.
다음 예제에서 애플리케이션은 FileName이 나타내는 파일 또는 디바이스에 대해 열린 핸들 hFile을 유지 관리합니다. 애플리케이션은 DBT_DEVTYP_HANDLE 형식 알림 필터를 사용하고 필터의 dbch_handle멤버에 hFile 변수를 지정하여 RegisterDeviceNotification 함수를 호출하여 기본 디바이스에서 디바이스 이벤트 알림을 등록합니다.
애플리케이션은 열려 있는 파일 핸들을 제거할 디바이스에 닫아 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;
}
관련 항목