MS Windows 32bit Application Programming Interface macros.
This library contains macros for some basic OS interactions: retrieving of command-line arguments, standard I/O, program termination, invocation of 32bit MS Windows Application Programming Interface.
Most macro names in this 32bit librarywinapi.htmare identical with macros from 64bit library winabi.htm and other API libraries. If you really need to include both libraries in one common source file, definitions of those macros should be forgotten before inclusion of the other library with%DROPMACRO GetArg,GetArgCount,StdInput,StdOutput,TerminateProgram
or with%DROPMACRO *
in order to prevent warning W2512 Overwriting macro "!1S" previously defined at !2@.
winapi HEAD INCLUDE1 winansi.htm ; Make sure that %WinANSI is assigned before WinAPI invocation.
%Param6 %SET EBP+56 %Param5 %SET EBP+52 %Param4 %SET EBP+48 %Param3 %SET EBP+44 %Param2 %SET EBP+40 %Param1 %SET EBP+36 %ReturnEAX %SET EBP+28 %ReturnECX %SET EBP+24 %ReturnEDX %SET EBP+20 %ReturnEBX %SET EBP+16 %ReturnESP %SET EBP+12 %ReturnEBP %SET EBP+08 %ReturnESI %SET EBP+04 %ReturnEDI %SET EBP+00
This macroinstruction invokes Function exported from 32bit MS Windows by [WindowsAPI].
The macro is similar to StdCall's Invoke with two subtle differences:
Lib=
.WinAPI functions require Direction Flag be zero on input and they do not change its value.
32bit Windows functions do not keep the original contents of flags, ECX, EDX,
but when this macro WinAPI is invoked with keyword Fastmode=No
(default), it preserves all registers except for EAX.
When you want to switch on the Fastmode for all WinAPI invokations, you don't have to appendLib= is the name of dynamic linked library (quoted or unquoted, always without path) which exports the invoked Function. This parameter may be empty or omitted,Fastmode=Yes
to every invokation ofWinAPI
if you set preprocessing %variable in the beginning of your program:%Fastmode %SETB On
.
kernel32.dll, or
IMPORT Function, LIB=user32.dll
, orFastmode=Yes
winabi.htm.
WinAPI %MACRO Function, Argument1, Argument2,,,,Lib=, Fastmode=%Fastmode, Lib= %IF %Fastmode ; Do not save scratch registers in fast mode. %ELSE PUSH ECX,EDX ; Save scratch registers when Fastmode=off. %ENDIF %ArgNr %SETA %# ; Number of ordinal operands. %WHILE %ArgNr > 1 PUSHD %*{%ArgNr} ; Push Function arguments on stack, begin with the last. %ArgNr %SETA %ArgNr-1 %ENDWHILE %suffix %SET ; Assume no A|W suffix (variable %suffix is empty). noreg %IF TYPE#%Function != 'R'; If the function is specified by name (not in GPR). fn %FOR %WinANSI ; Examine whether %Function is on the list %WinANSI. %IF "%fn" === "%Function" %suffix %SETC ('W' & (%^UNICODE)) + ('A' & ~(%^UNICODE)) %EXITFOR fn ; Break further examination when the %Function name was found. %ENDIF %ENDFOR fn IMPORT %Function%suffix, Lib=%Lib %ENDIF noreg CALL %Function%suffix %IF %Fastmode %ELSE POP EDX,ECX ; Restore scratch registers when Fastmode=off. %ENDIF %ENDMACRO WinAPI
Macro GetArg retrieves ArgNumber-th parameter provided on command line.
Parameters on the command line may be separated with unquoted
white spaces or commas. Single aphostrophe cannot be used as quote.
Macro returnes the executable name itself when ArgNumber is 0.
It is taken verbatim from the console window or, if launched
from Explorer, it may be expanded to a full pathname.
The returned argument is not zero terminated and it is not writable. Make a copy in local memory if you need to modify it. Quotes surrounding the argument are returned, too, but separating white spaces and commas are stripped off.
Value of EUROASM UNICODE=
option specifies whether the returned string will be ANSI or WIDE.
GetArg %MACRO ArgNumber, Unicode=%^UNICODE PUSHD %ArgNumber AorW %IF %Unicode CALL GetArgWin32W@RT GetArgWin32W@RT:: PROC1 ; Stdcalled with %Param1=ArgNumber. PUSHAD MOV EBP,ESP CMPD [%Param1],-1 ADCD [%Param1],0 IMPORT GetCommandLineW CALL GetCommandLineW MOV ESI,EAX MOV EDI,EAX MOV EBX,EAX XOR EAX,EAX CMP EAX,ESI STC JZ .Err: ; If GetCommandLine returned FALSE. XOR ECX,ECX DEC ECX REPNE SCASW LEA EDX,[EDI-2] ; EDX points to the end of command line. SUB ECX,ECX ; ECX will keep the ordinal number of parsed cmdline argument. .10:MOV EDI,ESI ; EDI is brutto end of current argument. CMP ECX,[%Param1] ; %Par1 is the number of requested argument. JAE .50: .20:CMP ESI,EDX JNB .50: ; No more arguments available. LODSW CMP AX,' ' JBE .20: DEC ESI,ESI INC ECX MOV EBX,ESI ; EBX is brutto beginning of ECX-th argument. MOV EDI,ESI .30:CMP ESI,EDX JNB .10: LODSW CMP AX,'"' JNE .40: .35:CMP ESI,EDX CMC JC .90: ; Syntax error - unpaired quotes. LODSW CMP AX,'"' JNE .35: JMP .30: .40:CMP AX,',' JE .10: CMP AX,' ' JA .30: .45:CMP ESI,EDX JNB .10: LODSW CMP AX,' ' JNA .45: CMP AX,',' JE .10: DEC ESI,ESI JMP .10: .50:CMPD [%Param1],-1 ; Test if invoked from GetArgCount with ArgNr= -1. JNE .60: DEC ECX ; Omit the 0-th argument (the executable itself). MOV [%ReturnECX],ECX JMP .80: .60:MOVD [%ReturnECX],0 CMP ECX,[%Param1] STC JNE .90: MOV ESI,EBX ; Brutto ECX-th argument found at ESI..EDI. Trim spaces and commas. .65:CMP ESI,EDI JNB .75: LODSW CMP AX,' ' JBE .65: CMP AX,',' JE .65: DEC ESI,ESI .70:DEC EDI,EDI MOV AX,[EDI] CMP AX,' ' JBE .70: CMP AX,',' JE .70: INC EDI,EDI ; Netto argument is now at ESI..EDI. .75 MOV [%ReturnESI],ESI SUB EDI,ESI JC .80: MOV [%ReturnECX],EDI .80:CLC .90:POPAD RET 4 ENDP1 GetArgWin32W@RT %ELSE AorW CALL GetArgWin32A@RT GetArgWin32A@RT:: PROC1 ; Stdcalled with %Param1=ArgNumber. PUSHAD MOV EBP,ESP CMPD [%Param1],-1 ADCD [%Param1],0 IMPORT GetCommandLineA CALL GetCommandLineA MOV ESI,EAX MOV EDI,EAX MOV EBX,EAX XOR EAX,EAX CMP EAX,ESI STC JZ .90: ; If GetCommandLine returned FALSE. XOR ECX,ECX DEC ECX REPNE SCASB LEA EDX,[EDI-1] ; EDX points to the end of command line. SUB ECX,ECX ; ECX will keep the ordinal number of parsed cmdline argument. .10:MOV EDI,ESI ; EDI is brutto end of current argument. CMP ECX,[%Param1] ; %Par1 is the number of requested argument. JAE .50: .20:CMP ESI,EDX JNB .50: ; No more arguments available. LODSB CMP AL,' ' JBE .20: DEC ESI INC ECX MOV EBX,ESI ; EBX is brutto beginning of ECX-th argument. MOV EDI,ESI .30:CMP ESI,EDX JNB .10: LODSB CMP AL,'"' JNE .40: .35:CMP ESI,EDX CMC JC .90: ; Syntax error - unpaired quotes. LODSB CMP AL,'"' JNE .35: JMP .30: .40:CMP AL,',' JE .10: CMP AL,' ' JA .30: .45:CMP ESI,EDX JNB .10: LODSB CMP AL,' ' JNA .45: CMP AL,',' JE .10: DEC ESI JMP .10: .50:CMPD [%Param1],-1 ; Test if invoked from GetArgCount with ArgNr= -1. JNE .60: DEC ECX ; Omit the 0-th argument (the executable itself). MOV [%ReturnECX],ECX JMP .80: .60:MOVD [%ReturnECX],0 CMP ECX,[%Param1] STC JNE .90: MOV ESI,EBX ; Brutto ECX-th argument found at ESI..EDI. Trim spaces and commas. .65:CMP ESI,EDI JNB .75: LODSB CMP AL,' ' JBE .65: CMP AL,',' JE .65: DEC ESI .70:DEC EDI MOV AL,[EDI] CMP AL,' ' JBE .70: CMP AL,',' JE .70: INC EDI ; Netto argument is now at ESI..EDI. .75 MOV [%ReturnESI],ESI SUB EDI,ESI JC .80: MOV [%ReturnECX],EDI .80:CLC .90:POPAD RET 4 ENDP1 GetArgWin32A@RT:: %ENDIF AorW %ENDMACRO GetArg
GetArgCount %MACRO Unicode=%^UNICODE GetArg -1, Unicode=%Unicode %ENDMACRO GetArgCount
Macro StdOutput writes one or more concatenated strings to the standard output or to other equipment specified with the Handle identifier.
Strings are either zero-terminated, or the keyword Size= must specify its size in bytes. The terminating NUL character is never written.
If keyword Eol=Yes, macro writes CR+LF after all strings.
The output device is by default treated as a file (when Console=No
)
Such output is redirectable, but it writes WIDE string as is;
in OEM console are the UTF-16 encoded characters displayed as interlaced.
Output produced with Console=Yes
cannot be redirected by command-line operators
|, > or >but it accepts WIDE Unicode strings and displays
the text in TrueType console properly, including non-English characters.
Unicode= %^UNICODE is boolean specification whether the Strings are in WIDE (UTF-16) encoding. By default (if omitted) it copies the global optionOutput of WriteFile (default) is redirectable, but it writes WIDE string as is; in OEM console are the UTF-16 encoded characters displayed as interlaced.
Output produced by WriteConsole (when Console=Yes) cannot be redirected by command-line operator > but it accepts WIDE Unicode strings and displays the text in TrueType console properly, including non-English characters.When you want to use the Console (nondefault) mode in all StdOutput and StdInput invokations, you don't have to append
,Console=Yes
to every invokation ofStdOutput
andStdInput
if you set preprocessing %variable in the beginning of your program:%StdConsole %SETB Yes
.
EUROASM Unicode=
.StdOutput %MACRO String1,String2,,,Size=-1, Handle=-11, Eol=No, Console=%StdConsole, Unicode=%^UNICODE C %IF %Console U %IF %Unicode %StdOutputFlags %SETA 2 + 1 %ELSE U %StdOutputFlags %SETA 2 + 0 %ENDIF U %ELSE C W %IF %Unicode %StdOutputFlags %SETA 0 + 1 %ELSE W %StdOutputFlags %SETA 0 + 0 %ENDIF W %ENDIF C ArgNr %FOR 1..%#, STEP=1 ; Call the runtime for each String. PUSHD %StdOutputFlags, %1, %Size, %Handle CALL StdOutputWin32@RT %SHIFT 1 ; The next string to output. %ENDFOR ArgNr Eol %IF %Eol U %IF %Unicode PUSHD %StdOutputFlags+4, 0, 4, %Handle %ELSE U PUSHD %StdOutputFlags+4, 0, 2, %Handle %ENDIF U CALL StdOutputWin32@RT %ENDIF Eol StdOutputWin32@RT:: PROC1 ; Invoked in stdcall convention with parameters Handle,Size,Addr,Flags. PUSHAD MOV EBP,ESP SUB ESP,4+4 ; Room for Eol and address of characters-written. MOV [ESP],ESP WinAPI GetStdHandle,[%Param1],Fastmode=Yes ; %Param1=Handle. MOV EBX,EAX INC EAX STC JZ .90: ; Abort with CF when INVALID_HANDLE_VALUE (-1). MOV ECX,[%Param2] ; String maximal size. MOV EDI,[%Param3] ; String pointer. MOV EAX,[%Param4] ; Status flags. Bits 0=Unicode, 1=Console, 2=Eol. IMPORT WriteFile,WriteConsoleA,WriteConsoleW MOV EDX,WriteFile TEST AL,2 ; Select File or Console mode. JZ .10: MOV EDX,WriteConsoleA TEST AL,1 JZ .10: MOV EDX,WriteConsoleW .10:TEST AL,4 JZ .20: LEA EDI,[EBP-4] ; EOL is requested instead of string. MOVD [EDI],0x000A_000D ; WIDE EOL. TEST AL,1 JNZ .20: MOVW [EDI],0x0A0D ; ANSI EOL. .20:XOR EAX,EAX ; EDI,ECX is string to write MOV ESI,EDI TESTB [%Param4],1 ; ASCII | WIDE. JZ .40: SHR ECX,1 ; Convert size to length in characters. REPNE SCASW ; Find the WIDE zero terminator. JNE .50: DEC EDI,EDI ; Omit the zero terminator. JMP .50: .40:REPNE SCASB ; Find the ANSI zero terminator. JNE .50: DEC EDI .50:SUB EDI,ESI ; EDI is now string size in bytes. MOV EAX,[%Param4] ; Status flags. AND AL,3 XOR AL,3 JNZ .60: SHR EDI,1 ; EDI is now string size in WIDE characters for Console. .60:WinAPI EDX,EBX,ESI,EDI,[EBP-8],0,Fastmode=on CMP [EBP-8],EDI ; Set CF if not all characters were written. .90:MOV ESP,EBP POPAD RET 4*4 ENDP1 StdOutputWin32@RT:: %ENDMACRO StdOutput
Macro StdInput reads a line of text terminated with CR (Enter) from standard input device (usually the keyboard) specified by the Handle identifier.
The input device is by default treated as a file (when Console=No
). Such input is redirectable by command-line operators
< or | but it treats input characters as bytes. Console mode
uses console input buffer (no redirection works here) but it interprets WIDE characters properly.
When you want to use the Console (nondefault) mode in all StdOutput and StdInput invokations, you don't have to appendUnicode=%^UNICODE is boolean specification whether the characters read from console should be in WIDE (UTF-16) encoding.,Console=Yes
to every invokation ofStdOutput
andStdInput
if you set preprocessing %variable in the beginning of your program:%StdConsole %SETB Yes
.
StdInput %MACRO Buffer, Size=, Handle=-10, Console=%StdConsole, Unicode=%^UNICODE %IF "%Size" === "" PUSHD %Handle, SIZE# %Buffer, %Buffer %ELSE PUSHD %Handle, %Size, %Buffer %ENDIF XOR ECX,ECX ; ECX=0 when characters are 8bit ANSI. %IF %Console %IF %Unicode ; ReadConsole WIDE variant. IMPORT ReadConsoleW PUSHD ReadConsoleW INC ECX ; ECX=1 when characters are 16bit WIDE. %ELSE ; ReadConsole ANSI variant. IMPORT ReadConsoleA PUSHD ReadConsoleA %ENDIF %ELSE ; ReadFile variant. Ignores Unicode. IMPORT ReadFile PUSHD ReadFile %ENDIF ; %StdInputRT is now the name of runtime PROC1. CALL StdInputWin32@RT StdInputWin32@RT:: PROC1 ; StdCalled with parameters Function,Addr,Size,Handle,ECX. PUSHAD MOV EBP,ESP WinAPI GetStdHandle,[%Param4],Fastmode=on ; Get input handle. MOV ECX,EAX INC ECX STC JZ .90: ; Abort with CF when EAX=-1 (INVALID_HANDLE_VALUE). MOV ESI,[%Param1] ; Function. MOV EBX,[%Param3] ; Size. MOV ECX,[%ReturnECX] ; 0=ANSI or 1=WIDE. LEA EDX,[%ReturnECX] ; Address of number of characters read. MOV EDI,ECX ; Save 0 or 1 to EDI. SHR EBX,CL ; Convert Size in bytes to length in characters. WinAPI ESI,EAX,[%Param2],EBX,EDX,0,Fastmode=on XCHG ECX,EDI ; Restore 0 or 1 to CL. SHLD [%ReturnECX],CL ; Convert read length in characters to bytes. SUB EAX,1 ; Return CF if WinAPI returned FALSE (EAX=0). .90:POPAD RET 4*4 ENDPROC1 StdInputWin32@RT:: %ENDMACRO StdInput
Errorlevel=
, this value may also be specified as an ordinal operand.
TerminateProgram %MACRO Errorlevel=0 %IF %# = 1 ; If Errorlevel is provided as an ordinal. PUSHD %1 %ELSE PUSHD %Errorlevel ; If Errorlevel is provided as a keyword. %ENDIF IMPORT ExitProcess, Lib="kernel32.dll" CALL ExitProcess %ENDMACRO TerminateProgram
ENDHEAD winapi