├── Icons ├── Structor.ico └── Verifier.ico ├── Img ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png └── 9.png ├── Lib ├── AutoXYWH.ahk ├── CreateGradient.ahk ├── MSVC2022.ahk └── RunGetStdout.ahk ├── README.md ├── Structor.ahk └── Verifier.ahk /Icons/Structor.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telppa/Structor/1fa5cc15d7ff518df3b5a5725fe08501f367e908/Icons/Structor.ico -------------------------------------------------------------------------------- /Icons/Verifier.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telppa/Structor/1fa5cc15d7ff518df3b5a5725fe08501f367e908/Icons/Verifier.ico -------------------------------------------------------------------------------- /Img/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telppa/Structor/1fa5cc15d7ff518df3b5a5725fe08501f367e908/Img/1.png -------------------------------------------------------------------------------- /Img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telppa/Structor/1fa5cc15d7ff518df3b5a5725fe08501f367e908/Img/2.png -------------------------------------------------------------------------------- /Img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telppa/Structor/1fa5cc15d7ff518df3b5a5725fe08501f367e908/Img/3.png -------------------------------------------------------------------------------- /Img/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telppa/Structor/1fa5cc15d7ff518df3b5a5725fe08501f367e908/Img/4.png -------------------------------------------------------------------------------- /Img/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telppa/Structor/1fa5cc15d7ff518df3b5a5725fe08501f367e908/Img/5.png -------------------------------------------------------------------------------- /Img/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telppa/Structor/1fa5cc15d7ff518df3b5a5725fe08501f367e908/Img/6.png -------------------------------------------------------------------------------- /Img/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telppa/Structor/1fa5cc15d7ff518df3b5a5725fe08501f367e908/Img/7.png -------------------------------------------------------------------------------- /Img/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telppa/Structor/1fa5cc15d7ff518df3b5a5725fe08501f367e908/Img/8.png -------------------------------------------------------------------------------- /Img/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telppa/Structor/1fa5cc15d7ff518df3b5a5725fe08501f367e908/Img/9.png -------------------------------------------------------------------------------- /Lib/AutoXYWH.ahk: -------------------------------------------------------------------------------- 1 | ; ================================================================================= 2 | ; Function: AutoXYWH 3 | ; Move and resize controls automatically when the window is resized. 4 | ; 5 | ; Parameters: 6 | ; DimSize - Can be one or more of x/y/w/h, optionally followed by a fraction. 7 | ; The presence of an asterisk in this parameter indicates that the 8 | ; controls are to be moved/resized with 'MoveDraw' instead of 'Move'. 9 | ; This is recommended for GroupBoxes. 10 | ; 11 | ; cList - Variadic list of ControlIDs. 12 | ; ControlID can be a control HWND, associated variable name, ClassNN 13 | ; or displayed text. The latter (displayed text) may not be reliable. 14 | ; Examples: 15 | ; AutoXYWH("xy", "Btn1", "Btn2") 16 | ; AutoXYWH("w0.5 h 0.75", hEdit, "displayed text", "vLabel", "Button1") 17 | ; AutoXYWH("*w0.5 h 0.75", hGroupbox1, "GrbChoices") 18 | ; --------------------------------------------------------------------------------- 19 | ; Version: 2015-5-29 / Added 'reset' option (by tmplinshi) 20 | ; 2014-7-03 / toralf 21 | ; 2014-1-2 / tmplinshi 22 | ; Mininum AHK version: 1.1.13.01. 23 | ; Forum topic: https://www.autohotkey.com/boards/viewtopic.php?t=1079 24 | ; ================================================================================= 25 | 26 | AutoXYWH(DimSize, cList*) { 27 | Static cInfo := {} 28 | 29 | If (DimSize = "reset") { 30 | Return cInfo := {} 31 | } 32 | 33 | For i, ctrl in cList { 34 | ctrlID := A_Gui ":" ctrl 35 | If (cInfo[ctrlID].x = "") { 36 | GuiControlGet i, %A_Gui%: Pos, %ctrl% 37 | MMD := InStr(DimSize, "*") ? "MoveDraw" : "Move" 38 | fx := fy := fw := fh := 0 39 | For i, dim in (a := StrSplit(RegExReplace(DimSize, "i)[^xywh]"))) { 40 | If (!RegExMatch(DimSize, "i)" . dim . "\s*\K[\d.-]+", f%dim%)) { 41 | f%dim% := 1 42 | } 43 | } 44 | cInfo[ctrlID] := {x: ix, fx: fx, y: iy, fy: fy, w: iw, fw: fw, h: ih, fh: fh, gw: A_GuiWidth, gh: A_GuiHeight, a: a, m: MMD} 45 | } Else If (cInfo[ctrlID].a.1) { 46 | dgx := dgw := A_GuiWidth - cInfo[ctrlID].gw, dgy := dgh := A_GuiHeight - cInfo[ctrlID].gh 47 | Options := "" 48 | For i, dim in cInfo[ctrlID]["a"] { 49 | Options .= dim . (dg%dim% * cInfo[ctrlID]["f" . dim] + cInfo[ctrlID][dim]) . A_Space 50 | } 51 | GuiControl, % A_Gui ":" cInfo[ctrlID].m, % ctrl, % Options 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Lib/CreateGradient.ahk: -------------------------------------------------------------------------------- 1 | ; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=91899 2 | 3 | CreateGradient(W, H, V, aColors) { 4 | Local 5 | 6 | C := aColors.Length() 7 | 8 | xOFF := (X := V ? W : 0) ? 0 : Ceil(W / (C - 1)) 9 | yOFF := (Y := V ? 0 : H) ? 0 : Ceil(H / (C - 1)) 10 | 11 | VarSetCapacity(VERT, C * 16, 0) 12 | VarSetCapacity(MESH, C * 8, 0) 13 | 14 | Loop % (C, pVert := &VERT, pMesh := &MESH) { 15 | X := V ? (X == 0 ? W : X := 0) : X 16 | Y := !V ? (Y == 0 ? H : Y := 0) : Y 17 | Color := Format("{:06X}", aColors[A_Index] & 0xFFFFFF) 18 | Color := Format("0x{5:}{6:}00{3:}{4:}00{1:}{2:}00", StrSplit(Color)*) 19 | pVert := NumPut(Color, NumPut(Y, NumPut(X, pVert+0, "Int"), "Int"), "Int64") 20 | pMesh := NumPut(A_Index, NumPut(A_Index - 1, pMesh+0, "Int"), "Int") 21 | V ? (Y += yOFF) : (X += xOFF) 22 | } 23 | 24 | hBM := DllCall("Gdi32.dll\CreateBitmap", "Int", 1, "Int", 1, "Int", 0x1, "Int", 32, "Ptr*", 0, "Ptr") 25 | hBM := DllCall("User32.dll\CopyImage", "Ptr", hBM, "Int", 0x0, "Int", W, "Int", H, "Int", 0x8, "Ptr") 26 | mDC := DllCall("Gdi32.dll\CreateCompatibleDC", "Ptr", 0, "Ptr") 27 | DllCall("Gdi32.dll\SaveDC", "Ptr", mDC) 28 | DllCall("Gdi32.dll\SelectObject", "Ptr", mDC, "Ptr", hBM) 29 | DllCall("Msimg32.dll\GradientFill", "Ptr", mDC, "Ptr", &VERT, "Int", C, "Ptr", &MESH, "Int", C - 1, "Int", !!V) 30 | DllCall("Gdi32.dll\RestoreDC", "Ptr", mDC, "Int", -1) 31 | DllCall("Gdi32.dll\DeleteDC", "Ptr", mDC) 32 | 33 | Return hBM 34 | } 35 | -------------------------------------------------------------------------------- /Lib/MSVC2022.ahk: -------------------------------------------------------------------------------- 1 | if (FileExist("MSVC2022")="D") 2 | { 3 | ; Structor.ini 配置 4 | IniWrite, %A_ScriptDir%\MSVC2022\VC\Tools\MSVC\14.30.30705\bin\Hostx64\x86\cl.exe, Structor.ini, Compiler, CompilerPath32 5 | IniWrite, %A_ScriptDir%\MSVC2022\VC\Auxiliary\Build\vcvars32.bat, Structor.ini, Compiler, BatchFile32 6 | IniWrite, %A_ScriptDir%\MSVC2022\VC\Tools\MSVC\14.30.30705\bin\Hostx64\x64\cl.exe, Structor.ini, Compiler, CompilerPath64 7 | IniWrite, %A_ScriptDir%\MSVC2022\VC\Auxiliary\Build\vcvars64.bat, Structor.ini, Compiler, BatchFile64 8 | IniWrite, 1, Structor.ini, Settings, 64bitOffsets 9 | IniWrite, 1, Structor.ini, Settings, 32bitOffsets 10 | 11 | ; Verifier.ini 配置 12 | IniWrite, %A_ScriptDir%\MSVC2022\VC\Tools\MSVC\14.30.30705\bin\Hostx64\x86\cl.exe, Verifier.ini, Visual Studio, CompilerPath 13 | IniWrite, %A_ScriptDir%\MSVC2022\VC\Auxiliary\Build\vcvars32.bat, Verifier.ini, Visual Studio, BatchFile 14 | IniWrite, %A_ScriptDir%\MSVC2022\VC\Tools\MSVC\14.30.30705\bin\Hostx64\x64\cl.exe, Verifier.ini, Visual Studio, CompilerPath64 15 | IniWrite, %A_ScriptDir%\MSVC2022\VC\Auxiliary\Build\vcvars64.bat, Verifier.ini, Visual Studio, BatchFile64 16 | } 17 | else 18 | { 19 | if (A_ScriptName="Structor.ahk") 20 | { 21 | IniRead, OutputVar32, Structor.ini, Compiler, CompilerPath32, %A_Space% 22 | IniRead, OutputVar64, Structor.ini, Compiler, CompilerPath64, %A_Space% 23 | if (!OutputVar32 and !OutputVar64) 24 | 提示下载完整版 := 1 25 | } 26 | if (A_ScriptName="Verifier.ahk") 27 | { 28 | IniRead, OutputVar32, Verifier.ini, Visual Studio, CompilerPath, %A_Space% 29 | IniRead, OutputVar64, Verifier.ini, Visual Studio, CompilerPath64, %A_Space% 30 | IniRead, OutputVar32_2, Verifier.ini, MinGW, CompilerPath, %A_Space% 31 | IniRead, OutputVar64_2, Verifier.ini, MinGW, CompilerPath64, %A_Space% 32 | if (!OutputVar32 and !OutputVar64 and !OutputVar32_2 and !OutputVar64_2) 33 | 提示下载完整版 := 1 34 | } 35 | } 36 | 37 | if (提示下载完整版) 38 | { 39 | Instruction := "没有找到编译器。" 40 | Content := "本工具需要指定 C++ 编译器才能正常运行。`r`n建议从下方下载一个带编译器的完整版使用。" 41 | Title := A_ScriptName 42 | MainIcon := 0xFFFF 43 | Flags := 0x10 44 | CustomButtons := [] 45 | CustomButtons.Push([101, "前往 Github 下载完整版。"]) 46 | CustomButtons.Push([102, "前往 AutoAHK 下载完整版。"]) 47 | CustomButtons.Push([103, "我有编译器。"]) 48 | cButtons := CustomButtons.Length() 49 | VarSetCapacity(pButtons, 4 * cButtons + A_PtrSize * cButtons, 0) 50 | Loop %cButtons% { 51 | iButtonID := CustomButtons[A_Index][1] 52 | iButtonText := &(b%A_Index% := CustomButtons[A_Index][2]) 53 | NumPut(iButtonID, pButtons, (4 + A_PtrSize) * (A_Index - 1), "Int") 54 | NumPut(iButtonText, pButtons, (4 + A_PtrSize) * A_Index - A_PtrSize, "Ptr") 55 | } 56 | 57 | ; TASKDIALOGCONFIG structure 58 | x64 := A_PtrSize == 8 59 | NumPut(VarSetCapacity(TDC, x64 ? 160 : 96, 0), TDC, 0, "UInt") ; cbSize 60 | NumPut(Flags, TDC, x64 ? 20 : 12, "Int") ; dwFlags 61 | NumPut(&Title, TDC, x64 ? 28 : 20, "Ptr") ; pszWindowTitle 62 | NumPut(MainIcon, TDC, x64 ? 36 : 24, "Ptr") ; pszMainIcon 63 | NumPut(&Instruction, TDC, x64 ? 44 : 28, "Ptr") ; pszMainInstruction 64 | NumPut(&Content, TDC, x64 ? 52 : 32, "Ptr") ; pszContent 65 | NumPut(cButtons, TDC, x64 ? 60 : 36, "UInt") ; cButtons 66 | NumPut(&pButtons, TDC, x64 ? 64 : 40, "Ptr") ; pButtons 67 | 68 | DllCall("Comctl32.dll\TaskDialogIndirect", "Ptr", &TDC 69 | , "Int*", Button := 0 70 | , "Int*", Radio := 0 71 | , "Int*", Checked := 0) 72 | 73 | If (Button == 101) { ; 前往 Github 下载完整版。 74 | Run, https://github.com/telppa/Structor 75 | ExitApp 76 | } Else If (Button == 102) { ; 前往 AutoAHK 下载完整版。 77 | Run, https://www.autoahk.com/archives/39950 78 | ExitApp 79 | } 80 | } -------------------------------------------------------------------------------- /Lib/RunGetStdout.ahk: -------------------------------------------------------------------------------- 1 | RunGetStdOut(sCmd, sEncoding := "CP0", sDir := "", ByRef nExitCode := 0, Callback := "") { 2 | DllCall("CreatePipe", "Ptr*", hStdOutRd, "Ptr*", hStdOutWr, "Ptr", 0, "UInt", 0) 3 | DllCall("SetHandleInformation", "Ptr", hStdOutWr, "UInt", 1, "UInt", 1) 4 | 5 | ; STARTUPINFO 6 | NumPut(VarSetCapacity(si, A_PtrSize == 4 ? 68 : 104, 0), si, 0, "UInt") 7 | NumPut(0x100, si, A_PtrSize == 4 ? 44 : 60, "UInt") ; dwFlags: STARTF_USESTDHANDLES 8 | NumPut(hStdOutWr, si, A_PtrSize == 4 ? 60 : 88, "Ptr" ) ; hStdOutput 9 | NumPut(hStdOutWr, si, A_PtrSize == 4 ? 64 : 96, "Ptr" ) ; hStdError 10 | 11 | ; PROCESS_INFORMATION 12 | VarSetCapacity(pi, A_PtrSize == 4 ? 16 : 24, 0) 13 | ; CREATE_NO_WINDOW = 0x08000000 14 | If (!DllCall("CreateProcess", "Ptr", 0, "Ptr", &sCmd, "Ptr", 0, "Ptr", 0, "Int", True 15 | , "UInt", 0x08000000, "Ptr", 0, "Ptr", sDir ? &sDir : 0, "Ptr", &si, "Ptr", &pi)) { 16 | DllCall("CloseHandle", "Ptr", hStdOutWr) 17 | DllCall("CloseHandle", "Ptr", hStdOutRd) 18 | Return "" 19 | } 20 | 21 | DllCall("CloseHandle", "Ptr", hStdOutWr) ; The write pipe must be closed before reading stdout. 22 | 23 | sOutput := "" 24 | While (1) { 25 | ; Before reading, we check if the pipe has been written to, so we avoid freezings. 26 | If (!DllCall("PeekNamedPipe", "Ptr", hStdOutRd, "Ptr", 0, "UInt", 0, "Ptr", 0, "UInt*", nTot, "Ptr", 0)) { 27 | Break 28 | } 29 | 30 | If (!nTot) { ; If the pipe buffer is empty, sleep and continue checking. 31 | Sleep 100 32 | Continue 33 | } 34 | 35 | ; Pipe buffer is not empty, so we can read it. 36 | VarSetCapacity(sTemp, nTot + 1) 37 | DllCall("ReadFile", "Ptr", hStdOutRd, "Ptr", &sTemp, "UInt", nTot, "Ptr*", nSize, "Ptr", 0) 38 | sOutput .= sStdOut := StrGet(&sTemp, nSize, sEncoding) 39 | If (Callback != "") { 40 | %Callback%(sStdOut) 41 | } 42 | } 43 | 44 | DllCall("GetExitCodeProcess", "Ptr", NumGet(pi, 0), "UInt*", nExitCode) 45 | DllCall("CloseHandle", "Ptr", NumGet(pi, 0)) ; hProcess 46 | DllCall("CloseHandle", "Ptr", NumGet(pi, A_PtrSize)) ; hThread 47 | DllCall("CloseHandle", "Ptr", hStdOutRd) 48 | Return sOutput 49 | } 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Structor 2 | 3 | 轻松获取结构体大小、偏移、常量值的工具。 4 | 5 | 6 | 7 | ## 简介 8 | 9 | ![Structor](https://raw.githubusercontent.com/telppa/Structor/main/Img/1.png) 10 | ![Verifier](https://raw.githubusercontent.com/telppa/Structor/main/Img/2.png) 11 | 12 | 本工具提取自 [Adventure IDE – 3.0.4](https://sourceforge.net/projects/autogui/) ,作者 alguimistf 。 13 | 14 | 为实现工具便携性与使用傻瓜化,我修改了部分代码,并集成了最新的 MSVC2022 编译器及 WIN10 SDK 。 15 | 16 | 简单说就是,现在你只需要下载解压就可以使用了。 17 | 18 | 19 | 20 | ## 功能1:创建结构体并从中读取内容。 21 | 22 | 当我们想在 ahk 中使用一个结构体,例如 URL_COMPONENTS 时。 23 | 24 | 1. 首先在 MSDN 也就是微软官网找到 URL_COMPONENTS 的页面。 25 | 26 | 2. 复制结构体到工具中。 27 | ![](https://raw.githubusercontent.com/telppa/Structor/main/Img/3.png) 28 | 29 | 3. 根据页面最下方的提示在工具中添加对应的头文件(页面无提示则可以不添加)。 30 | ![](https://raw.githubusercontent.com/telppa/Structor/main/Img/4.png) 31 | 32 | 4. 点击 Compile 按钮,等待结果出现再点击 Copy 按钮。 33 | ![](https://raw.githubusercontent.com/telppa/Structor/main/Img/5.png) 34 | 35 | 此时剪贴板中就得到了可以让你像变量一样使用该结构体的代码了。 36 | 37 | 38 | 39 | ## 功能2:获取数据类型的大小。 40 | 41 | 例如我们想知道, DWORD 类型在32位下的大小时。 42 | 43 | ![](https://raw.githubusercontent.com/telppa/Structor/main/Img/6.png) 44 | 45 | 需要注意, DWORD 之类的内容是大小写敏感的。 46 | 47 | 48 | 49 | ## 功能3:获取成员的偏移量。 50 | 51 | 例如我们想知道,结构体 URL_COMPONENTS 的成员 nPort 在64位下的偏移量时。 52 | 53 | ![](https://raw.githubusercontent.com/telppa/Structor/main/Img/7.png) 54 | 55 | 需要注意,本例中的结构体 URL_COMPONENTS 需要头文件 winhttp.h ,所以在 Includes 中要自己加上。 56 | 57 | 同样的, URL_COMPONENTS.nPort 之类的内容是大小写敏感的。 58 | 59 | 60 | 61 | ## 功能4:获取常量值。 62 | 63 | 例如我们想知道,常量 LVM_GETHEADER 在32位下的具体值时。 64 | 65 | ![](https://raw.githubusercontent.com/telppa/Structor/main/Img/8.png) 66 | 67 | 需要注意,本例中的 LVM_GETHEADER 需要头文件 commctrl.h ,所以在 Includes 中要自己加上。 68 | 69 | 同样的, LVM_GETHEADER 之类的内容是大小写敏感的。 70 | 71 | 72 | 73 | ## 功能5:批量模式。 74 | 75 | 例如我们想知道,DWORD WORD HANDLE 3种类型的大小时。 76 | 77 | 新建一个文本文档,每行写一种类型,像这样。 78 | 79 | ``` 80 | WORD 81 | DWORD 82 | HANDLE 83 | ``` 84 | 85 | ![](https://raw.githubusercontent.com/telppa/Structor/main/Img/9.png) 86 | 87 | 同理,也可以批量获取成员偏移量和常量值。 88 | 89 | 90 | 91 | ## 更新日志 92 | #### 2022.05.12 93 | * 为 StrGet 与 StrPut 提供 Plan B 。 94 | * 版本号 1.2.2 。 95 | #### 2022.04.18 96 | * 修复了原版数个 BUG 。 97 | * 打包了编译器和 SDK 。 98 | * 增强了类型识别功能。 99 | * 实现了工具便携性。 100 | * 版本号 1.2.1 。 101 | 102 | 103 | 104 | ## 下载地址 105 | 106 | [Github Releases](https://github.com/telppa/Structor/releases) 107 | -------------------------------------------------------------------------------- /Structor.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | 本工具提取自 : Adventure IDE - 3.0.4 3 | 完整版默认编译器 : MSVC2022_Mini 4 | 默认编译器制作说明: MSVC2022 制作说明.txt 5 | 6 | 为实现工具便携性与使用傻瓜化,部分代码有修改,需自行对比原版。 7 | 8 | Original Version : https://www.autohotkey.com/boards/viewtopic.php?t=31711 9 | Modified Version : https://github.com/telppa/Structor 10 | 11 | */ 12 | 13 | ; Structor - Structure Helper 14 | 15 | #SingleInstance Off 16 | #NoEnv 17 | #NoTrayIcon 18 | SetWorkingDir %A_ScriptDir% 19 | SetBatchLines -1 20 | 21 | ; 自动配置编译器路径 22 | #Include %A_ScriptDir%\Lib\MSVC2022.ahk 23 | 24 | Global C 25 | , AppName := "Structor" 26 | , Version := "1.2.2" 27 | , g_AppData := A_ScriptDir 28 | , StructSize32 := 0 29 | , StructSize64 := 0 30 | , Unicode := 1 31 | , PausePrompt := 0 32 | , g_aGradColors := [0x3FBBE3, 0x008EBC] 33 | 34 | GoSub LoadSettings 35 | 36 | SetMainIcon(A_ScriptDir . "\Icons\Structor.ico") 37 | 38 | Gui Main: New, LabelMain hWndhMainWnd +Resize +MinSize627x511 39 | 40 | Gui Add, Pic, hWndhGrad1 x11 y10 w606 h26, % "HBITMAP:" . Gradient(606, 26) 41 | Gui Font, s9 cWhite Bold, Segoe UI 42 | Gui Add, Text, vLabel1 x11 y10 w606 h26 +0x200 +E0x200 +BackgroundTrans, %A_Space%Structure Declaration 43 | Gui Font 44 | 45 | Gui Font, s10 c0x003399, Lucida Console 46 | Gui Add, Edit, vInput gEnableParse x11 y39 w605 h176 47 | Gui Font 48 | 49 | Gui Font, s9, Segoe UI 50 | Gui Add, Button, vBtnParse gGetOffsets x10 y224 w84 h24 +Disabled, &Compile 51 | Gui Add, CheckBox, vChk32bit gEnableParse x110 y225 w96 h23 +Checked%Chk32bit%, &32-bit offsets 52 | GuiControl % (CompilerPath32 != "") ? "Enable" : "Disable", Chk32bit 53 | Gui Add, CheckBox, vChk64bit gEnableParse x208 y225 w96 h23 +Checked%Chk64bit%, &64-bit offsets 54 | GuiControl % (CompilerPath64 != "") ? "Enable" : "Disable", Chk64bit 55 | Gui Add, Text, vLblStructName x360 y225 w101 h23 +0x202, Structure &Name: 56 | Gui Add, Edit, vStructName x470 y225 w146 h21 57 | 58 | Gui Add, Pic, hWndhGrad2 x11 y257 w605 h26, % "HBITMAP:" . Gradient(606, 26) 59 | Gui Font, s9 cWhite Bold, Segoe UI 60 | Gui Add, Text, vLabel2 x11 y257 w605 h26 +0x200 +E0x200 +BackgroundTrans, %A_Space%Structure Offsets 61 | Gui Font 62 | 63 | Gui Font, s9, Segoe UI 64 | Gui Add, ListView, hWndhLVOffset vLV x11 y286 w603 h180 +LV0x114004, Member|Data Type|32-bit Offset|64-bit Offset 65 | LV_ModifyCol(1, 150) 66 | LV_ModifyCol(2, 150) 67 | LV_ModifyCol(3, "80 Integer") 68 | LV_ModifyCol(4, "80 Integer") 69 | 70 | Gui Add, Button, vBtnCopy gGenerateCode x9 y476 w84 h24 +Disabled, C&opy 71 | Gui Add, CheckBox, vChkNumGet x110 y476 w96 h23 +Checked%ChkNumGet%, Num&Get 72 | Gui Add, CheckBox, vChkNumPut x208 y476 w96 h23 +Checked%ChkNumPut%, Num&Put 73 | Gui Add, Button, vBtnSettings gShowSettings x519 y476 w96 h24, &Settings... 74 | 75 | Gui Show, w627 h511, %AppName% 76 | 77 | Test(113) 78 | 79 | If (CompilerPath32 == "" && CompilerPath64 == "") { 80 | GoSub ShowSettings 81 | } 82 | 83 | If (RegExMatch(Clipboard, "^(typedef)? struct")) { 84 | GuiControl,, Input, %Clipboard% 85 | GuiControl Main: Enable, BtnParse 86 | } 87 | 88 | DllCall("UxTheme.dll\SetWindowTheme", "Ptr", hLVOffset, "WStr", "Explorer", "Ptr", 0) 89 | 90 | Menu ContextMenu, Add, Copy for NumGet, CopyForNumGet 91 | Menu ContextMenu, Add, Copy for NumPut, CopyForNumPut 92 | 93 | hSysMenu := DllCall("GetSystemMenu", "Ptr", hMainWnd, "Int", False, "Ptr") 94 | DllCall("InsertMenu", "Ptr", hSysMenu, "UInt", 5, "UInt", 0x400, "UPtr", 0xC0DE, "Str", "About...") 95 | DllCall("InsertMenu", "Ptr", hSysMenu, "UInt", 5, "UInt", 0xC00, "UPtr", 0, "Str", "") ; Separator 96 | 97 | OnMessage(0x100, "OnWM_KEYDOWN") 98 | OnMessage(0x112, "OnWM_SYSCOMMAND") 99 | Return 100 | 101 | MainEscape: 102 | MainClose: 103 | GoSub SaveSettings 104 | DeleteTempFiles() 105 | ExitApp 106 | 107 | GetOffsets: 108 | Gui Main: Submit, NoHide 109 | 110 | RegEx := "^([\w ]+)\s+(\*?.+);$" 111 | 112 | DataTypes := [] 113 | Members := [] 114 | StructName := "" 115 | 116 | ; Parse input data 117 | Loop Parse, Input, `n, `r 118 | { 119 | Line := RegExReplace(A_LoopField, "(#|//|/\*).+") ; Remove comments and directives 120 | Line := Trim(Line) 121 | If (RegExMatch(Line, RegEx, Match)) { 122 | Match1 := RTrim(Match1) 123 | Match2 := StrReplace(Match2, "*") 124 | 125 | If (InStr(Match2, ":")) { 126 | ;MsgBox 0x30, %AppName%, %Match2% is a bit field and will be skipped. 127 | Continue 128 | } 129 | 130 | DataTypes.Push(Match1) 131 | Members.Push(Match2) 132 | 133 | } Else If (RegExMatch(Line, "}\s+(\w+)", Match)) { 134 | StructName := Match1 135 | } Else If (RegExMatch(Line, "struct (?:tag)?(\w+)", Match)) { 136 | StructName := Match1 137 | } 138 | } 139 | 140 | If (StructName == "") { 141 | Gui Main: +OwnDialogs 142 | MsgBox 0x10, %AppName%, Invalid input. 143 | Return 144 | } 145 | 146 | GuiControl,, StructName, %StructName% 147 | 148 | DeleteTempFiles() 149 | 150 | GoSub GenerateCCode 151 | 152 | Offsets32 := [] 153 | Offsets64 := [] 154 | 155 | If (Chk32bit) { 156 | If (CreateBatchFile("32")) { 157 | GetOffsets("32", Offsets32, StructSize32) 158 | } 159 | } 160 | 161 | If (Chk64bit) { 162 | If (CreateBatchFile("64")) { 163 | GetOffsets("64", Offsets64, StructSize64) 164 | } 165 | } 166 | 167 | LV_Delete() 168 | Loop % Members.Length() { 169 | LV_Add("Check", Members[A_Index], DataTypes[A_Index], Offsets32[A_Index], Offsets64[A_Index]) 170 | } 171 | 172 | If (Members.Length()) { 173 | GuiControl Main: Enable, BtnCopy 174 | } 175 | Return 176 | 177 | ; Generate Offsets.c 178 | GenerateCCode: 179 | C := "" 180 | 181 | If (Unicode) { 182 | C .= "#define UNICODE 1`r`n" 183 | } 184 | 185 | C .= "#include `r`n" 186 | C .= "#include `r`n" 187 | 188 | Loop % arrIncludes.Length() { 189 | If (InStr(arrIncludes[A_Index], ":")) { 190 | C .= "#include """ . arrIncludes[A_Index] . """`r`n" 191 | } Else { 192 | C .= "#include <" . arrIncludes[A_Index] . ">`r`n" 193 | } 194 | } 195 | 196 | C .= "`r`nint main() {`r`n" 197 | C .= " printf(""%d\n"", sizeof(" . StructName . "));`r`n" 198 | 199 | Loop % Members.Length() { 200 | If (InStr(Members[A_Index], "[")) { 201 | If (RegExMatch(Members[A_Index], "\[(.+)\]", Match)) { 202 | C .= " printf(""%d\n"", offsetof(" . StructName . ", " . Members[A_Index] . ") - ((" . Match1 . ") * sizeof(" . DataTypes[A_Index] . ")));`r`n" 203 | } 204 | } Else { 205 | C .= " printf(""%d\n"", offsetof(" . StructName . ", " . Members[A_Index] . "));`r`n" 206 | } 207 | } 208 | C .= " return 0;`r`n}" 209 | 210 | FileAppend %C%, %A_Temp%\Offsets.c 211 | Return 212 | 213 | ; Generate the files Compile32.bat and Compile64.bat 214 | CreateBatchFile(xNN) { 215 | Bat := "@ECHO OFF`r`nCD /D " . A_Temp . "`r`n" 216 | If (BatchFile%xNN% != "") { 217 | Bat .= "CALL """ . BatchFile%xNN% . """`r`n" 218 | } 219 | 220 | CompilerPath := CompilerPath%xNN% 221 | 222 | If (!GetExePathAndArgs(CompilerPath, Args)) { 223 | Gui Main: +OwnDialogs 224 | MsgBox 0x10, %AppName%, Invalid file path: CompilerPath%xNN% 225 | Return 0 226 | } 227 | 228 | If (Args != "") { 229 | Args := " " . Args 230 | } 231 | 232 | If (InStr(CompilerPath, "CL.EXE")) { 233 | Bat .= """" . CompilerPath . """" . Args . " Offsets.c -FeOffsets" . xNN . ".exe" 234 | 235 | } Else If (InStr(CompilerPath, "GCC.EXE")) { 236 | Bat .= """" . CompilerPath . """" . Args . " Offsets.c -o Offsets" . xNN . ".exe" 237 | } 238 | 239 | If (PausePrompt) { 240 | Bat .= "`r`nECHO. && PAUSE" 241 | } 242 | 243 | FileAppend %Bat%, %A_Temp%\Compile%xNN%.bat 244 | Return !ErrorLevel 245 | } 246 | 247 | ; Compile and run 248 | GetOffsets(xNN, ByRef Offsets, ByRef StructSize) { 249 | RunWait %A_Temp%\Compile%xNN%.bat,, % PausePrompt ? "" : "Hide" 250 | 251 | Stdout := RunGetStdout(A_Temp . "\Offsets" . xNN . ".exe") 252 | 253 | If (A_LastError == 2) { ; File not found 254 | Gui Main: +OwnDialogs 255 | MsgBox 0x10, %AppName%, %xNN%-bit compilation failed. 256 | Return 257 | } 258 | 259 | StructSize := 0 260 | Offsets := [] 261 | Loop Parse, Stdout, `n, `r 262 | { 263 | If (A_Index == 1) { 264 | StructSize := A_LoopField 265 | } Else { 266 | Offsets.Push(A_LoopField) 267 | } 268 | } 269 | } 270 | 271 | DeleteTempFiles() { 272 | FileDelete %A_Temp%\Compile32.bat 273 | FileDelete %A_Temp%\Compile64.bat 274 | FileDelete %A_Temp%\Offsets.c 275 | FileDelete %A_Temp%\Offsets.obj 276 | FileDelete %A_Temp%\Offsets32.exe 277 | FileDelete %A_Temp%\Offsets64.exe 278 | } 279 | 280 | CopyForNumGet: 281 | CopyForNumPut: 282 | GenerateCode: 283 | Gui Main: Default 284 | Gui Submit, NoHide 285 | 286 | Cap := "" 287 | Condition := "" 288 | IncludePlanBFunc := "" 289 | 290 | If (StructSize32 == StructSize64) { 291 | StructSize := (Chk32bit) ? StructSize32 : StructSize64 292 | 293 | } Else If (Chk32bit && Chk64bit) { 294 | If (ShortTernary || GetKeyState("Shift", "P")) { 295 | Cap := "x64 := (A_PtrSize == 8)`r`n" 296 | Condition := "x64 ? " 297 | } Else { 298 | Condition := "(A_PtrSize == 8) ? " 299 | } 300 | 301 | StructSize := StructSize64 . " : " . StructSize32 302 | 303 | } Else If (Chk32bit) { 304 | StructSize := StructSize32 305 | 306 | } Else If (Chk64bit) { 307 | StructSize := StructSize64 308 | 309 | } Else { 310 | Return 311 | } 312 | 313 | If (StructSize) { 314 | Cap .= Format("VarSetCapacity({}, {}, 0)", StructName, Condition . StructSize) 315 | } 316 | 317 | Get := "" 318 | Put := "" 319 | If (A_ThisLabel == "CopyForNumGet") { 320 | fGet := True 321 | fPut := False 322 | 323 | } Else If (A_ThisLabel == "CopyForNumPut") { 324 | fGet := False 325 | fPut := True 326 | 327 | } Else { 328 | fGet := ChkNumGet 329 | fPut := ChkNumPut 330 | } 331 | 332 | Checked := A_ThisLabel == "GenerateCode" ? "Checked" : "" 333 | PrevOffset := -1 334 | Row := 0 335 | 336 | While (Row := LV_GetNext(Row, Checked)) { 337 | LV_GetText(Member, Row, 1) 338 | LV_GetText(DataType, Row, 2) 339 | LV_GetText(Offset32, Row, 3) 340 | LV_GetText(Offset64, Row, 4) 341 | 342 | fStr := False, ftype := "" 343 | 344 | If (FoundPos := InStr(Member, "[")) { 345 | Member := SubStr(Member, 1, FoundPos - 1) 346 | If (RegExMatch(DataType, "i)(TCHAR|WCHAR|wchar_t|CHAR)", fType)) 347 | fStr := True 348 | } 349 | 350 | AHKType := GetAHKType(DataType, Member, Row) 351 | If (!InStr(AHKType, "=")) { ; Add quotes. int->"int" (a=b)?c:d->(a=b)?c:d 352 | AHKType := Format("""{}""", AHKType) 353 | If (InStr(AHKType, "Str")) ; Str AStr WStr 354 | fStr := True 355 | } 356 | 357 | switch, fType 358 | { 359 | case "TCHAR" : AHKType := """Str""" 360 | case "CHAR" : AHKType := """AStr""" 361 | case "WCHAR", "wchar_t" : AHKType := """WStr""" 362 | } 363 | 364 | If (fStr) { 365 | If (Row == LV_GetCount()) { 366 | Length := (Offset64 != "") ? (StructSize64 - Offset64) : (StructSize32 - Offset32) 367 | } Else { 368 | LV_GetText(NextOffset32, Row + 1, 3) 369 | LV_GetText(NextOffset64, Row + 1, 4) 370 | Length := (Offset64 != "") ? (NextOffset64 - Offset64) : (NextOffset32 - Offset32) 371 | } 372 | 373 | ; If the type is Str(e.g. TCHAR), and you want to do compatibility for ansi and unicode. 374 | ; The right way is to generate the structure twice by checked and no checked the checkbox-Unicode in Settings. 375 | ; The ansi size calculated by unicode size is not accurate, that's why we should get the them by generating it twice. 376 | Tips := "" 377 | switch, Trim(AHKType, """") 378 | { 379 | case "Str": 380 | Encoding := Unicode ? """UTF-16""" : """CP0""" 381 | Length := Unicode ? Length//2 : Length 382 | Tips := Unicode ? " `; work on AutoHotkeyU32(U64).exe" : " `; work on AutoHotkeyA32.exe" 383 | case "AStr": 384 | Encoding := """CP0""" 385 | Length := Length 386 | case "WStr": 387 | Encoding := """UTF-16""" 388 | Length //= 2 389 | } 390 | } 391 | 392 | u := (Offset32 == PrevOffset 393 | || Offset64 == PrevOffset 394 | || (Chk32bit ? Offset32 : Offset64) < PrevOffset) ? "; " : "" ; Union 395 | 396 | If (Condition != "" && Offset32 != Offset64) { 397 | Offset := Condition . Offset64 . " : " . Offset32 398 | } Else If (Chk32bit) { 399 | Offset := Offset32 400 | } Else If (Chk64bit) { 401 | Offset := Offset64 402 | } 403 | 404 | If (DataType ~= "^(RECT|POINTL?)$") { 405 | Prefix := Member . "_" 406 | Fields := (DataType == "RECT") ? "left,top,right,bottom" : "X,Y" 407 | 408 | Loop Parse, Fields, `, 409 | { 410 | If (fGet) { 411 | Get .= Format("{} := NumGet({}, {}, ""Int"")`r`n", u . Prefix . A_LoopField, StructName, Offset) 412 | } 413 | 414 | If (fPut) { 415 | Put .= Format("{}NumPut({}, {}, {}, ""Int"")`r`n", u, Prefix . A_LoopField, StructName, Offset) 416 | } 417 | 418 | If (Condition != "" && Offset32 != Offset64) { 419 | Offset := Condition . (Offset64 + (A_Index * 4)) . " : " . (Offset32 + (A_Index * 4)) 420 | } Else { 421 | Offset += 4 422 | } 423 | } 424 | 425 | Continue 426 | } 427 | 428 | If (InStr(Offset, ":")) 429 | Offset := Format("({})", Offset) 430 | 431 | If (fGet) { 432 | If (fStr) { 433 | 434 | Get .= Format("; Plan A.`r`n{} := StrGet(&{} + {}, {}, {}){}`r`n", u . Member, StructName, Offset, Length, Encoding, Tips) 435 | 436 | ; sometimes it's a pointer. 437 | PlanB = 438 | (LTrim 439 | ; Plan B. Try this if Plan A fails. 440 | ; Pointer_{1} := NumGet({2}, {3}, "Ptr") 441 | ; {1} := StrGet(Pointer_{1}, {4}){5}`r`n 442 | ) 443 | PlanB := Format(PlanB, Member, StructName, Offset, Encoding, Tips) 444 | Get .= PlanB 445 | 446 | } Else { 447 | Get .= Format("{} := NumGet({}, {}, {})`r`n", u . Member, StructName, Offset, AHKType) 448 | } 449 | } 450 | 451 | If (fPut) { 452 | If (fStr) { 453 | 454 | Put .= Format("; Plan A.`r`n{}StrPut({}, &{} + {}, {}, {}){}`r`n", u, Member, StructName, Offset, Length, Encoding, Tips) 455 | 456 | ; sometimes it's a pointer. 457 | PlanB = 458 | (LTrim 459 | ; Plan B. Try this if Plan A fails. 460 | ; {1} := "Put your string here." 461 | ; StrPutVar({1}, Pointer_{1}, {4}) 462 | ; NumPut(&Pointer_{1}, {2}, {3}, "Ptr"){5}`r`n 463 | ) 464 | PlanB := Format(PlanB, Member, StructName, Offset, Encoding, Tips) 465 | Put .= PlanB 466 | IncludePlanBFunc := True 467 | 468 | } Else { 469 | Put .= Format("{}NumPut({}, {}, {}, {})`r`n", u, Member, StructName, Offset, AHKType) 470 | } 471 | } 472 | 473 | If (u == "") { 474 | PrevOffset := (Chk32bit) ? Offset32 : Offset64 475 | } 476 | } 477 | 478 | If (Get != "" || Put != "") { 479 | Cap .= "`r`n`r`n" 480 | } 481 | 482 | If (Get != "") { 483 | Get .= "`r`n" 484 | } 485 | 486 | if (IncludePlanBFunc) { 487 | PlanBFunc = 488 | (LTrim 489 | StrPutVar(str, ByRef var, encoding) 490 | { 491 | %A_Space%%A_Space%factor := (encoding="utf-16" or encoding="cp1200") ? 2 : 1 492 | %A_Space%%A_Space%VarSetCapacity(var, StrPut(str, encoding) * factor) 493 | %A_Space%%A_Space%return StrPut(str, &var, encoding) 494 | } 495 | ) 496 | Put .= "`r`n" PlanBFunc 497 | } 498 | 499 | If (Cap != "") { 500 | Gui Main: +OwnDialogs 501 | MsgBox 0, %AppName%, % Clipboard := Cap . Get . Put 502 | } 503 | Return 504 | 505 | GetAHKType(DataType, Member, Row) { 506 | ; You can get the following list of types by press F10 in "AHK DllCall Terminator". 507 | ; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=101795 508 | ; https://autohotkey.com/board/topic/25250-structparser-for-cc-structs/ 509 | Static Types = "Int,UInt,Ptr,UPtr,Short,UShort,Char,UChar,Int64,Float,Double,Str,AStr,WStr" 510 | , AStrTypes = "__nullterminated CONST CHAR*,CHAR*,CONST CHAR*,INT8*,LPCSTR,LPSTR,PCHAR,PCSTR,PINT8,PSTR" 511 | , CharTypes = "CCHAR,char,INT8,signed char" 512 | , DoubleTypes = "double" 513 | , FloatTypes = "float" 514 | , IntTypes = "BOOL,HFILE,HRESULT,int,INT32,long,LONG32,NTSTATUS,signed int" 515 | , Int64Types = "__int64,DWORD64,DWORDLONG,INT64,LARGE_INTEGER,LONG64,LONGLONG,QWORD,signed __int64,UINT64,ULARGE_INTEGER,ULONG64,ULONGLONG,unsigned __int64,USN" 516 | , PtrTypes = "__int3264,ADCONNECTION_HANDLE,CONST void*,HACCEL,HANDLE,HBITMAP,HBRUSH,HCOLORSPACE,HCONV,HCONVLIST,HCURSOR,HDC,HDDEDATA,HDESK,HDROP,HDWP,HENHMETAFILE,HFONT,HGDIOBJ,HGLOBAL,HHOOK,HICON,HINSTANCE,HKEY,HKL,HLOCAL,HMENU,HMETAFILE,HMODULE,HMONITOR,HPALETTE,HPEN,HRGN,HRSRC,HSZ,HWND,INT_PTR,LDAP_UDP_HANDLE,LONG_PTR,LPARAM,LPCVOID,LPVOID,LRESULT,PCONTEXT_HANDLE,PVOID,RPC_BINDING_HANDLE,SC_HANDLE,SC_LOCK,SERVICE_STATUS_HANDLE,SSIZE_T,void*,WINSTA" 517 | , ShortTypes = "INT16,short,signed short" 518 | , StrTypes = "LPCTSTR,LPTSTR,PCTSTR,PTCHAR,PTSTR,TCHAR*" 519 | , UCharTypes = "BOOLEAN,BYTE,UCHAR,UINT8,unsigned char" 520 | , UIntTypes = "ACCESS_MASK,COLORREF,DWORD,DWORD32,error_status_t,HCALL,LCID,LCTYPE,LGRPID,NET_API_STATUS,SECURITY_INFORMATION,TOKEN_MANDATORY_POLICY,UINT,UINT32,ULONG,ULONG32,unsigned int,unsigned long" 521 | , UPtrTypes = "DWORD_PTR,SIZE_T,UINT_PTR,ULONG_PTR,unsigned __int3264,WPARAM" 522 | , UShortTypes = "ATOM,LANGID,UINT16,UNICODE,unsigned short,USHORT,WCHAR,wchar_t,WORD" 523 | , WStrTypes = "BSTR,CONST WCHAR*,const wchar_t*,LMCSTR,LMSTR,LPCWSTR,LPWORD,LPWSTR,PCWSTR,PUINT16,PUSHORT,PWCHAR,PWORD,PWSTR,UINT16*,USHORT*,WCHAR*,WORD*" 524 | 525 | Loop Parse, Types, `, 526 | { 527 | TypeList := %A_LoopField%Types 528 | If DataType in %TypeList% 529 | { 530 | Return A_LoopField 531 | Break 532 | } 533 | } 534 | 535 | If (Type == "TBYTE") 536 | Return "(A_IsUnicode) ? ""UShort"" : ""UChar""" 537 | 538 | If (Type == "HALF_PTR") 539 | Return "(A_PtrSize=8) ? ""Int"" : ""Short""" 540 | 541 | If (Type == "UHALF_PTR") 542 | Return "(A_PtrSize=8) ? ""UInt"" : ""UShort""" 543 | 544 | If (SubStr(DataType, 1, 2) == "LP" || SubStr(Member, 1, 2) == "lp") { 545 | Return "Ptr" 546 | } 547 | 548 | LV_GetText(Offset32, Row, 3) 549 | LV_GetText(Offset64, Row, 4) 550 | 551 | If (Row == LV_GetCount()) { 552 | Size := (Offset64 != "") ? (StructSize64 - Offset64) : (StructSize32 - Offset32) 553 | } Else { 554 | If (Offset64 != "") { 555 | LV_GetText(NextOffset, Row + 1, 4) 556 | Size := NextOffset - Offset64 557 | } Else { 558 | LV_GetText(NextOffset, Row + 1, 3) 559 | Size := NextOffset - Offset32 560 | } 561 | } 562 | 563 | Type := (Size >= 8) ? "Ptr" : {1: "Char", 2: "Short", 4: "Int"}[Size] 564 | 565 | Return (Type == "") ? "UInt" : Type 566 | } 567 | 568 | MainContextMenu: 569 | If (A_GuiControl != "LV" || !LV_GetNext()) { 570 | Return 571 | } 572 | 573 | Menu ContextMenu, Show 574 | Return 575 | 576 | MainSize: 577 | AutoXYWH("w", hGrad1) 578 | AutoXYWH("w", "Label1") 579 | AutoXYWH("w", "Input") 580 | AutoXYWH("x*", "LblStructName") 581 | AutoXYWH("x", "StructName") 582 | AutoXYWH("w", hGrad2) 583 | AutoXYWH("w", "Label2") 584 | AutoXYWH("wh", hLVOffset) 585 | AutoXYWH("y", "BtnCopy") 586 | AutoXYWH("y", "ChkNumGet") 587 | AutoXYWH("y", "ChkNumPut") 588 | AutoXYWH("xy", "BtnSettings") 589 | Return 590 | 591 | DPIScale(x) { 592 | Return (x * A_ScreenDPI) // 96 593 | } 594 | 595 | Gradient(Width, Height) { 596 | Return CreateGradient(DPIScale(Width), DPIScale(Height), 1, g_aGradColors) 597 | } 598 | 599 | ShowSettings: 600 | Gui Settings: New, +LabelSettings -MinimizeBox +OwnerMain 601 | Gui Color, White 602 | 603 | Gui Add, Pic, x9 y10 w637 h26, % "HBITMAP:" . Gradient(637, 26) 604 | Gui Font, s9 cWhite Bold, Segoe UI 605 | Gui Add, Text, x9 y10 w637 h26 +0x200 +E0x200 +BackgroundTrans, %A_Space%Compiler Settings 606 | Gui Font 607 | 608 | Gui Font, s9, Segoe UI 609 | Gui Add, GroupBox, x9 y44 w637 h99, 32-bit Compiler 610 | Gui Add, Text, x26 y71 w97 h21 +0x200, Compiler Path: 611 | Gui Add, Edit, vCompilerPath32 x124 y71 w418 h22, %CompilerPath32% 612 | Gui Add, Button, gSelectCompiler32 x549 y69 w84 h24, Browse... 613 | Gui Add, Text, x26 y105 w97 h21 +0x200, Batch File: 614 | Gui Add, Edit, vBatchFile32 x124 y105 w418 h22, %BatchFile32% 615 | Gui Add, Button, gSelectBatchFile32 x549 y103 w84 h24, Browse... 616 | 617 | Gui Add, GroupBox, x9 y149 w637 h99, 64-bit Compiler 618 | Gui Add, Text, x26 y176 w97 h21 +0x200, Compiler Path: 619 | Gui Add, Edit, vCompilerPath64 x124 y174 w418 h22, %CompilerPath64% 620 | Gui Add, Button, gSelectCompiler64 x549 y173 w84 h24, Browse... 621 | Gui Add, Text, x26 y210 w97 h21 +0x200, Batch File: 622 | Gui Add, Edit, vBatchFile64 x124 y208 w418 h22, %BatchFile64% 623 | Gui Add, Button, gSelectBatchFile64 x549 y207 w84 h24, Browse... 624 | 625 | Gui Add, Text, x18 y259 w100 h21 +0x200, &Includes: 626 | Gui Add, Edit, hWndhEdtHeader vNewInclude x124 y259 w200 h22 627 | Gui Add, Button, gAddInclude x331 y258 w84 h24, &Add 628 | Gui Add, Button, gRemoveInclude x331 y290 w84 h24, &Remove 629 | Gui Add, ListView, hWndhHeaderList x124 y290 w200 h119 -Hdr +LV0x114004, Headers 630 | 631 | Gui Add, CheckBox, vUnicode x483 y360 w167 h23 +Checked%Unicode%, &Unicode 632 | Gui Add, CheckBox, vPausePrompt x483 y388 w167 h23 +Checked%PausePrompt%, &Pause command prompt 633 | 634 | Gui Add, Text, x-1 y422 w660 h48 +Border -Background 635 | Gui Add, Button, gShowHelp x11 y434 w84 h24, &Help 636 | Gui Add, Button, gSettingsOK x469 y434 w84 h24 +Default, &OK 637 | Gui Add, Button, gSettingsClose x561 y434 w84 h24, Cancel 638 | 639 | If (strIncludes == "" || strIncludes == "ERROR") { 640 | LV_Add("Check", "windows.h") 641 | LV_Add("Check", "commctrl.h") 642 | } Else { 643 | Loop Parse, strIncludes, `n 644 | { 645 | If (A_LoopField != "") { 646 | Pair := StrSplit(A_LoopField, "=") 647 | Checked := (Pair[1] == 1) ? "Check" : "" 648 | LV_Add(Checked, Pair[2]) 649 | } 650 | } 651 | LV_ModifyCol(1, "AutoHdr") 652 | } 653 | 654 | Gui Show, w656 h469, Settings 655 | 656 | DllCall("SetFocus", "Ptr", 0) 657 | 658 | ; EM_SETCUEBANNER 659 | DllCall("SendMessage", "Ptr", hEdtHeader, "UInt", 0x1501, "Ptr", 0, "WStr", "Header file", "Ptr") 660 | 661 | DllCall("UxTheme.dll\SetWindowTheme", "Ptr", hHeaderList, "WStr", "Explorer", "Ptr", 0) 662 | Return 663 | 664 | SettingsEscape: 665 | SettingsClose: 666 | Gui Settings: Destroy 667 | Return 668 | 669 | SettingsOK: 670 | Gui Settings: Default 671 | 672 | If (!LV_GetCount()) { 673 | LV_Add("Check", "windows.h") 674 | LV_Add("Check", "commctrl.h") 675 | } 676 | 677 | arrIncludes := [] 678 | strIncludes := "" 679 | Loop % LV_GetCount() { 680 | LV_GetText(Header, A_Index) 681 | 682 | Checked := 0 683 | SendMessage 0x102C, % A_Index - 1, 0x2000,, ahk_id %hHeaderList% ; LVM_GETITEMSTATE, LVIS_CHECKED 684 | If (Errorlevel == 0x2000) { 685 | arrIncludes.Push(Header) 686 | Checked := 1 687 | } 688 | 689 | strIncludes .= Checked . "=" . Header . "`n" 690 | } 691 | 692 | Gui Settings: Submit 693 | 694 | If (CompilerPath32 != "") { 695 | GuiControl Main:, Chk32bit, 1 696 | GuiControl Main: Enable, Chk32bit 697 | } Else { 698 | GuiControl Main:, Chk32bit, 0 699 | GuiControl Main: Disable, Chk32bit 700 | } 701 | 702 | If (CompilerPath64 != "") { 703 | GuiControl Main:, Chk64bit, 1 704 | GuiControl Main: Enable, Chk64bit 705 | } Else { 706 | GuiControl Main:, Chk64bit, 0 707 | GuiControl Main: Disable, Chk64bit 708 | } 709 | Return 710 | 711 | AddInclude: 712 | Gui Settings: Default 713 | Gui Submit, NoHide 714 | If (NewInclude != "") { 715 | GuiControl,, NewInclude 716 | LV_Add("Check", NewInclude) 717 | LV_ModifyCol(1, "AutoHdr") 718 | } 719 | Return 720 | 721 | RemoveInclude: 722 | If (Row := LV_GetNext()) { 723 | LV_Delete(Row) 724 | } 725 | Return 726 | 727 | SelectCompiler32: 728 | SelectCompiler("32") 729 | Return 730 | 731 | SelectCompiler64: 732 | SelectCompiler("64") 733 | Return 734 | 735 | SelectCompiler(xNN) { 736 | Global 737 | GuiControlGet CompilerPath%xNN%,, CompilerPath%xNN% 738 | SplitPath CompilerPath%xNN%,, CompilerDir 739 | Gui +OwnDialogs 740 | FileSelectFile SelectedFile, 3, %CompilerDir%, Select %xNN%-bit Compiler, Executable Files (*.exe) 741 | If (!ErrorLevel) { 742 | GuiControl,, CompilerPath%xNN%, %SelectedFile% 743 | 744 | GuiControlGet BatchFile, Settings:, BatchFile%xNN% 745 | If (BatchFile == "" && RegExMatch(SelectedFile, "i)cl.exe$")) { 746 | SplitPath SelectedFile,, CompilerDir 747 | BatchFile := CompilerDir . "\vcvars" . xNN . ".bat" 748 | If (FileExist(BatchFile)) { 749 | GuiControl, Settings:, BatchFile%xNN%, %BatchFile% 750 | } Else { 751 | BatchFile := GetParentDir(CompilerDir) . "\vcvars" . xNN . ".bat" 752 | If (FileExist(BatchFile)) { 753 | GuiControl, Settings:, BatchFile%xNN%, %BatchFile% 754 | } 755 | } 756 | } 757 | } 758 | } 759 | 760 | GetParentDir(Dir) { 761 | Return RegExReplace(Dir, "\\[^\\]+$") 762 | } 763 | 764 | SelectBatchFile32: 765 | GuiControlGet BatchFile32,, BatchFile32 766 | SplitPath BatchFile32,, BatchFileDir 767 | Gui +OwnDialogs 768 | FileSelectFile SelectedFile, 3, %BatchFileDir%, Select Batch File, Batch Files (*.bat; *.cmd) 769 | If (!ErrorLevel) { 770 | GuiControl,, BatchFile32, %SelectedFile% 771 | } 772 | Return 773 | 774 | SelectBatchFile64: 775 | GuiControlGet BatchFile64,, BatchFile64 776 | SplitPath BatchFile64,, BatchFileDir 777 | Gui +OwnDialogs 778 | FileSelectFile SelectedFile, 3, %BatchFileDir%, Select Batch File, Batch Files (*.bat; *.cmd) 779 | If (!ErrorLevel) { 780 | GuiControl,, BatchFile64, %SelectedFile% 781 | } 782 | Return 783 | 784 | LoadSettings: 785 | IniFile := GetIniFileLocation("Structor.ini") 786 | 787 | IniRead Chk32bit, %IniFile%, Settings, 32bitOffsets, 0 788 | IniRead Chk64bit, %IniFile%, Settings, 64bitOffsets, 0 789 | IniRead PausePrompt, %IniFile%, Settings, PausePrompt, 0 790 | IniRead ChkNumGet, %IniFile%, Settings, NumGet, 1 791 | IniRead ChkNumPut, %IniFile%, Settings, NumPut, 1 792 | IniRead ShortTernary, %IniFile%, Settings, ShortTernary, 1 793 | 794 | IniRead CompilerPath32, %IniFile%, Compiler, CompilerPath32, %A_Space% 795 | IniRead BatchFile32, %IniFile%, Compiler, BatchFile32, %A_Space% 796 | IniRead CompilerPath64, %IniFile%, Compiler, CompilerPath64, %A_Space% 797 | IniRead BatchFile64, %IniFile%, Compiler, BatchFile64, %A_Space% 798 | 799 | IniRead strIncludes, %IniFile%, Includes 800 | arrIncludes := [] 801 | If (strIncludes == "" || strIncludes == "ERROR") { 802 | arrIncludes.Push("windows.h") 803 | arrIncludes.Push("commctrl.h") 804 | } Else { 805 | Loop Parse, strIncludes, `n 806 | { 807 | Pair := StrSplit(A_LoopField, "=") 808 | If (Pair[1] == 1) { 809 | arrIncludes.Push(Pair[2]) 810 | } 811 | } 812 | } 813 | Return 814 | 815 | SaveSettings: 816 | CreateIniFile() 817 | 818 | Gui Main: Submit, NoHide 819 | 820 | IniWrite %Chk32bit%, %IniFile%, Settings, 32bitOffsets 821 | IniWrite %Chk64bit%, %IniFile%, Settings, 64bitOffsets 822 | IniWrite %PausePrompt%, %IniFile%, Settings, PausePrompt 823 | IniWrite %ChkNumGet%, %IniFile%, Settings, NumGet 824 | IniWrite %ChkNumPut%, %IniFile%, Settings, NumPut 825 | IniWrite %ShortTernary%, %IniFile%, Settings, ShortTernary 826 | 827 | IniWrite %CompilerPath32%, %IniFile%, Compiler, CompilerPath32 828 | IniWrite %BatchFile32%, %IniFile%, Compiler, BatchFile32 829 | IniWrite %CompilerPath64%, %IniFile%, Compiler, CompilerPath64 830 | IniWrite %BatchFile64%, %IniFile%, Compiler, BatchFile64 831 | 832 | IniWrite %strIncludes%, %IniFile%, Includes 833 | Return 834 | 835 | EnableParse: 836 | Gui Main: Submit, NoHide 837 | If (Input != "" && (Chk32bit || Chk64bit)) { 838 | GuiControl Main: Enable, BtnParse 839 | } Else { 840 | GuiControl Main: Disable, BtnParse 841 | } 842 | Return 843 | 844 | OnWM_KEYDOWN(wParam, lParam, msg, hWnd) { 845 | Global 846 | 847 | If (hWnd == hEdtHeader && wParam == 13) { 848 | GoSub AddInclude 849 | Return False 850 | 851 | } Else If (wParam == 120) { ; F9 852 | GoSub GetOffsets 853 | 854 | } Else If (wParam ~= "113|114|115") { ; F2, F3, F4 855 | Test(wParam) 856 | } 857 | } 858 | 859 | Test(Key) { 860 | If (Key == 113) { 861 | Struct = 862 | ( 863 | typedef struct { 864 | int iBitmap; 865 | int idCommand; 866 | BYTE fsState; 867 | BYTE fsStyle; 868 | #ifdef _WIN64 869 | BYTE bReserved[6]; 870 | #else 871 | #if defined(_WIN32) 872 | BYTE bReserved[2]; 873 | #endif 874 | #endif 875 | DWORD_PTR dwData; 876 | INT_PTR iString; 877 | } TBBUTTON, *PTBBUTTON, *LPTBBUTTON; 878 | ) 879 | } Else If (Key == 114) { 880 | Struct = 881 | ( 882 | typedef struct _SHFILEINFO { 883 | HICON hIcon; 884 | int iIcon; 885 | DWORD dwAttributes; 886 | TCHAR szDisplayName[MAX_PATH]; 887 | TCHAR szTypeName[80]; 888 | } SHFILEINFO; 889 | ) 890 | } Else If (Key == 115) { 891 | Struct = 892 | ( 893 | typedef struct tagWINDOWPLACEMENT { 894 | UINT length; 895 | UINT flags; 896 | UINT showCmd; 897 | POINT ptMinPosition; 898 | POINT ptMaxPosition; 899 | RECT rcNormalPosition; 900 | } WINDOWPLACEMENT, *PWINDOWPLACEMENT, *LPWINDOWPLACEMENT; 901 | ) 902 | } 903 | GuiControl Main:, Input, %Struct% 904 | GoSub EnableParse 905 | } 906 | 907 | OnWM_SYSCOMMAND(wParam, lParam, msg, hWnd) { 908 | If (wParam == 0xC0DE) { 909 | ShowAbout() 910 | } 911 | } 912 | 913 | ShowAbout() { 914 | Gui Main: +Disabled 915 | Gui About: New, -SysMenu OwnerMain 916 | Gui Color, White 917 | Gui Add, Picture, x15 y16 w32 h32, %A_ScriptDir%\Icons\Structor.ico 918 | Gui Font, s12 c0x003399, Segoe UI 919 | Gui Add, Text, x56 y11 w120 h23 +0x200, %AppName% 920 | Gui Font, s9 cDefault, Segoe UI 921 | Gui Add, Text, x56 y34 h18 +0x200, Structure helper (v %Version%) 922 | Gui Add, Text, x1 y72 w391 h48 -Background 923 | Gui Add, Button, gAboutGuiClose x299 y85 w80 h23 Default, &OK 924 | Gui Show, w392 h120, About 925 | } 926 | 927 | AboutGuiClose() { 928 | AboutGuiEscape: 929 | Gui Main: -Disabled 930 | Gui About: Destroy 931 | Return 932 | } 933 | 934 | ShowHelp() { 935 | Gui Settings: +OwnDialogs 936 | MsgBox 0, Help, %AppName% requires a C compiler. Supported: Visual Studio and MinGW.`n`n♦ Visual Studio`, Windows SDK`n`nCompiler Path: path to CL.EXE. Example:`nC:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\cl.exe`n`nBatch File: path to VCVARS32.bat or VCVARS64.BAT. Example:`nC:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\vcvars32.bat`n`n♦ MinGW or similars`n`nCompiler Path: path to GCC.EXE. Example:`nC:\MinGW\bin\gcc.exe`n`nBatch File: only needed if the gcc.exe directory is not in the PATH.`n`nEnable "Pause Command Prompt" to see compiler error messages. 937 | } 938 | 939 | GetExePathAndArgs(ByRef ExePath, ByRef Args) { 940 | Local Attrib, FoundPos, FilePath 941 | 942 | Attrib := FileExist(ExePath) 943 | If (Attrib && !InStr(Attrib, "D")) { 944 | Return 1 945 | 946 | } Else { 947 | FoundPos := InStr(ExePath, ".exe") 948 | If (FoundPos) { 949 | FilePath := SubStr(ExePath, 1, FoundPos + 3) 950 | If (FileExist(FilePath)) { 951 | If (StrLen(FilePath) < StrLen(ExePath)) { 952 | Args := SubStr(ExePath, StrLen(FilePath) + 2) 953 | } 954 | 955 | ExePath := FilePath 956 | Return 1 957 | } 958 | } 959 | } 960 | 961 | Return 0 962 | } 963 | 964 | GetIniFileLocation(Filename) { 965 | Local FullPath, AppCfgFile 966 | FullPath := A_ScriptDir . "\" . Filename 967 | 968 | If (!FileExist(FullPath)) { 969 | AppCfgFile := g_AppData . "\" . Filename 970 | If (FileExist(AppCfgFile)) { 971 | Return AppCfgFile 972 | } 973 | } 974 | 975 | Return FullPath 976 | } 977 | 978 | CreateIniFile() { 979 | Local Sections 980 | 981 | If (!FileExist(IniFile)) { 982 | Sections := "[Settings]`n`n[Compiler]`n`n[Includes]`n" 983 | 984 | FileAppend %Sections%, %IniFile%, UTF-16 985 | If (ErrorLevel) { 986 | FileCreateDir %g_AppData% 987 | IniFile := g_AppData . "\Structor.ini" 988 | FileDelete %IniFile% 989 | FileAppend %Sections%, %IniFile%, UTF-16 990 | } 991 | } 992 | } 993 | 994 | SetMainIcon(IconRes, IconIndex := 1) { 995 | Try { 996 | Menu Tray, Icon, % A_IsCompiled ? A_ScriptName : IconRes, %IconIndex% 997 | } 998 | } 999 | 1000 | #Include %A_ScriptDir%\Lib\AutoXYWH.ahk 1001 | #Include %A_ScriptDir%\Lib\CreateGradient.ahk 1002 | #Include %A_ScriptDir%\Lib\RunGetStdout.ahk 1003 | -------------------------------------------------------------------------------- /Verifier.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | 本工具提取自 : Adventure IDE - 3.0.4 3 | 完整版默认编译器 : MSVC2022_Mini 4 | 默认编译器制作说明: MSVC2022 制作说明.txt 5 | 6 | 为实现工具便携性与使用傻瓜化,部分代码有修改,需自行对比原版。 7 | 8 | */ 9 | 10 | ; Verifier - Check the size of data types and constant values 11 | ; Structor (another tool) provides information about structures (size and offsets) 12 | ; These tools require Windows SDK, Visual Studio or MinGW 13 | 14 | ; Derived from: https://github.com/ahkscript/AHK-SizeOf-Checker/ 15 | 16 | #SingleInstance Off 17 | #NoEnv 18 | #NoTrayIcon 19 | SetWorkingDir %A_ScriptDir% 20 | SetBatchLines -1 21 | 22 | ; 自动配置编译器路径 23 | #Include %A_ScriptDir%\Lib\MSVC2022.ahk 24 | 25 | Global AppName := "Verifier" 26 | , Version := "1.1.3" 27 | , g_AppData := A_ScriptDir 28 | , Unicode := 1 29 | 30 | GoSub LoadSettings 31 | 32 | SetMainIcon(A_ScriptDir . "\Icons\" . AppName . ".ico") 33 | 34 | Gui Font, s9, Segoe UI 35 | Gui Color, White 36 | 37 | Gui Add, Text, vLblInputType x18 y18 w100 h21 +0x200, &Size of: 38 | Gui Add, Edit, hWndhEdtInput vInput gEnableGET x124 y18 w200 h21, DWORD 39 | Gui Add, DropDownList, hWndh1 vInputType gSetInputType x331 y17 w80, Size||Offset|Constant 40 | GuiControl Choose, InputType, %InputType% 41 | GoSub SetInputType 42 | 43 | Gui Add, Button, gSelectList x418 y16 w80 h25, From &List... 44 | 45 | Gui Add, Text, x18 y61 w100 h23 +0x200, Compiler: 46 | Gui Add, DropDownList, vCompiler gSetCompiler x124 y61 w120, Visual Studio||MinGW 47 | GuiControl Choose, Compiler, %Compiler% 48 | 49 | Gui Add, Text, x18 y96 w100 h23 +0x200, Platform: 50 | Gui Add, DropDownList, vPlatform gSetPlatform x124 y96 w63, x86||x64 51 | GuiControl Choose, Platform, %Platform% 52 | 53 | Gui Add, Text, x18 y143 w100 h21 +0x200, Compiler Path: 54 | Gui Add, Edit, vCompilerPath gEnableGET x124 y143 w426 55 | Gui Add, Button, gSelectCompiler x557 y141 w80 h24, Browse... 56 | 57 | Gui Add, Text, x18 y177 w100 h21 +0x200, Batch File: 58 | Gui Add, Edit, vBatchFile x124 y177 w426 59 | Gui Add, Button, gSelectBatch x557 y176 w80 h24, Browse... 60 | 61 | Gui Add, Text, x18 y215 w100 h21 +0x200, &Includes: 62 | Gui Add, Edit, hWndhEdtHeader vNewInclude x124 y215 w200 h21 63 | Gui Add, Button, gAddInclude x331 y214 w80 h23, &Add 64 | Gui Add, Button, gRemoveInclude x331 y246 w80 h23, &Remove 65 | Gui Add, ListView, hWndhListView x124 y246 w200 h150 -Hdr +LV0x114004, Headers 66 | 67 | Gui Add, CheckBox, vUnicode x488 y350 w167 h23 Checked, &Unicode 68 | Gui Add, CheckBox, vPausePrompt x488 y374 w167 h23 Checked%PausePrompt%, &Pause command prompt 69 | 70 | Gui Add, Text, x-1 y410 w660 h48 -Background +Border 71 | Gui Add, Button, gCheck x124 y422 w80 h23 +Disabled, &Check 72 | Gui Add, Edit, vOutput x213 y423 w345 h21 +ReadOnly -Background 73 | Gui Add, Button, gGuiClose x567 y422 w80 h23, Close 74 | 75 | Gui Add, Button, gShowHelp x557 y18 w80 h24, &Help 76 | Gui Add, Button, gShowAbout x557 y52 w80 h24, About 77 | 78 | Comp := (Compiler == "Visual Studio") ? "VS" : "MinGW" 79 | Plat := (Platform == "x86") ? "" : "64" 80 | GuiControl,, CompilerPath, % %Comp%CompilerPath%Plat% 81 | GuiControl,, BatchFile, % %Comp%BatchFile%Plat% 82 | 83 | If (Includes != "" && Includes != "ERROR") { 84 | Loop Parse, Includes, `n 85 | { 86 | Pair := StrSplit(A_LoopField, "=") 87 | Checked := (Pair[1] == 1) ? "Check" : "" 88 | LV_Add(Checked, Pair[2]) 89 | } 90 | LV_ModifyCol(1, "AutoHdr") 91 | } Else { 92 | LV_Add("Check", "windows.h") 93 | LV_Add("", "commctrl.h") 94 | } 95 | 96 | Gui Show, w658 h457, %AppName% 97 | 98 | ; EM_SETCUEBANNER 99 | DllCall("SendMessage", "Ptr", hEdtHeader, "UInt", 0x1501, "Ptr", 0, "WStr", "Header file", "Ptr") 100 | 101 | DllCall("UxTheme.dll\SetWindowTheme", "Ptr", hListView, "WStr", "Explorer", "Ptr", 0) 102 | 103 | RegRead ProductName, HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion, ProductName 104 | 105 | OnMessage(0x100, "OnWM_KEYDOWN") 106 | 107 | Return 108 | 109 | GuiEscape: 110 | GuiClose: 111 | GoSub SaveSettings 112 | DeleteTempFiles() 113 | ExitApp 114 | 115 | Check: 116 | Gui Submit, NoHide 117 | 118 | If (InStr(Input, ":\") && FileExist(Input)) { 119 | BulkList := Input 120 | BulkMode := True 121 | } Else { 122 | BulkMode := False 123 | } 124 | 125 | DeleteTempFiles() 126 | 127 | ; Compile.bat 128 | Bat := "@ECHO OFF`r`nCD /D " . A_Temp . "`r`n" 129 | If (BatchFile != "") { 130 | Bat .= "CALL """ . BatchFile . """`r`n" 131 | } 132 | 133 | If (!GetExePathAndArgs(CompilerPath, Args)) { 134 | Gui +OwnDialogs 135 | MsgBox 0x10, %AppName%, Invalid file path: %CompilerPath% 136 | Return 137 | } 138 | 139 | If (Args != "") { 140 | Args := " " . Args 141 | } 142 | 143 | If (Compiler == "Visual Studio") { 144 | Bat .= """" . CompilerPath . """" . Args . " sizeof.c" 145 | } Else { 146 | Bat .= """" . CompilerPath . """" . Args . " sizeof.c -o sizeof.exe" 147 | } 148 | 149 | If (PausePrompt) { 150 | Bat .= "`r`nECHO. && PAUSE" 151 | } 152 | 153 | FileAppend %Bat%, %A_Temp%\Compile.bat 154 | 155 | Includes := [] 156 | Row := 0 157 | While (Row := LV_GetNext(Row, "Checked")) { 158 | LV_GetText(Include, Row) 159 | Includes.Push(Include) 160 | } 161 | 162 | ; sizeof.c 163 | C := "" 164 | 165 | If (Unicode) { 166 | C .= "#define UNICODE 1`r`n" 167 | } 168 | 169 | C .= "#include `r`n" 170 | If (InputType == "Offset") { 171 | C .= "#include `r`n" 172 | } 173 | 174 | Loop % Includes.Length() { 175 | If (InStr(Includes[A_Index], ":")) { 176 | C .= "#include """ . Includes[A_Index] . """`r`n" 177 | } Else { 178 | C .= "#include <" . Includes[A_Index] . ">`r`n" 179 | } 180 | } 181 | 182 | C .= "`r`nint main() {`r`n" 183 | If (BulkMode) { 184 | FileRead List, %BulkList% 185 | Loop Parse, List, `n, `r 186 | { 187 | If (A_LoopField != "") { 188 | If (InputType == "Size") { 189 | C .= " printf(""" . A_LoopField . " = %d\n"", sizeof(" . A_LoopField . "));`r`n" 190 | 191 | } Else If (InputType == "Offset") { 192 | offsetof := StrSplit(A_LoopField, ".") 193 | C .= " printf(""" . A_LoopField . " = %d\n"", " 194 | C .= "offsetof(" . offsetof[1] . ", " . offsetof[2] . "));`r`n" 195 | 196 | } Else If (InputType == "Constant") { 197 | C .= " printf(""" . A_LoopField . " = 0x%X (%d)\n"", " 198 | C .= A_LoopField . "," . A_LoopField . ");`r`n" 199 | } 200 | } 201 | } 202 | } Else { 203 | If (InputType == "Size") { 204 | C .= " printf(""%d"", sizeof(" . Input . "));`r`n" 205 | } Else If (InputType == "Offset") { 206 | offsetof := StrSplit(Input, ".") 207 | C .= " printf(""%d"", offsetof(" . offsetof[1] . ", " . offsetof[2] . "));`r`n" 208 | } Else If (InputType == "Constant") { 209 | C .= " printf(""0x%X (%d)"", " . Input . ", " . Input . ");`r`n" 210 | } 211 | } 212 | C .= " return 0;`r`n}`r`n" 213 | 214 | FileAppend %C%, %A_Temp%\sizeof.c 215 | 216 | GuiControl,, Output, Compiling... 217 | RunWait %A_Temp%\Compile.bat,, % PausePrompt ? "" : "Hide" 218 | 219 | Stdout := RunGetStdout(A_Temp . "\sizeof.exe") 220 | 221 | If (A_LastError == 2) { ; File not found 222 | GuiControl,, Output, Compilation failed. 223 | Return 224 | } 225 | 226 | If (BulkMode) { 227 | GuiControl,, Output, Done 228 | If (GetKeyState("Shift", "P")) { 229 | Gui +OwnDialogs 230 | MsgBox 0, %AppName%, %Stdout% 231 | } Else { 232 | SplitPath BulkList,, FileDir 233 | Gui +OwnDialogs 234 | FileSelectFile SelectedFile, S16, %FileDir%, Save File 235 | If (!ErrorLevel) { 236 | Text := Compiler . " " . Platform . " on " . ProductName . "`r`n`r`n" . Stdout 237 | FileDelete %SelectedFile% 238 | FileAppend %Text%, %SelectedFile% 239 | } 240 | } 241 | } Else { 242 | Type := (InputType == "Constant") ? "Value" : InputType 243 | If (Type == "Size") { 244 | Bytes := Stdout == 1 ? " byte" : " bytes" 245 | Stdout .= Bytes 246 | } 247 | 248 | GuiControl,, Output, %Type% of %Input% is %Stdout% 249 | 250 | If (LogOutput) { 251 | If (!FileExist(LogFile)) { 252 | FileAppend %ProductName%`r`n`r`n, %LogFile% 253 | } 254 | 255 | Line := Type . " of " . Input . " is " . Stdout . " (" . Compiler . " " . Platform . ")`r`n" 256 | FileAppend %Line% , %LogFile% 257 | } 258 | } 259 | Return 260 | 261 | DeleteTempFiles() { 262 | FileDelete %A_Temp%\Compile.bat 263 | FileDelete %A_Temp%\sizeof.c 264 | FileDelete %A_Temp%\sizeof.obj 265 | FileDelete %A_Temp%\sizeof.exe 266 | } 267 | 268 | AddInclude: 269 | Gui Submit, NoHide 270 | If (NewInclude != "") { 271 | GuiControl,, NewInclude 272 | LV_Add("Check", NewInclude) 273 | LV_ModifyCol(1, "AutoHdr") 274 | } 275 | Return 276 | 277 | RemoveInclude: 278 | If (Row := LV_GetNext()) { 279 | LV_Delete(Row) 280 | } 281 | Return 282 | 283 | SelectList: 284 | Gui +OwnDialogs 285 | FileSelectFile BulkList, 3,, Select List 286 | If (!ErrorLevel) { 287 | GuiControl,, Input, %BulkList% 288 | } 289 | Return 290 | 291 | SelectCompiler: 292 | GuiControlGet CompilerPath,, CompilerPath 293 | SplitPath CompilerPath,, CompilerDir 294 | Gui +OwnDialogs 295 | FileSelectFile SelectedFile, 3, %CompilerDir%, Select Compiler, Executable Files (*.exe) 296 | If (!ErrorLevel) { 297 | GuiControl,, CompilerPath, %SelectedFile% 298 | } 299 | Return 300 | 301 | SelectBatch: 302 | GuiControlGet BatchFile,, BatchFile 303 | SplitPath BatchFile,, BatchDir 304 | Gui +OwnDialogs 305 | FileSelectFile SelectedFile, 3, %BatchDir%, Select Batch File, Batch Files (*.bat; *.cmd) 306 | If (!ErrorLevel) { 307 | GuiControl,, BatchFile, %SelectedFile% 308 | } 309 | Return 310 | 311 | SetCompiler: 312 | ; Store values before submit 313 | GuiControlGet Platform,, Platform 314 | GuiControlGet CompilerPath,, CompilerPath 315 | GuiControlGet BatchFile,, BatchFile 316 | 317 | If (Compiler == "Visual Studio") { ; Changing from VS to MinGW 318 | If (Platform == "x86") { 319 | VSCompilerPath := CompilerPath 320 | VSBatchFile := BatchFile 321 | } Else { 322 | VSCompilerPath64 := CompilerPath 323 | VSBatchFile64 := BatchFile 324 | } 325 | } Else { ; Changing from MinGW to VS 326 | If (Platform == "x86") { 327 | MinGWCompilerPath := CompilerPath 328 | MinGWBatchFile := BatchFile 329 | } Else { 330 | MinGWCompilerPath64 := CompilerPath 331 | MinGWBatchFile64 := BatchFile 332 | } 333 | } 334 | 335 | GoSub SetCompilerPath 336 | Return 337 | 338 | SetPlatform: 339 | ; Store values before submit 340 | GuiControlGet Compiler,, Compiler 341 | GuiControlGet CompilerPath,, CompilerPath 342 | GuiControlGet BatchFile,, BatchFile 343 | 344 | If (Platform == "x86") { ; Changing from x86 to x64 345 | If (Compiler == "Visual Studio") { 346 | VSCompilerPath := CompilerPath 347 | VSBatchFile := BatchFile 348 | } Else { 349 | MinGWCompilerPath := CompilerPath 350 | MinGWBatchFile := BatchFile 351 | } 352 | } Else { ; Changing from x64 to x86 353 | If (Compiler == "Visual Studio") { 354 | VSCompilerPath64 := CompilerPath 355 | VSBatchFile64 := BatchFile 356 | } Else { 357 | MinGWCompilerPath64 := CompilerPath 358 | MinGWBatchFile64 := BatchFile 359 | } 360 | } 361 | 362 | GoSub SetCompilerPath 363 | Return 364 | 365 | SetCompilerPath: 366 | Gui Submit, NoHide 367 | 368 | If (Compiler == "Visual Studio") { 369 | If (Platform == "x86") { 370 | GuiControl,, CompilerPath, %VSCompilerPath% 371 | GuiControl,, BatchFile, %VSBatchFile% 372 | } Else { 373 | GuiControl,, CompilerPath, %VSCompilerPath64% 374 | GuiControl,, BatchFile, %VSBatchFile64% 375 | } 376 | } Else If (Compiler == "MinGW") { 377 | If (Platform == "x86") { 378 | GuiControl,, CompilerPath, %MinGWCompilerPath% 379 | GuiControl,, BatchFile, %MinGWBatchFile% 380 | } Else { 381 | GuiControl,, CompilerPath, %MinGWCompilerPath64% 382 | GuiControl,, BatchFile, %MinGWBatchFile64% 383 | } 384 | } 385 | Return 386 | 387 | LoadSettings: 388 | IniFile := GetIniFileLocation("Verifier.ini") 389 | 390 | IniRead InputType, %IniFile%, Settings, InputType, Size 391 | 392 | IniRead Compiler, %IniFile%, Settings, Compiler, Visual Studio 393 | IniRead Platform, %IniFile%, Settings, Platform, x86 394 | 395 | IniRead VSCompilerPath, %IniFile%, Visual Studio, CompilerPath, %A_Space% 396 | IniRead VSCompilerPath64, %IniFile%, Visual Studio, CompilerPath64, %A_Space% 397 | IniRead VSBatchFile, %IniFile%, Visual Studio, BatchFile, %A_Space% 398 | IniRead VSBatchFile64, %IniFile%, Visual Studio, BatchFile64, %A_Space% 399 | 400 | IniRead MinGWCompilerPath, %IniFile%, MinGW, CompilerPath, %A_Space% 401 | IniRead MinGWCompilerPath64, %IniFile%, MinGW, CompilerPath64, %A_Space% 402 | IniRead MinGWBatchFile, %IniFile%, MinGW, BatchFile, %A_Space% 403 | IniRead MinGWBatchFile64, %IniFile%, MinGW, BatchFile64, %A_Space% 404 | 405 | IniRead Includes, %IniFile%, Includes 406 | 407 | IniRead PausePrompt, %IniFile%, Settings, PausePrompt, 0 408 | 409 | IniRead LogOutput, %IniFile%, Log, LogOutput, 0 410 | IniRead LogFile, %IniFile%, Log, LogFile, %AppName%.log 411 | Return 412 | 413 | SaveSettings: 414 | CreateIniFile() 415 | 416 | Gui Submit, NoHide 417 | 418 | Comp := (Compiler == "Visual Studio") ? "VS" : "MinGW" 419 | Plat := (Platform == "x86") ? "" : "64" 420 | %Comp%CompilerPath%Plat% := CompilerPath 421 | %Comp%BatchFile%Plat% := BatchFile 422 | 423 | IniWrite %InputType%, %IniFile%, Settings, InputType 424 | 425 | IniWrite %Compiler%, %IniFile%, Settings, Compiler 426 | IniWrite %Platform%, %IniFile%, Settings, Platform 427 | 428 | IniWrite %VSCompilerPath%, %IniFile%, Visual Studio, CompilerPath 429 | IniWrite %VSCompilerPath64%, %IniFile%, Visual Studio, CompilerPath64 430 | IniWrite %VSBatchFile%, %IniFile%, Visual Studio, BatchFile 431 | IniWrite %VSBatchFile64%, %IniFile%, Visual Studio, BatchFile64 432 | 433 | IniWrite %MinGWCompilerPath%, %IniFile%, MinGW, CompilerPath 434 | IniWrite %MinGWCompilerPath64%, %IniFile%, MinGW, CompilerPath64 435 | IniWrite %MinGWBatchFile%, %IniFile%, MinGW, BatchFile 436 | IniWrite %MinGWBatchFile64%, %IniFile%, MinGW, BatchFile64 437 | 438 | Includes := "" 439 | Loop % LV_GetCount() { 440 | LV_GetText(Text, A_Index) 441 | 442 | Checked := 0 443 | SendMessage 0x102C, % A_Index - 1, 0x2000,, ahk_id %hListView% ; LVM_GETITEMSTATE, LVIS_CHECKED 444 | If (Errorlevel == 0x2000) { 445 | Checked := 1 446 | } 447 | 448 | Includes .= Checked . "=" . Text . "`n" 449 | 450 | IniWrite %Includes%, %IniFile%, Includes 451 | } 452 | 453 | IniWrite %PausePrompt%, %IniFile%, Settings, PausePrompt 454 | 455 | IniWrite %LogOutput%, %IniFile%, Log, LogOutput 456 | IniWrite %LogFile%, %IniFile%, Log, LogFile 457 | Return 458 | 459 | ShowHelp() { 460 | Gui +OwnDialogs 461 | MsgBox 0, Help, Usage: enter the name of a data type or constant declared in a header file.`nExamples: DWORD`, SYSTEMTIME.wHour`, LVM_GETHEADER (requires commctrl.h)`, etc.`n`nSet compiler and platform before defining the compiler path.`n`n♦ Windows SDK or Visual Studio`n`nCompiler path: path to CL.EXE. Example:`nC:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\cl.exe`n`nBatch file: path to VCVARS32.BAT or VCVARS64.BAT or VCVARSX86_AMD64.BAT. Example:`nC:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\vcvars32.bat`n`n♦ MinGW or similars`n`nCompiler path: path to GCC.EXE. Example:`nC:\MinGW\bin\gcc.exe`n`nBatch file: only required if the gcc.exe directory is not in the PATH.`n`nAnother tool, Structor, is more appropriate for information about structures (size and offsets). 462 | } 463 | 464 | ShowAbout() { 465 | Gui 1: +Disabled 466 | Gui About: New, -SysMenu Owner1 467 | Gui Color, White 468 | Gui Add, Picture, x15 y16 w32 h32, %A_ScriptDir%\Icons\%AppName%.ico 469 | Gui Font, s12 c0x003399, Segoe UI 470 | Gui Add, Text, x56 y11 w120 h23 +0x200, %AppName% 471 | Gui Font, s9 cDefault, Segoe UI 472 | Gui Add, Text, x56 y34 h18 +0x200, Size of data types and constant values (v %Version%) 473 | Gui Add, Text, x1 y72 w391 h48 -Background 474 | Gui Add, Button, gAboutGuiClose x299 y85 w80 h23 Default, &OK 475 | Gui Font 476 | Gui Show, w392 h120, About 477 | } 478 | 479 | AboutGuiClose() { 480 | AboutGuiEscape: 481 | Gui 1: -Disabled 482 | Gui About: Destroy 483 | Return 484 | } 485 | 486 | OnWM_KEYDOWN(wParam) { 487 | If (wParam == 120) { ; F9 488 | GoSub Check 489 | } 490 | } 491 | 492 | EnableGET: 493 | Gui Submit, NoHide 494 | If (Input != "" && CompilerPath != "") { 495 | GuiControl Enable, &Check 496 | } Else { 497 | GuiControl Disable, &Check 498 | } 499 | Return 500 | 501 | SetInputType: 502 | GuiControlGet InputType,, InputType 503 | GuiControl,, LblInputType, % (InputType == "Size") ? "&Size of:" : InputType . ":" 504 | HintText := {"Size": "Structure or data type", "Offset": "Structure.Member", "Constant": ""} 505 | DllCall("SendMessage", "Ptr", hEdtInput, "UInt", 0x1501, "Ptr", 0, "WStr", HintText[InputType], "Ptr") 506 | Return 507 | 508 | GetExePathAndArgs(ByRef ExePath, ByRef Args) { 509 | Local Attrib, FoundPos, FilePath 510 | 511 | Attrib := FileExist(ExePath) 512 | If (Attrib && !InStr(Attrib, "D")) { 513 | Return 1 514 | 515 | } Else { 516 | FoundPos := InStr(ExePath, ".exe") 517 | If (FoundPos) { 518 | FilePath := SubStr(ExePath, 1, FoundPos + 3) 519 | If (FileExist(FilePath)) { 520 | If (StrLen(FilePath) < StrLen(ExePath)) { 521 | Args := SubStr(ExePath, StrLen(FilePath) + 2) 522 | } 523 | 524 | ExePath := FilePath 525 | Return 1 526 | } 527 | } 528 | } 529 | 530 | Return 0 531 | } 532 | 533 | GetIniFileLocation(Filename) { 534 | Local FullPath, AppCfgFile 535 | FullPath := A_ScriptDir . "\" . Filename 536 | 537 | If (!FileExist(FullPath)) { 538 | AppCfgFile := g_AppData . "\" . Filename 539 | If (FileExist(AppCfgFile)) { 540 | Return AppCfgFile 541 | } 542 | } 543 | 544 | Return FullPath 545 | } 546 | 547 | CreateIniFile() { 548 | Local Sections 549 | 550 | If (!FileExist(IniFile)) { 551 | Sections := "[Settings]`n`n[Visual Studio]`n`n[MinGW]`n`n[Includes]`n`n[Log]`n" 552 | 553 | FileAppend %Sections%, %IniFile%, UTF-16 554 | If (ErrorLevel) { 555 | FileCreateDir %g_AppData% 556 | IniFile := g_AppData . "\Verifier.ini" 557 | FileDelete %IniFile% 558 | FileAppend %Sections%, %IniFile%, UTF-16 559 | } 560 | } 561 | } 562 | 563 | SetMainIcon(IconRes, IconIndex := 1) { 564 | Try { 565 | Menu Tray, Icon, % A_IsCompiled ? A_ScriptName : IconRes, %IconIndex% 566 | } 567 | } 568 | 569 | #Include %A_ScriptDir%\Lib\RunGetStdout.ahk 570 | --------------------------------------------------------------------------------