Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with field alignment padding of the RAWMOUSE struct #106

Open
nunomluz opened this issue Jun 3, 2020 · 0 comments
Open

Issue with field alignment padding of the RAWMOUSE struct #106

nunomluz opened this issue Jun 3, 2020 · 0 comments

Comments

@nunomluz
Copy link

nunomluz commented Jun 3, 2020

While using GetRawInputData, I've stumbled upon an issue where the value of UsButtonFlags is apparently placed inside UsButtonData.

After looking at the code, I noticed the Pad_cgo_0 field and got to read a bit about the beautiful world of field alignment in C. I still don't know much about it but here's what worked in my case:

type MYRAWMOUSE struct {
	UsFlags            uint16
	Pad_cgo_0          [2]byte
	UsButtonFlags      uint16
	UsButtonData       uint16
	UlRawButtons       uint32
	LLastX             int32
	LLastY             int32
	UlExtraInformation uint32
}

By just moving that padding above UsButtonFlags it seems to work just fine, even for the info in LLastX and LLastY.
I was wondering about creating a PR but then noticed this might work differently depending on the target architecture. Can you please give me your thoughts on this? Is it safe to move that padding field, or will I have to look out for its position depending on my compiler target?

EDIT:
I did some more investigation on this and here's an interesting read on the subject: http://www.catb.org/esr/structure-packing/

I've also checked the paddings using this code:

/*
#include <windows.h>
*/
import "C"
import (
	"github.com/davecgh/go-spew/spew"
)

func main() {
	var test C.RAWMOUSE
	spew.Dump(test)
}

Built for both 32bit and 64bit Windows:

set GOARCH=386 && go build -o ./build/Debug/test_offset_386.exe ./cmd/testoffset
set GOARCH=amd64 && go build -o ./build/Debug/test_offset_amd64.exe ./cmd/testoffset

Here's the output for 32bit:

$ ./build/Debug/test_offset_386.exe
(main._Ctype_struct_tagRAWMOUSE) {
 usFlags: (main._Ctype_ushort) 0,
 _: ([2]uint8) (len=2 cap=2) {
  00000000  00 00                                             |..|
 },
 anon0: ([4]uint8) (len=4 cap=4) {
  00000000  00 00 00 00                                       |....|
 },
 ulRawButtons: (main._Ctype_ulong) 0,
 lLastX: (main._Ctype_long) 0,
 lLastY: (main._Ctype_long) 0,
 ulExtraInformation: (main._Ctype_ulong) 0
}

Here's the output for 64bit:

$ ./build/Debug/test_offset_amd64.exe
(main._Ctype_struct_tagRAWMOUSE) {
 usFlags: (main._Ctype_ushort) 0,
 _: ([2]uint8) (len=2 cap=2) {
  00000000  00 00                                             |..|
 },
 anon0: ([4]uint8) (len=4 cap=4) {
  00000000  00 00 00 00                                       |....|
 },
 ulRawButtons: (main._Ctype_ulong) 0,
 lLastX: (main._Ctype_long) 0,
 lLastY: (main._Ctype_long) 0,
 ulExtraInformation: (main._Ctype_ulong) 0
}

You might need to check the RAWMOUSE struct and the Windows data type docs to make some sense of the above output.
The output is pretty much the same and the padding is set above the usButtonFlags+usButtonData inner struct. Maybe I need an actual 32bit machine for it to be different (not sure).
I wonder if the current Golang structure in this repo is prepared for 32bit builds since the commit was made in July 2012, or if this has been a bug all along 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant