return-type function-name ( arg-type-1 arg-name-1 ... );
So for example the definition of SetWindowText looks like
BOOL SetWindowText ( HWND hWnd LPCTSTR lpString );
In all cases the arguments will be pushed starting with the rightmost argument. So to call the above function you push the arguments before calling like this:
If you know what the types HWND and LPCTSTR mean you will be able to convert the call to something like this:
push offset title1 ; address of new title string push dword ptr [ebp+8] ; hwnd from wndproc arg list call SetWindowText ; BOOL result (success/fail) in EAX ; arguments already popped by SetWindowTextThe above illustrates the stdcall calling convention used by most of the Win32 API functions. SetWindowText pops the arguments so that you won't need to. If it had used the cdecl calling convention you would've needed to reset ESP with an extra instruction as in the following:
add esp 8 ; pop two DWORD argumentsBecause SetWindowText uses a character string the documentation is actually referring to two functions: SetWindowTextA which uses a string of ANSI (8-bit) characters and SetWindowTextW which uses a string of (wide 16-bit) Unicode characters. In a C program the include file windows.h has macros that automatically control and redefine these documented names to their Unicode/ANSI-specific ones. Thus the typical program will use only the documented names.
SetWindowText equ <SetWindowTextA> ; use ANSI in Win95You can if you like use a more elaborate technique to select which name you want as default.
interface_pointer -> function ( arglist )
The arguments are pushed in the reverse order just like SDK functions. The extra argument is the interface pointer which is pushed last. Then we use it to access the vtable and call the function. You will need to know the exact storage order of the function addresses. Assuming interface_pointer is in memory the instructions would be something like
; ... ; insert argument stacking here ; ... mov eax [interface_pointer] push eax ; push interface pointer mov ecx [eax] ; 1st dword of interface is vtable addr call [ecx+8] ; call the third function ; arguments already poppedString data in COM interfaces should always be in Unicode.
BYTE: char (signed)
WORD: short (signed) WORD (unsigned) ATOM (unsigned)
QWORD: double (floating point)
DWORD: int (signed) DWORD (unsigned) handles pointers and hopefully everything else that's not a struct or related to the previous types
push ebp mov ebp esp sub esp 4 ; example for allocating one local DWORDthen you can access the first argument as [ebp+8] the second argument as [ebp+12] and so on. The size of each argument is a multiple of four bytes (DWORD). Most arguments are integers handles or pointers: all of these are only one DWORD in size.
mov esp ebp pop ebpThe arguments can be popped off with the return instruction:
ret 16 ; example for four DWORD arguments