title: Detecting USB Insertion / Removal Events in Windows using C++
body: <p>I am writing an extension for an existing application that needs to handle USB insertion/removal events.  I know the VID/PID of the device of interest.  However, I don't have access to the window handle, so I don't know if <code>RegisterDeviceNotification</code> will be of much use, unless there is a way to obtain the handle via the <code>WINAPI</code>.  What would be the best way to detect USB insertion/removal events with C++?</p>
  
  <p><a href="http://msdn.microsoft.com/en-us/library/aa390425%28v=VS.85%29.aspx" rel="noreferrer">This sample code on the Microsoft website</a> shows how to receive event notifications via WMI:</p>
  
  <p>How could it be modified to receive USB insertion/removal events?  Or, is there another way I should be going about this?  I am using Visual Studio 2008.  Thanks.</p>
  
  <p><strong><em>ADDITIONAL INFO</em></strong></p>
  
  <p>This is what I have so far (minus error-handling):</p>
  
  <pre><code>DEFINE_GUID(GUID_INTERFACE_CP210x, 0x993f7832, 0x6e2d, 0x4a0f, 0xb2, 0x72, 0xe2, 0xc7, 0x8e, 0x74, 0xf9, 0x3e);
  
  MyClass::MyClass()
  {
      // Generate message-only window
      _pWndClassEx = (WNDCLASSEX *)malloc( sizeof(WNDCLASSEX) );
      memset( _pWndClassEx, 0, sizeof(WNDCLASSEX) );
      _pWndClassEx-&gt;cbSize = sizeof(WNDCLASSEX);
      _pWndClassEx-&gt;lpfnWndProc = (WNDPROC)WndProc; // function which will handle messages
      _pWndClassEx-&gt;hInstance = GetCurrentModule();
      _pWndClassEx-&gt;lpszClassName = pClassName;
      atom = RegisterClassEx( _pWndClassEx );
      _hWnd = CreateWindowEx( 0, pClassName, pWindowName, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );
  
      // Register the USB device for notification
      _pDevIF = (DEV_BROADCAST_DEVICEINTERFACE *)malloc( sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
      memset( _pDevIF, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
      _pDevIF-&gt;dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
      _pDevIF-&gt;dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
      _pDevIF-&gt;dbcc_classguid = GUID_INTERFACE_CP210x;
      _hNotifyDevNode = RegisterDeviceNotification( _hWnd, _pDevIF, DEVICE_NOTIFY_WINDOW_HANDLE );
  }
  
  static bool OnDeviceChange(UINT nEventType, DWORD dwData)
  {
      switch ( nEventType )
      {
      case DBT_DEVICEARRIVAL:
          // A device has been inserted adn is now available.
          break;
  
      case DBT_DEVICEREMOVECOMPLETE:
          // Device has been removed.
          break;
  
      default:
          break;
      }
  
      return true;
  }
  
  static LRESULT WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
  {
      switch ( message )
      {
      case WM_DEVICECHANGE:
          OnDeviceChange( wParam, lParam ); // Set breakpoint (never gets here)
          break;
  
      default:
          break;
      }
  
      return DefWindowProc(hwnd, message, wParam, lParam);
  }
  </code></pre>
  
  <p>The PC gets into <code>WndProc</code>, but not when I remove/insert my USB device.  The PC never seems to get into <code>OnDeviceChange</code>.  Any tips would be appreciated.  I need to handle unexpected insertions/removals of the USB device.  If it makes a difference, the USB device appears as a virtual COM port to Windows.  Thanks.</p>
  
  <p><strong>Aditional info:</strong> Calling <code>CreateWindowEx</code> using the class <code>atom</code> returned by <code>RegisterClassEx</code> fails with the error message, "Cannot find window class."</p>
  
  <pre><code>_hWnd = CreateWindowEx( 0, (LPCTSTR)&amp;atom, pWindowName, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );
  </code></pre>
  
  <p><strong><em>NEW APPROACH</em></strong></p>
  
  <p>I'm also trying this new approach.  I'm trying to get write a message-only window to receive device change notification messages for a USB device.  I am using MFC, C++, and Visual Studio 2008.  Everything compiles, and it runs without crashing or locking up, but the event handler is never triggered.  The device of interest is installed on Windows as a virtual COM port.</p>
  
  <p>My main application instantiates the class described below then waits for a character input from the keyboard polling using a while loop.  It is during this wait time that I remove and insert my USB device expecting the event to get fired.</p>
  
  <pre><code>class CMessageOnlyWindow : public CWnd
  {
      DECLARE_DYNAMIC(CMessageOnlyWindow)
  private:
      DEV_BROADCAST_DEVICEINTERFACE * _pDevIF; // The notification filter.
      HDEVNOTIFY _hNotifyDev;             // The device notification handle.
  public:
      CMessageOnlyWindow();
      virtual ~CMessageOnlyWindow();
  protected:
      afx_msg BOOL OnDeviceChange( UINT nEventType, DWORD dwData );
  private:
      void RegisterNotification( void );
      void UnregisterNotification( void );
  protected:
      DECLARE_MESSAGE_MAP()               // Must be last.
  };
  </code></pre>
  
  <p>For simplicity, I've removed all the cleanup and error-handling:</p>
  
  <pre><code>DEFINE_GUID(GUID_INTERFACE_CP210x, 0x993f7832, 0x6e2d, 0x4a0f, \
      0xb2, 0x72, 0xe2, 0xc7, 0x8e, 0x74, 0xf9, 0x3e);
  
  IMPLEMENT_DYNAMIC(CMessageOnlyWindow, CWnd)
  
  CMessageOnlyWindow::CMessageOnlyWindow()
  {
      CString cstrWndClassName = ::AfxRegisterWndClass( NULL );
      BOOL bCreated = this-&gt;CreateEx( 0, cstrWndClassName,
          L"CMessageOnlyWindow", 0, 0, 0, 0, 0, HWND_MESSAGE, 0 );
      this-&gt;RegisterNotification();
  }
  
  CMessageOnlyWindow::~CMessageOnlyWindow() {}
  
  BEGIN_MESSAGE_MAP(CMessageOnlyWindow, CWnd)
      ON_WM_DEVICECHANGE()
  END_MESSAGE_MAP()
  
  afx_msg BOOL CMessageOnlyWindow::OnDeviceChange( UINT nEventType, DWORD dwData )
  {
      switch ( nEventType ) // &lt;-- Never gets here.
      {
      case DBT_DEVICEARRIVAL:
          break;
  
      case DBT_DEVICEREMOVECOMPLETE:
          break;
  
      default:
          break;
      }
  
      return TRUE;
  }
  
  void CMessageOnlyWindow::RegisterNotification(void)
  {
      _pDevIF = (DEV_BROADCAST_DEVICEINTERFACE *)malloc( sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
      memset( _pDevIF, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
      _pDevIF-&gt;dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
      _pDevIF-&gt;dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
      _pDevIF-&gt;dbcc_classguid = GUID_INTERFACE_CP210x;
      _hNotifyDev = RegisterDeviceNotification( this-&gt;m_hWnd, _pDevIF, DEVICE_NOTIFY_WINDOW_HANDLE );
  }
  
  void CMessageOnlyWindow::UnregisterNotification(void)
  {
      UnregisterDeviceNotification( _hNotifyDev );
  }
  </code></pre>
  
  <p>Any thoughts or suggestions would be much appreciated.  If any details are missing, let me know, and I will be glad to add them.  Thanks.</p>
  
  <p>Does the message-only window need to be started in a new thread, or does creating a new window automatically spin off a new thread?</p>