winapifirefox-addonjsctypes

tagRAWMOUSE Structure Issues


I have set up Raw Input to trigger WM_INPUT on my message window. I have set up input for mouse. I am succesfully getting messages and calling GetRawInputData().

I followed the documentation to the letter but it is being a bit silly.

The docs say this is the struct I receive:

RAWMOUSE structure

So I am doing this from ctypes so this is why im getting into this.

When I do a mouse wheel up I get this:

tagRAWMOUSE(0, 0, 1024, 0, 0, 0, 0)

and when I do mouse wheel down I get the exact same thing:

tagRAWMOUSE(0, 0, 1024, 0, 0, 0, 0)

As a guide, when I just do a mouse move my mouse it gets this:

tagRAWMOUSE(0, 0, 0, 0, 0, 1, 0)

I set up my struct with the union as 2 USHORT as my ctypes does not support union:

this.RAWMOUSE = ctypes.StructType('tagRAWMOUSE', [
    { usFlags: this.USHORT },
    { usButtonFlags: this.USHORT },
    { usButtonData: this.USHORT },
    { ulRawButtons: this.ULONG },
    { lLastX: this.LONG },
    { lLastY: this.LONG },
    { ulExtraInformation: this.ULONG }
]);

Does anyone see anything wrong?


Solution

  • Let's re-cap the C++ definition of the struct since it is important:

    typedef struct tagRAWMOUSE {
      USHORT usFlags;
      union {
        ULONG  ulButtons;
        struct {
          USHORT usButtonFlags;
          USHORT usButtonData;
        };
      };
      ULONG  ulRawButtons;
      LONG   lLastX;
      LONG   lLastY;
      ULONG  ulExtraInformation;
    } RAWMOUSE, *PRAWMOUSE, *LPRAWMOUSE;
    

    The union is messing up your alignment. The union needs to be aligned so that all of its members is aligned. Because the union has a ULONG member, namely ulButtons, the union's alignment is 4 bytes. Therefore the union has to be placed at an offset that is a multiple of 4. In this case that places it at offset 4. And so there are two bytes of padding immediately after usFlags.

    In your ctypes struct, the two USHORT members of the union that overlay that ULONG, namely usButtonFlags and usButtonData have alignment 2. Therefore they are placed at offsets 2 and 4. And the padding has been lost in translation.

    This sort of thing is very common, and is one of the first things you check when translating a struct. Dig out a C++ compiler and get it to emit the size of the struct, and the offsets for all the members. Compare that with the same information from your translation. If they don't match, work out why.

    You have a couple of ways to fix it: