C++: DllCall: get parameter types/sizes

Discuss other programming languages besides AutoHotkey
User avatar
jeeswg
Posts: 5448
Joined: 19 Dec 2016, 01:58
Location: UK

C++: DllCall: get parameter types/sizes

04 Nov 2017, 17:46

- Using the list of dlls and functions here:
WinApi
https://hotkeyit.github.io/v2/docs/commands/WinApi.htm
I created a list of all the raw parameter descriptions for each dll function, and removed the duplicates to give 7686 unique parameter names.
- I then attempted to create a struct definition based on each of these parameters and retrieve the size of them of in C++, the x64 and x32 sizes.
- I obtained all of the uppercase words and kept including .h files, and adding custom definitions, until all of them were defined.
- I pasted in definitions for all the structs, and tried multiple times to compile the script, retrieving a list of lines that had errors and commenting out those lines until the script compiled. I had to comment out about 10% of the struct definitions.

I used this AutoHotkey code to generate the list of structs.

Code: Select all

q:: ;Winapi.htm - list unique parameters
;WinApi
;https://hotkeyit.github.io/v2/docs/commands/WinApi.htm

;warning: there is one awkward parameter: DWORD dwFlags = SHPPFW_DEFAULT

vPath = %A_Desktop%\WinApi [hotkeyit.github.io].htm
oHTML := ComObjCreate("HTMLFile")
vHtml = <meta http-equiv="X-UA-Compatible" content="IE=9">
oHTML.write(vHtml)
FileRead, vHtml, % vPath
oHTML.write(vHtml)

oArray := {}
Loop, % oHTML.getElementsByTagName("table").length
{
	if (A_Index = 1)
		continue
	oTable := oHTML.getElementsByTagName("table")[A_Index-1]
	oRows := oTable.rows
	;vDll := oHTML.getElementsByTagName("h2")[A_Index-2].innerText
	;if (SubStr(vDll, StrLen(vTemp)+1-4) = ".dll")
	;	vDll := SubStr(vDll, 1, -4)
	Loop % oRows.length
	{
		oCells := oRows[A_Index-1].cells
		vDef := oCells[2].innerText
		vDef := RegExReplace(vDef, "^\w+\(")
		vDef := RegExReplace(vDef, "\)$")
		Loop, Parse, vDef, % ","
		{
			vTemp := Trim(A_LoopField)
			if !oArray.HasKey("z" vTemp)
				oArray["z" vTemp] := ""
		}
	}
}
VarSetCapacity(vOutput, 1000000*2)

;for vKey, vValue in oArray
;	vOutput .= SubStr(vKey, 2) "`r`n"

;struct TEST1 { LIST; }; printf("LIST=%d\n", sizeof(TEST1));
for vKey, vValue in oArray
{
	vTemp := SubStr(vKey, 2)
	vNum := A_Index
	vOutput .= "struct TEST" vNum " { " vTemp "; }; printf(" Chr(34) vTemp "=%d\n" Chr(34) ", sizeof(TEST" vNum "));" "`r`n"
}

oHTML := oTable := oRows := oCells := ""
Clipboard := vOutput
MsgBox, % "done"
return
I used this AutoHotkey code to generate a list of parameters and sizes based on the information already in Winapi.htm. I wanted to use the Winapi.htm information, and my C++ list, to help me check that my lists of dll functions and their parameter sizes/types were correct.

Code: Select all

q:: ;Winapi.htm - list unique parameters and their sizes
;WinApi
;https://hotkeyit.github.io/v2/docs/commands/WinApi.htm

;warning: there is one awkward parameter: DWORD dwFlags = SHPPFW_DEFAULT

vPath = %A_Desktop%\WinApi [hotkeyit.github.io].htm
oHTML := ComObjCreate("HTMLFile")
vHtml = <meta http-equiv="X-UA-Compatible" content="IE=9">
oHTML.write(vHtml)
FileRead, vHtml, % vPath
oHTML.write(vHtml)

oSize := {c:"1:1",h:"2:2",i:"4:4",6:"8:8",t:"8:4",f:"4:4",d:"8:8",x:"4:2",z:"2:2"}
oSize["6"] := "8:8"
oArray := {}
Loop, % oHTML.getElementsByTagName("table").length
{
	if (A_Index = 1)
		continue
	oTable := oHTML.getElementsByTagName("table")[A_Index-1]
	oRows := oTable.rows
	;vDll := oHTML.getElementsByTagName("h2")[A_Index-2].innerText
	;if (SubStr(vDll, StrLen(vTemp)+1-4) = ".dll")
	;	vDll := SubStr(vDll, 1, -4)
	Loop % oRows.length
	{
		oCells := oRows[A_Index-1].cells
		vList := oCells[0].innerText
		vList := StrReplace(vList, "u")
		vList := StrReplace(vList, "i6", "6")
		vList := RegExReplace(vList, "[asw]", "t")
		vList := StrReplace(vList, "v", "x")
		vList := StrReplace(vList, "y", "z")
		vDef := oCells[2].innerText
		vDef := RegExReplace(vDef, "^\w+\(")
		vDef := RegExReplace(vDef, "\)$")
		Loop, Parse, vDef, % ","
		{
			vTemp := Trim(A_LoopField)
			if !oArray.HasKey("z" vTemp)
				oArray["z" vTemp] := oSize[SubStr(vList, A_Index, 1)]
		}
	}
}
VarSetCapacity(vOutput, 1000000*2)
for vKey, vValue in oArray
	vOutput .= SubStr(vKey, 2) "=" vValue "`r`n"
oHTML := oTable := oRows := oCells := ""
Clipboard := vOutput
MsgBox, % "done"
return
Every item generated by the script had a maximum size of 8 bytes or fewer. With these 7 exceptions.

Code: Select all

_In_ CLSID clsid=16:16
_In_ const SYSTEMTIME lpSysTime=16:16
_In_ CRYPT_PKCS8_IMPORT_PARAMS sPrivateKeyAndParams=48:24
_In_ STGMEDIUM pmedium=24:12
_In_ VARIANT varFileName=24:16
_Out_ STGMEDIUM pmedium=24:12
WCHAR name[LF_FACESIZE]=64:64
To retrieve the output from the C++ script:

Code: Select all

q:: ;console application - get output
vPath = C:\Users\%A_UserName%\Documents\visual studio 2013\Projects\ConsoleApplication14\Debug\ConsoleApplication14.exe
;vPath = C:\Users\%A_UserName%\Documents\visual studio 2013\Projects\ConsoleApplication14\x64\Debug\ConsoleApplication14.exe
Clipboard := JEE_RunGetStdOut(vPath)
return

;==================================================

JEE_RunGetStdOut(vTarget, vSize:="")
{
	DetectHiddenWindows, On
	vComSpec := A_ComSpec ? A_ComSpec : ComSpec
	Run, % vComSpec,, Hide, vPID
	WinWait, % "ahk_pid " vPID
	DllCall("kernel32\AttachConsole", UInt,vPID)
	oShell := ComObjCreate("WScript.Shell")
	oExec := oShell.Exec(vTarget)
	vStdOut := ""
	if !(vSize = "")
		VarSetCapacity(vStdOut, vSize)
	while !oExec.StdOut.AtEndOfStream
		vStdOut := oExec.StdOut.ReadAll()
	DllCall("kernel32\FreeConsole")
	Process, Close, % vPID
	return vStdOut
}
User avatar
jeeswg
Posts: 5448
Joined: 19 Dec 2016, 01:58
Location: UK

Re: C++: DllCall: get parameter types/sizes

04 Nov 2017, 18:31

Here is the C++ code I used, although with only 10 of the 7686 structs, so that it can fit in a post. I'm quite new to C++, so this the best I could come up with. I would welcome any comments or ideas for improving it.

Code: Select all

// dll function parameters get sizes by jeeswg

// based on:
// WinApi
// https://hotkeyit.github.io/v2/docs/commands/WinApi.htm

// based on the following dlls:
// Advapi32.dll, Comctl32.dll, Comdlg32.dll, Crypt32.dll, Gdi32.dll, Gdiplus.dll, Glu32.dll
// Hid.dll, Kernel32.dll, Ole32.dll, Oleacc.dll, OleAut32.dll, Opengl32.dll
// Rasapi32.dll, Rasdlg.dll, Rasman.dll, Shell32.dll, Shlwapi.dll, Tapi32.dll
// User32.dll, Userenv.dll, UxTheme.dll, Version.dll, Winhttp.dll, Wininet.dll, Winmm.dll, Ws2_32.dll

#include "stdafx.h"
#include <iostream>
#include <chrono> //for sleep_for
#include <thread> //for sleep_for

#include "Windows.h"
#include "CommCtrl.h"
#include "Wincrypt.h"
#include "Gdiplus.h"
//#include "GLU.h" //cannot open
#include "Hidsdi.h"
//#include "Synchapi.h" //on Windows 8 and Windows Server 2012
#include "Objbase.h"
#include "Oleacc.h"
#include "OleAuto.h"
//#include "GL.h" //cannot open
#include "Ras.h"
#include "Rasdlg.h"
#include "Rasshost.h"
#include "Shellapi.h"
#include "Shlwapi.h"
#include "Tapi.h"
#include "Userenv.h"
#include "Uxtheme.h"
#include "Winhttp.h"
//#include "WinInet.h" //causes errors
//#include "WinSock2.h"  //causes errors

//==================================================

#include "AclAPI.h"
#include "appmgmt.h"
#include "evntprov.h"
#include "evntrace.h"
#include "lowlevelmonitorconfigurationapi.h"
#include "mmddk.h"
#include "MSChapp.h"
#include "mssip.h"
#include "NTSecAPI.h"
#include "OleCtl.h"
#include "perflib.h"
#include "ShlObj.h"
#include "ShObjIdl.h"
#include "TlHelp32.h"
#include "wct.h"
#include "WERAPI.H"
#include "wincred.h"
//#include "Winineti.h" //causes errors
#include "winsafer.h"
//#include "WS2spi.h" //causes errors
//#include "WS2tcpip.h" //causes errors

//==================================================

//not guaranteed to be correct
//guessed as Int (int)/UInt (UINT)/Ptr (PVOID)/_ (TCHAR)
typedef int APITYPE;
typedef UINT ARGB;
typedef int CALDATETIME_DATEUNIT; //enum
typedef int GDIPARGB;
typedef int GDIPBITMAPINFO;
typedef int GDIPBYTE;
typedef int GDIPCLSID;
typedef int GDIPGUID;
typedef int GDIPLOGFONTA;
typedef int GDIPLOGFONTW;
typedef int GDIPREAL;
typedef int GDIPUINT16;
typedef int GDIPWCHAR;
typedef PVOID HCD; //typo in MSDN? should be HDC?
typedef PVOID LPCALDATETIME;
typedef PVOID LPMRUINFO;
typedef PVOID LPORPC_INIT_ARGS;
typedef PVOID LPRASNAPSTATE;
typedef PVOID LPTCSTR;
typedef PVOID POBJECTS_AND_NAME;
typedef PVOID PWORD64;
typedef int REAL;
typedef TCHAR TUCHAR; //is this U for unsigned? so UShort/UChar?
typedef int X;
typedef int Y;

//==================================================

//would be defined by one of:
/*
#include "WinInet.h" //causes errors
#include "WinSock2.h"  //causes errors
#include "Winineti.h" //causes errors
#include "WS2spi.h" //causes errors
#include "WS2tcpip.h" //causes errors
*/

