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,TerminateProgramor 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=Yesto every invokation ofWinAPIif 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=Yesto every invokation ofStdOutputandStdInputif 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=Yesto every invokation ofStdOutputandStdInputif 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