title: PeekMessage triggers WndProc callback
body: <p>Yesterday I encountered the weirdest problem I have ever seen.
  I wrote a module that should get a notification on USB plugs.
  To do so, I created a dummy window and registered it to device change notifications using some interface's <code>GUID</code>.</p>
  
  <p>The strange error occurs when <code>PeekMessage</code> is called.
  at this point, some why, the window's WndProc callback is called, only when the peeked message is <code>WM_DEVICECHANGE</code> (we were registered to in the above code).
  On any other message, the DispatchMessage triggers the callback, as expected.</p>
  
  <p>code:</p>
  
  <pre><code>NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
  NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  NotificationFilter.dbcc_classguid = guid;
  not = RegisterDeviceNotification(
      hWnd,     // events recipient
      &amp;NotificationFilter,        // type of device
      DEVICE_NOTIFY_WINDOW_HANDLE // type of recipient handle
  );
  </code></pre>
  
  <p>In order to incorporate this module with the rest of my code which is asynchronous, using <code>Reactor</code> design pattern with <code>Windows Events</code>, and following the advice of stackoverflow community members, I incorporated <code>MsgWaitForMultipleObjects</code> in order to listen for events and windows messages as well.</p>
  
  <p>code:</p>
  
  <pre><code>for (;;)
  {
      dwRetval = MsgWaitForMultipleObjects(cntEvents, arrEvents, FALSE, INFINITE, QS_ALLINPUT);
      switch (dwRetval)
      {
      case WAIT_FAILED:
          // failed. TODO: status
          break;
      // TODO: handle abandoned.
      default:
          if (dwRetval == cntEvents)
          {
              // Message has popped.
              BOOL x = PeekMessage(&amp;tMsg, hWnd, 0, 0, PM_REMOVE); &lt;---- WM_DEVICECHANGE triggers the callback
              if (x)
              {
                  TranslateMessage(&amp;tMsg);
                  DispatchMessage(&amp;tMsg);
              }
          }
          else if (dwRetval &lt; cntEvents)
          {
              // event signaled
          }
          else
          {
              // TODO: status. unexpected.
              return FALSE; // unexpected failure
          }
          break;
      }
  }
  </code></pre>
  
  <p>I disassembled the code, and compared the registers before any call to <code>NtUserPeekMessage</code></p>
  
  <p>Registers on successful call:</p>
  
  <pre><code>RAX = 00000059A604EFB0 RBX = 0000000000000000 RCX = 00000059A604EF18
  RDX = 0000000000070C62 RSI = 00000059A604EF18 RDI = 0000000000070C62
  R8  = 0000000000000000 R9  = 0000000000000000 R10 = 00007FF71A65D800
  R11 = 0000000000000246 R12 = 0000000000000000 R13 = 0000000000000000
  R14 = 0000000000000000 R15 = 0000000000000000 RIP = 00007FF954562AA1
  RSP = 00000059A604EE70 RBP = 0000000000000000 EFL = 00000200 
  </code></pre>
  
  <p>Registers on unknown callback trigger call:</p>
  
  <pre><code>RAX = 00000059A604EFB0 RBX = 0000000000000000 RCX = 00000059A604EF18
  RDX = 0000000000070C62 RSI = 00000059A604EF18 RDI = 0000000000070C62
  R8  = 0000000000000000 R9  = 0000000000000000 R10 = 00007FF71A65D800
  R11 = 0000000000000246 R12 = 0000000000000000 R13 = 0000000000000000
  R14 = 0000000000000000 R15 = 0000000000000000 RIP = 00007FF954562AA1
  RSP = 00000059A604EE70 RBP = 0000000000000000 EFL = 00000200 
  </code></pre>
  
  <p><strong>The registers are exactly the same!</strong> (No parameters are passed on the stack, 64bit..)</p>
  
  <p>In both cases (<em>strange error</em> and <em>expected flow</em>) I stepped into at <code>NtUserPeekMessage</code>, it turns out that the <code>WndProc</code> callback is triggered only from the internal syscall!</p>
  
  <pre><code>00007FF954562A80  mov         r10,rcx  
  00007FF954562A83  mov         eax,1003h  
  00007FF954562A88  syscall  
  </code></pre>
  
  <p>I couldn't find any documentation on MSDN or explanation on the internet to the phenomenon.</p>
  
  <p>I would really like some help,
  Thanks in advance.</p>