//not guaranteed to be correct
typedef int ADDRINFOA;
typedef int ADDRINFOEX;
typedef int ADDRINFOW;
typedef int GOPHER_ATTRIBUTE_ENUMERATOR;
typedef int GROUP;
typedef int GROUPID;
typedef int INTERNET_STATUS_CALLBACK;
typedef PVOID LPCNSPV2_ROUTINE;
typedef PVOID LPCONDITIONPROC;
typedef PVOID LPGOPHER_FIND_DATA;
typedef PVOID LPINTERNET_BUFFERS;
typedef PVOID LPINTERNET_CACHE_CONFIG_INFO;
typedef PVOID LPINTERNET_CACHE_ENTRY_INFO;
typedef PVOID LPINTERNET_CACHE_GROUP_INFO;
typedef PVOID LPLOOKUPSERVICE_COMPLETION_ROUTINE;
typedef PVOID LPQOS;
typedef PVOID LPWSABUF;
typedef PVOID LPWSAMSG;
typedef PVOID LPWSANAMESPACE_INFO;
typedef PVOID LPWSANAMESPACE_INFOEX;
typedef PVOID LPWSANETWORKEVENTS;
typedef PVOID LPWSAOVERLAPPED;
typedef PVOID LPWSAOVERLAPPED_COMPLETION_ROUTINE;
typedef PVOID LPWSAPROTOCOL_INFO;
typedef PVOID LPWSAPROTOCOL_INFOW;
typedef PVOID LPWSAQUERYSET;
typedef PVOID LPWSASERVICECLASSINFO;
typedef PVOID PADDRINFOA;
typedef PVOID PADDRINFOEX;
typedef PVOID PADDRINFOW;
typedef PVOID PSOCKET_ADDRESS_LIST;
typedef int SOCKET_ADDRESS;
typedef int WSAESETSERVICEOP;
typedef int WSAEVENT;
typedef int WSAPOLLFD;
typedef int WSC_PROVIDER_INFO_TYPE;

//==================================================

int main()
{
	//struct TEST1 { ...; }; printf("...=%d\n", sizeof(TEST1));
	//struct TEST2 { __in const GdiplusStartupInput *input; }; printf("__in const GdiplusStartupInput *input=%d\n", sizeof(TEST2));
	struct TEST3 { __in DWORD dwLength; }; printf("__in DWORD dwLength=%d\n", sizeof(TEST3));
	struct TEST4 { __in DWORD dwNewValue; }; printf("__in DWORD dwNewValue=%d\n", sizeof(TEST4));
	struct TEST5 { __in DWORD dwPhysicalMonitorArraySize; }; printf("__in DWORD dwPhysicalMonitorArraySize=%d\n", sizeof(TEST5));

	// ...

	struct TEST7683 { WPARAM wParam; }; printf("WPARAM wParam=%d\n", sizeof(TEST7683));
	struct TEST7684 { WPARAM wRequestID; }; printf("WPARAM wRequestID=%d\n", sizeof(TEST7684));
	//struct TEST7685 { WrapMode wrap; }; printf("WrapMode wrap=%d\n", sizeof(TEST7685));
	struct TEST7686 { YIELDPROC yp; }; printf("YIELDPROC yp=%d\n", sizeof(TEST7686));
	//struct TEST7686 { YIELDPROC yp; }; printf("YIELDPROC yp=%d\n", sizeof(TEST7686));

	std::this_thread::sleep_for(std::chrono::milliseconds(2000));
}
Here's the full script:
Attachments
dll function parameters get sizes.zip
(111.62 KiB) Downloaded 38 times
HotKeyIt
Posts: 1713
Joined: 29 Sep 2013, 18:35
Contact:

Re: C++: DllCall: get parameter types/sizes

04 Nov 2017, 20:05

Many thanks for checking the parameters, much appreciated ;)
I have fixed 66 definitions and 710 functions in WinApi.
User avatar
jeeswg
Posts: 5448
Joined: 19 Dec 2016, 01:58
Location: UK

Re: C++: DllCall: get parameter types/sizes

04 Nov 2017, 20:31

Cheers, no problem. The Winapi.htm list has been useful to me many times and has been key in me checking and fixing my own small (700 or so) list of dll functions for correcting DllCall lines. ;)

DllCall converter/cleaner (e.g. x32 to x64/x32 two-way compatible) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=31365

Return to “Other Programming Languages”

Who is online

Users browsing this forum: No registered users and 1 guest