다음을 통해 공유


디바이스 제거 요청 처리

시스템의 기능이 지정된 디바이스를 제거하기로 결정하면 애플리케이션이 DBT_DEVICEQUERYREMOVE 디바이스 이벤트를 받습니다. 애플리케이션이 이 이벤트를 수신하면 지정된 디바이스를 사용하고 있는지 여부를 확인하고 제거를 취소하거나 준비해야 합니다.

다음 예제에서 애플리케이션은 FileName이 나타내는 파일 또는 디바이스에 대해 열린 핸들 hFile을 유지 관리합니다. 애플리케이션은 RegisterDeviceNotification 함수를 호출하고, DBT_DEVTYP_HANDLE 형식 알림 필터를 사용하고, 필터의 dbch_handle 멤버에 hFile 변수를 지정하여 기본 디바이스에서 디바이스 이벤트 알림을 등록합니다.

애플리케이션은 제거할 디바이스에 열린 파일 핸들을 닫아 DBT_DEVICEQUERYREMOVE 디바이스 이벤트를 처리합니다. 이 디바이스 제거가 취소된 경우 애플리케이션은 DBT_DEVICEQUERYREMOVEFAILED 디바이스 이벤트를 처리하여 디바이스에 대한 핸들을 다시 엽니다. 디바이스가 시스템에서 제거된 후, 애플리케이션은 DBT_DEVICEREMOVECOMPLETEDBT_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;
}

디바이스 이벤트 유형