Kay Sarraute
Kay Sarraute

Reputation: 1242

MSVC: Compiler bug on seemingly trivial C code?

Here's a simple, 45 line console application that reproduces the bug on my Win XP 32-bit system.

The relevant parts:

input_watcher_wndproc belongs to a window that was set-up via RegisterRawInputDevices to watch raw keyboard input events.

  LRESULT APIENTRY
  input_watcher_wndproc(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam) {
    switch(umsg) {
    case WM_INPUT:
      analyze_raw_input((HRAWINPUT)lparam);
      DefWindowProc(hwnd, umsg, wparam, lparam);
      return 0;
    }
    return DefWindowProc(hwnd, umsg, wparam, lparam);
  }

  void analyze_raw_input(HRAWINPUT raw_input) {
    RAWINPUTHEADER header;
    UINT size;
    GetRawInputData(raw_input, RID_HEADER, &header, &size, sizeof(RAWINPUTHEADER));
    printf("raw input device handle: %d\n", header.hDevice);
  }

When compiled with MSVC 9 or 10, the program always incorrectly reports the device handle to be "1".

However, if I apply some seemingly non-functional changes, like transforming the switch-statement into an if-statement...

    if (umsg == WM_INPUT) {
      analyze_raw_input((HRAWINPUT)lparam);
      DefWindowProc(hwnd, umsg, wparam, lparam);
      return 0;
    }

... or when adding an arbitrary instruction before the call to analyze_raw_input ...

  switch(umsg) {
   case WM_INPUT:
     puts("foo");
     analyze_raw_input((HRAWINPUT)lparam);
     DefWindowProc(hwnd, umsg, wparam, lparam);
     return 0;
   }

...the code runs fine and outputs the corrent device handle.

Here's the modified, working source code, with just the print statement added.

Any ideas what might cause this behaviour?

Upvotes: 0

Views: 177

Answers (1)

ribram
ribram

Reputation: 2450

Make sure to initialize 'size' to be sizeof(RAWINPUTHEADER) before calling GetRawInputData since this is an __inout parameter.

Upvotes: 2

Related Questions