GetRawInputData header.hDevice is NULL for builtin touchpad only

Wallby 46 Reputation points
2024-05-14T15:19:16.1966667+00:00

I've tested both using mingw and visual studio 2022 with C17. I have tested with two external mice, for both of them <RAWINPUT>.header.hDevice is always not NULL. For the builtin keyboard it is also not NULL. Only the builtin touchpad. I've also used GetRawInputDeviceList and <RAWINPUTDEVICELIST>.hDevice is not NULL for the touchpad, only the <RAWINPUT>.header.hDevice in WNDPROC with WM_INPUT is for the touchpad mouse and only for the touchpad mouse. I've tried to assume that the mouse element (i.e. with RID_TYPEMOUSE) for the builtin touchpad is always the last mouse element in the RAWINPUTDEVICELIST elements (which it was initially), but that also proved to not be the case.

Is this a bug with my specific touchpad? Is there any way to figure out which device has the NULL hDevice? Even the WM_INPUT_DEVICE_CHANGE sent for every device at the start never has NULL for the lParam.

Here's information on the code I've used..

My application doesn't have any memory leaks (I've checked using wrap malloc and wrap free).

I've registered two RAWINPUTDEVICE elements, both have..

  • dwFlags == RIDEV_DEVNOTIFY | RIDEV_INPUTSINK
  • hwndTarget != NULL
  • usUsagePage == HID_USAGE_PAGE_GENERIC

One has usUsage == HID_USAGE_GENERIC_MOUSE The other has usUsage == HID_USAGE_GENERIC_KEYBOARD

Here is the GetRawInputData code in the WNDPROC for WM_INPUT..

struct
{
  PRAWINPUT a;
} prawinput = { .a = NULL };

do
{
  struct
  {
    HRAWINPUT a;
  } hrawinput = { .a = (HRAWINPUT)lParam };

  UINT a;
  if(GetRawInputData(hrawinput.a, RID_HEADER, NULL, &a, sizeof(RAWINPUTHEADER)) != 0)
  {
    //... //< print GetLastError using FormatMessage
    break;
  }

  prawinput.a = malloc(a);
  UINT a = GetRawInputData((HRAWINPUT)lParam, RID_HEADER, prawinput.a, &a, sizeof(RAWINPUTHEADER));
  printf("%u bytes copied into prawinput.a\n", a);
  printf("sizeof(<RAWINPUT>.header) %i\n", sizeof(prawinput.a->header));
  printf("sizeof(<RAWINPUT>.data) %i\n", sizeof(prawinput.a->data));
  printf("sizeof(<RAWINPUT>.mouse %i sizeof(<RAWINPUT>.keyboard) %i sizeof(<RAWINPUT>.hid) %i\n",  sizeof(prawinput.a->data.mouse), sizeof(prawinput.a->data.keyboard), sizeof(prawinput.a->data.hid));
  if(a == (UINT)-1)
  {
    //... //< print GetLastError using FormatMessage
    break;
  }

  printf("<RAWINPUT>->header.hDevice %p\n", prawinput.a->header.hDevice);

  //...
} while(0);
if(prawinput.a != NULL)
{
  free(prawinput.a);
}

The message after the second GetRawInputData prints "24 bytes copied into prawinput.a" if using RID_HEADER and "48 bytes copied into prawinput.a" if using RID_INPUT. In both cases the last message printed is "<RAWINPUT>->header.hDevice 0000000000000000".

Windows 10
Windows 10
A Microsoft operating system that runs on personal computers and tablets.
10,847 questions
0 comments No comments
{count} votes