Ward Posted January 15, 2015 Posted January 15, 2015 (edited) I am trying to serialize all the autoit variable by >msgpack, so that I can used it in ZeroRPC (language-agnostic remote procedure call over internet). Int, string, binary are easy, but DllStruct is not. Before variable serialization become build-in function (I hope so), I have to find out my own way. Here is my attempt to guess the setup string. I am not sure did I deal with all the align and struct/endstruct correctly, please let me know if there is any bug. The output may not be the same with the original string, it is not bug. Test() Func Test() Local $Struct $Struct = DllStructCreate("align 2;byte;ptr[2]") ConsoleWrite(DLLStructAnalyze($Struct) & @LF) ; Output: byte;align 2;ptr[2] $Struct = DllStructCreate("int;struct;struct;uint64;uint;byte[5];endstruct;byte;endstruct;byte") ConsoleWrite(DLLStructAnalyze($Struct) & @LF) ; Output: int;struct;struct;uint64;uint;byte[5];endstruct;byte;endstruct;byte $Struct = DllStructCreate("int;uint64;struct;struct;uint;byte[5];endstruct;byte;endstruct;byte") ConsoleWrite(DLLStructAnalyze($Struct) & @LF) ; Output: int;uint64;struct;struct;uint;byte[5];endstruct;byte;endstruct;byte EndFunc expandcollapse popup#Include <Array.au3> Func DLLStructAnalyze(ByRef $DLLStruct) Local $Dict = __DLLStructAnalyzeHook(True) $Dict.Add($DLLStruct) __DLLStructAnalyzeHook(False) Return __DLLStructAnalyzeCallback(0) EndFunc Func __DLLStructAnalyzeCallback($Ptr) Static $Array[0], $Echo = ConsoleWrite If $Ptr = 0 Then Local $Ret = '' For $i = 0 To UBound($Array) - 1 Local $Item = $Array[$i] $Ret &= ($i ? ";" : "") & $Item[0] Next Return $Ret EndIf ReDim $Array[0] Local $Buffer = DllStructCreate("ptr", $Ptr) $Ptr = DllStructGetData($Buffer, 1) Local $Variant = DllStructCreate("word vt;word[3];ptr data;ptr record", $Ptr) Local $Type = DllStructGetData($Variant, "vt") If $Type = 36 Then Local $Record = DllStructGetData($Variant, "record") Local $RecordType = DllStructCreate("ptr;uint;uint type;ptr struct", $Record) If DllStructGetData($RecordType, "type") = 12 Then Local $Struct = DllStructCreate("uint count;ptr define;ptr base;uint size", DllStructGetData($RecordType, "struct")) Local $Count = DllStructGetData($Struct, "count") Local $Align = 8, $LastEnd = 0, $DefineSize = 0 For $i = 0 To $Count - 1 Local $Define = DllStructCreate("uint start;uint size;uint flag;ptr name;ptr;ptr;ptr;uint end", DllStructGetData($Struct, "define") + $i * $DefineSize) Local $DefineSize = DllStructGetSize($Define) Local $Start = DllStructGetData($Define, "start") Local $Size = DllStructGetData($Define, "size") Local $Flag = DllStructGetData($Define, "flag") Local $End = DllStructGetData($Define, "end") Local $Name = DllStructGetData($Define, "name") Local $Ret = DllCall("kernel32.dll", "int", "lstrlenW", "ptr", $Name) $Name = $Ret[0] ? " " & DllStructGetData(DllStructCreate("wchar[" & $Ret[0] & "]", $Name), 1) : "" $Echo("start: " & $Start & @TAB) $Echo("size: " & $Size & @TAB) $Echo("end: " & $End & @TAB) Local $NextAlign = 0 If $i > 0 Then $Pad = $Start - $LastEnd If Not ((Mod($Start, $Align) = 0 Or Mod($Start, $Size) = 0) And $Pad < $Align) Then $NextAlign = 1 $Echo("(pad" & $Pad & ") align 1") If Mod($Start, 2) = 0 And $Pad < 2 Then $Echo(" 2") $NextAlign = 2 EndIf If Mod($Start, 4) = 0 And $Pad < 4 Then $Echo(" 4") $NextAlign = 4 EndIf If Mod($Start, 8) = 0 And $Pad < 8 Then $Echo(" 8") $NextAlign = 8 EndIf $Echo("; ") If $NextAlign <> $Align Then $Align = $NextAlign Local $ItemAlign[] = ["align " & $Align, 0] ArrayAdd($Array, $ItemAlign) EndIf ElseIf $Pad <> 0 And $Pad >= $Size Then $Echo("(pad" & $Pad & ") endstruct; ") Local $ItemStruct[] = ["struct", 0] For $j = UBound($Array) - 1 To 0 Step -1 Local $Item = $Array[$j] If $Item[1] > $Pad Then ArrayInsert($Array, $j, $ItemStruct) ExitLoop EndIf Next Local $ItemEndStruct[] = ["endstruct", 0] ArrayAdd($Array, $ItemEndStruct) EndIf EndIf $LastEnd = $End Local $Type = "unknow" & $Name Select Case $Size = 1 And $Flag = 18 $Type = "byte" & $Name Case $Size = 1 And $Flag = 1 $Type = "char" & $Name Case $Size = 2 And $Flag = 32 $Type = "wchar" & $Name Case $Size = 2 And $Flag = 0 $Type = "short" & $Name Case $Size = 2 And $Flag = 2 $Type = "ushort" & $Name Case $Size = 4 And $Flag = 0 $Type = "int" & $Name Case $Size = 4 And $Flag = 2 $Type = "uint" & $Name Case $Size = 8 And $Flag = 0 $Type = "int64" & $Name Case $Size = 8 And $Flag = 2 $Type = "uint64" & $Name Case $Size = 4 And $Flag = 64 And Not @AutoItX64 $Type = "ptr" & $Name Case $Size = 8 And $Flag = 64 And @AutoItX64 $Type = "ptr" & $Name Case $Size = 4 And $Flag = 8 $Type = "float" & $Name Case $Size = 8 And $Flag = 8 $Type = "double" & $Name Case $Size = 1 And $Flag = 22 $Type = "byte" & $Name If $End - $Start = $Size Then $Type &= "[1]" Case $Size = 1 And $Flag = 5 $Type = "char" & $Name If $End - $Start = $Size Then $Type &= "[1]" Case $Size = 2 And $Flag = 36 $Type = "wchar" & $Name If $End - $Start = $Size Then $Type &= "[1]" EndSelect If $End - $Start <> $Size Then $Type &= "[" & Int(($End - $Start) / $Size) & "]" $Echo($Type & @LF) Local $Item[] = [$Type, $Size] ArrayAdd($Array, $Item) Next EndIf EndIf EndFunc Func __DLLStructAnalyzeHook($IsHook) Static $Callback, $CallbackPtr, $VTable, $InvokePtr, $CodeBuffer, $Hook = 0 Local $Dict = ObjCreate("Scripting.Dictionary") If Not $Hook Then $Callback = DllCallbackRegister(__DLLStructAnalyzeCallback, "none", "ptr") $CallbackPtr = DllCallbackGetPtr($Callback) Local $VTablePtr = DllStructCreate("ptr", Ptr($Dict)) $VTablePtr = DllStructGetData($VTablePtr, 1) $VTable = DllStructCreate("ptr[7]", $VTablePtr) $InvokePtr = DllStructGetData($VTable, 1, 7) Local $Code, $CallPtr, $JmpPtr If @AutoItX64 Then $Code = '0x41554154555756534883EC38488BB424980000008B9C24900000004889CF8954242C4C8944242044894C2428488BAC24A00000004889F14C8BA424A80000004C8BAC24B000000048B8FFFFFFFFFFFFFFFFFFD0448B4C24284C8B4424200FB7DB8B54242C4889F94C89AC24B00000004C89A424A80000004889AC24A00000004889B42498000000899C24900000004883C4385B5E5F5D415C415D48B8FFFFFFFFFFFFFFFFFFE0' $CallPtr = (StringInStr($Code, '48B8FFFFFFFFFFFFFFFFFFD0', 2) + 1) / 2 $JmpPtr = (StringInStr($Code, '48B8FFFFFFFFFFFFFFFFFFE0', 2) + 1) / 2 Else $Code = '0x5589E557565383EC3C8B45088B5D1C8B55248B4D288B75108B7D148945E48B450C891C248955D4894DD88945E08B45188945DC8B45208945D0B8FFFFFFFFFFD0508B45D08B4DD88B55D4895D1C897D148945200FB745DC897510894D288955248945188B45E089450C8B45E48945088D65F45B5E5F5DB8FFFFFFFFFFE0' $CallPtr = (StringInStr($Code, 'B8FFFFFFFFFFD0', 2) - 1) / 2 $JmpPtr = (StringInStr($Code, 'B8FFFFFFFFFFE0', 2) - 1) / 2 EndIf $Code = Binary($Code) $CodeBuffer = DllStructCreate("byte[" & BinaryLen($Code) & "]") $Hook = DllStructGetPtr($CodeBuffer) DllStructSetData($CodeBuffer, 1, $Code) DllCall("kernel32.dll", "bool", "VirtualProtect", "ptr", $Hook, "dword_ptr", BinaryLen($Code), "dword", 64, "dword*", 0) DllStructSetData(DllStructCreate("ptr", $Hook + $CallPtr), 1, $CallbackPtr) DllStructSetData(DllStructCreate("ptr", $Hook + $JmpPtr), 1, $InvokePtr) DllCall("kernel32.dll", "bool", "VirtualProtect", "ptr", $VTablePtr, "dword_ptr", @AutoItX64 ? 56 : 28, "dword", 4, "dword*", 0) EndIf If $IsHook Then DllStructSetData($VTable, 1, $Hook, 7) Return $Dict Else DllStructSetData($VTable, 1, $InvokePtr, 7) EndIf EndFunc Func ArrayAdd(ByRef $avArray, $vValue) If Not IsArray($avArray) Then Return SetError(1, 0, -1) If UBound($avArray, 0) <> 1 Then Return SetError(2, 0, -1) Local $iUBound = UBound($avArray) ReDim $avArray[$iUBound + 1] $avArray[$iUBound] = $vValue Return $iUBound EndFunc Func ArrayInsert(ByRef $avArray, $iElement, $vValue = "") If Not IsArray($avArray) Then Return SetError(1, 0, 0) If UBound($avArray, 0) <> 1 Then Return SetError(2, 0, 0) ; Check element in array bounds + 1 If $iElement > UBound($avArray) Then Return SetError(3, 0, 0) ; Add 1 to the array Local $iUBound = UBound($avArray) + 1 ReDim $avArray[$iUBound] ; Move all entries over til the specified element For $i = $iUBound - 1 To $iElement + 1 Step -1 $avArray[$i] = $avArray[$i - 1] Next ; Add the value in the specified element $avArray[$iElement] = $vValue Return $iUBound EndFunc Edited February 10, 2015 by Ward RTFC and trancexx 2 新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了。
RTFC Posted February 9, 2015 Posted February 9, 2015 (edited) Hi Ward, This would be an extremely useful function (to me, at least). However, on my test rig (W7Pro/64) it errors with: "D:\Autoit\Pool\dllstructAnalyze.au3" (18) : ==> Subscript used on non-accessible variable.: $Ret &= ($i ? ";" : "") & $Item[0] $Ret &= ($i ? ";" : "") & $Item^ ERROR This is when I include the analyzer as a separate file in your test example. If I simply append the analyzer to the test file, AutoIt crashes. Haven't done any detailed diagnostics. Edited February 9, 2015 by RTFC My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O
Ward Posted February 9, 2015 Author Posted February 9, 2015 (edited) Oh, this scrip crash on v3.3.12.0, because I still use v3.3.10.2... I fixed it. The problem is in the newer Array.au3 UDF. It did "concatenate" rather than "add" in _ArrayAdd(). (WTF...) Edited February 9, 2015 by Ward 新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了。
RTFC Posted February 10, 2015 Posted February 10, 2015 Perfect, Ward. Another outstanding contribution of yours! Thanks for sharing. My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O
JohnOne Posted February 10, 2015 Posted February 10, 2015 Is this just an oversight? Func DLLStructAnalyze(ByRef $DLLStruct) Local $Dict = __DLLStructAnalyzeHook(True) $Dict.Add($DLLStruct) Return __DLLStructAnalyzeCallback(0) __DLLStructAnalyzeHook(False); In C/++ terms it would mean unreachable code. EndFunc Not that I'd know what to do with the code anyway, just seen it. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans.
Ward Posted February 10, 2015 Author Posted February 10, 2015 Thanks JohnOne, It seems I pressed some hotkey that swapped these two lines by accident. 新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了。
Zehir Posted March 24, 2022 Posted March 24, 2022 (edited) Thank you I was looking for exactly that ! Edited April 1, 2022 by Zehir
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