Aether Posted November 27, 2018 Posted November 27, 2018 (edited) Hi there, I am in the process of learning how to translate C struct into autoit struct and I'm asking a probably dumb question. Why do I need end padding in autoit ? Here are the C struct : typedef struct tagINPUT { DWORD type; union { MOUSEINPUT mi; KEYBDINPUT ki; HARDWAREINPUT hi; } DUMMYUNIONNAME; } INPUT, *PINPUT, *LPINPUT; typedef struct tagKEYBDINPUT { WORD wVk; WORD wScan; DWORD dwFlags; DWORD time; ULONG_PTR dwExtraInfo; } KEYBDINPUT, *PKEYBDINPUT, *LPKEYBDINPUT; typedef struct tagMOUSEINPUT { LONG dx; LONG dy; DWORD mouseData; DWORD dwFlags; DWORD time; ULONG_PTR dwExtraInfo; } MOUSEINPUT, *PMOUSEINPUT, *LPMOUSEINPUT; Here are the autoit struct I was able to find and adapt: Global Const $tagKEYBDINPUT = _ 'dword type;' & _ ; 4 bytes 'ushort wVk;' & _ ; 2 bytes 'ushort wScan;' & _ ; 2 bytes 'dword dwFlags;' & _ ; 4 bytes 'dword time;' & _ ; 4 bytes 'ulong_ptr ExtraInfo;' & _ ; 4 bytes in x86 'dword pad1;' & _ ; 4 bytes 'dword pad2;' ; 4 bytes Global Const $tagMOUSEINPUT = _ "DWORD type;" & _ ; 4 bytes "long dx;" & _ ; 4 bytes "long dy;" & _ ; 4 bytes "long mouseData;" & _ ; 4 bytes "DWORD dwFlags;" & _ ; 4 bytes "DWORD time;" & _ ; 4 bytes "ULONG_PTR ExtraInfo;" ; 4 bytes in x86 As you can see both autoit struct put 8 bytes of padding at the end, can someone explain me why ? So far I was able to test keyboard input and it is working perfectly. Thanks in advance. Edit : I found the reason, you need padding when you have a union of structures. Padding is used to get the same size between different structures. Also I removed, the padding of the mouse struct as it was a bug in the original script ! Edited November 27, 2018 by Aether
Danyfirex Posted November 27, 2018 Posted November 27, 2018 Hello. Your structure's declaration seem to be wrong. I think correct way should look like this: expandcollapse popup#AutoIt3Wrapper_UseX64=y Global Const $tagHARDWAREINPUT = _ 'dword uMsg;' & _ ; 4 bytes 'word wParamL;' & _ ; 2 bytes 'word wParamL;' ; 2 bytes Global Const $tagKEYBDINPUT = _ 'word wVk;' & _ ; 2 bytes 'word wScan;' & _ ; 2 bytes 'dword dwFlags;' & _ ; 4 bytes 'dword time;' & _ ; 4 bytes 'ulong_ptr ExtraInfo;' ; sizeof(ptr) 4 for x86 - 8 for x64 Global Const $tagMOUSEINPUT = _ "long dx;" & _ ; 4 bytes "long dy;" & _ ; 4 bytes "dword mouseData;" & _ ; 4 bytes "dword dwFlags;" & _ ; 4 bytes "dword time;" & _ ; 4 bytes "ULONG_PTR ExtraInfo;" ; sizeof(ptr) 4 for x86 - 8 for x64 Global Const $tagINPUT = _ "dword type;byte DummyUnion[" & (@AutoItX64 ? 34 : 24) & "]" Local $tu = DllStructCreate($tagINPUT) ConsoleWrite("$tagINPUT: " & DllStructGetSize($tu) & @CRLF) Local $t0 = DllStructCreate($tagHARDWAREINPUT) ConsoleWrite("$tagHARDWAREINPUT: " & DllStructGetSize($t0) & @CRLF) Local $t1 = DllStructCreate($tagKEYBDINPUT) ConsoleWrite("$tagKEYBDINPUT: " & DllStructGetSize($t1) & @CRLF) Local $t2 = DllStructCreate($tagMOUSEINPUT) ConsoleWrite("$tagMOUSEINPUT: " & DllStructGetSize($t2) & @CRLF) ;~ 28 ;~ tagHARDWAREINPUT: 8 ;~ tagKEYBDINPUT: 16 ;~ tagMOUSEINPUT: 24 ;~ 40 ;~ tagHARDWAREINPUT: 8 ;~ tagKEYBDINPUT: 24 ;~ tagMOUSEINPUT: 32 Saludos Danysys.com AutoIt... UDFs: VirusTotal API 2.0 UDF - libZPlay UDF - Apps: Guitar Tab Tester - VirusTotal Hash Checker Examples: Text-to-Speech ISpVoice Interface - Get installed applications - Enable/Disable Network connection PrintHookProc - WINTRUST - Mute Microphone Level - Get Connected NetWorks - Create NetWork Connection ShortCut
Nine Posted November 27, 2018 Posted November 27, 2018 (edited) Hi Danyfirex, I agree that your declaration is more in line with the reality of the original C typedef. On the other hand, I like to set the structure data by name instead by offset (reduce possible mistakes). Since you would create the struct like you did : Local $tu = DllStructCreate($tagINPUT) I would not be able to access the structure by name, unless there is another way that I don't know of. Edited November 27, 2018 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
Danyfirex Posted November 27, 2018 Posted November 27, 2018 @Nine What do you mean? Saludos Danysys.com AutoIt... UDFs: VirusTotal API 2.0 UDF - libZPlay UDF - Apps: Guitar Tab Tester - VirusTotal Hash Checker Examples: Text-to-Speech ISpVoice Interface - Get installed applications - Enable/Disable Network connection PrintHookProc - WINTRUST - Mute Microphone Level - Get Connected NetWorks - Create NetWork Connection ShortCut
Nine Posted November 27, 2018 Posted November 27, 2018 It would not be possible to do something like : Local $tu = DllStructCreate($tagINPUT) DllStructSetData($tu, "type", 0) DllStructSetData($tu, "dx", 100) DllStructSetData($tu, "dy", 200) Right ? “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
Danyfirex Posted November 27, 2018 Posted November 27, 2018 It happens because AutoIt don't allow union as C but you always can use a reference pointer. expandcollapse popupGlobal Const $tagHARDWAREINPUT = _ 'dword uMsg;' & _ ; 4 bytes 'word wParamL;' & _ ; 2 bytes 'word wParamL;' ; 2 bytes Global Const $tagKEYBDINPUT = _ 'word wVk;' & _ ; 2 bytes 'word wScan;' & _ ; 2 bytes 'dword dwFlags;' & _ ; 4 bytes 'dword time;' & _ ; 4 bytes 'ulong_ptr ExtraInfo;' ; sizeof(ptr) 4 for x86 - 8 for x64 Global Const $tagMOUSEINPUT = _ "long dx;" & _ ; 4 bytes "long dy;" & _ ; 4 bytes "dword mouseData;" & _ ; 4 bytes "dword dwFlags;" & _ ; 4 bytes "dword time;" & _ ; 4 bytes "ULONG_PTR ExtraInfo;" ; sizeof(ptr) 4 for x86 - 8 for x64 Global Const $tagINPUT = _ "dword type;byte DummyUnion[" & (@AutoItX64 ? 34 : 24) & "]" Local $tu = DllStructCreate($tagINPUT) ConsoleWrite("$tagINPUT: " & DllStructGetSize($tu) & @CRLF) Local $tu = DllStructCreate($tagINPUT) Local $tm = DllStructCreate($tagMOUSEINPUT, DllStructGetPtr($tu, "DummyUnion")) DllStructSetData($tu, "type", 1) DllStructSetData($tm, "dx", 2) DllStructSetData($tm, "dy", 3) ConsoleWrite('DllStructSetData($tu, "type", 1)= ' & DllStructGetData($tu, "type") & @CRLF) ConsoleWrite('DllStructSetData($tm, "dx", 1)= ' & DllStructGetData($tm, "dx") & @CRLF) ConsoleWrite('DllStructSetData($tm, "dy", 1)= ' & DllStructGetData($tm, "dy") & @CRLF) ConsoleWrite('DllStructSetData($tu, "byte", 1)= ' & DllStructGetData($tu, "DummyUnion") & @CRLF) Saludos Nine 1 Danysys.com AutoIt... UDFs: VirusTotal API 2.0 UDF - libZPlay UDF - Apps: Guitar Tab Tester - VirusTotal Hash Checker Examples: Text-to-Speech ISpVoice Interface - Get installed applications - Enable/Disable Network connection PrintHookProc - WINTRUST - Mute Microphone Level - Get Connected NetWorks - Create NetWork Connection ShortCut
Aether Posted November 27, 2018 Author Posted November 27, 2018 Thank you guys, it was a very enlightening convo. I will definitely replace my autoit struct with yours Danyfirex. Still have a question for you regarding x64. Based on your info, the largest struct is the mouse at 32 bytes. So DummyUnion shouldn't it also be at 32 bytes ? I suppose that with alignment "type" has to be on 8 bytes slot, that's why you end up with a 40 bytes struct at x64 ? That's maybe the reason you have DummyUnion at 34 bytes ? So my guess is that the struct should be : Global Const $tagINPUT = _ "dword type;" _ & (@AutoItX64 ? "dword pad;" : "") _ & "byte DummyUnion[" & (@AutoItX64 ? 32 : 24) & "]" ???
Danyfirex Posted November 27, 2018 Posted November 27, 2018 I'm sure type need to be 4 byte ( a long). I think the pad ins for the end probably no needed I just checked the size of the structure on x64 version using C++ so I assumed pad is at the end because It return size = 40. Do some test and check if you get correct values. Saludos Danysys.com AutoIt... UDFs: VirusTotal API 2.0 UDF - libZPlay UDF - Apps: Guitar Tab Tester - VirusTotal Hash Checker Examples: Text-to-Speech ISpVoice Interface - Get installed applications - Enable/Disable Network connection PrintHookProc - WINTRUST - Mute Microphone Level - Get Connected NetWorks - Create NetWork Connection ShortCut
Aether Posted November 28, 2018 Author Posted November 28, 2018 (edited) 47 minutes ago, Danyfirex said: I'm sure type need to be 4 byte ( a long). I think the pad ins for the end probably no needed I just checked the size of the structure on x64 version using C++ so I assumed pad is at the end because It return size = 40. Do some test and check if you get correct values. Saludos Done testing and it is what I was thinking : Global Const $tagINPUT = _ "dword type;" & _ (@AutoItX64 ? "dword pad;" : "") & _ "byte DummyUnion[" & (@AutoItX64 ? 32 : 24) & "]" Works perfectly well on 32 and 64. But your 34 array was giving me error. But thank you very much for the teaching you have giving me. Cause I would have struggle a lot to understand all the subtleties of struct Edited November 28, 2018 by Aether Danyfirex 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now