;
; =============================================================================================== 
; RqUtils.dll                         July 03nd, 2004                         by Jacques Philippe 
; MASM 8.2  Assembler Code                                             Version   1.0.0  Release 0
; ===============================================================================================
;
; --------------- Assember Header -----------------
    .386
    .model flat, stdcall
    option casemap :none   ; case sensitive

	include \masm32\include\windows.inc
    
	return MACRO arg
      mov eax, arg
      ret
    ENDM

	.code

; --------------- DLL's entry point --------------- 
LibMain			proc	hInstance:HINSTANCE,reason:dword,reserved1:dword
			.if 	reason == DLL_PROCESS_ATTACH
			.elseif reason == DLL_PROCESS_DETACH
			.elseif reason == DLL_THREAD_ATTACH
			.elseif reason == DLL_THREAD_DETACH
			.endif
			mov	eax,1
			ret
LibMain			endp
; --------------- DLL's Functions -----------------

; --------------- CallAddress
;     RQ Declaration and Prototype :
;
;       Declare Function CallAddress Lib "RqUtils.dll" Alias "CallAddress" _
;                                (AddressToCall As Long, ptrToArgumentsStructure As Long) As Long
;
;     The structure is an Array of DWORDs (Long or Integer or DWORD in RapidQ), the first
;     being the number of arguments in the structure, the other one are the arguments ordered
;     as in a RapidQ function. These arguments will be pushed on stack begining by the last
;     one to respect the ???C??? calling convention.
;       Array(0) = Number of argument
;       Array(1) = Argument_1
;       Array(2) = Argument_2
;       ...
;       Array(n) = Argument_n           '      No limit on n here
;
;     The function returns 0 if one or both of the two arguments passed are 0, in that case,
;     the AddressToCall is NOT called. If the two arguments are different from 0, the function
;     returns the value returned by the function called at AddressToCall.
;
CallAddress             Proc    address:dword,ptrStructArg:dword
                        push    esi
                        push    ebx
                        mov     esi, ptrStructArg           ; get poiter to struture
                        cmp     esi, 0						; avoid pointer = 0
                        jz      OneArgIsZero 
                        mov     eax, [esi]         			; number of args. Error was here : mov eax, [ptrStructArg] equal to mov eax, ptrStructArg
                        shl     eax, 2                      ; multipled by 4 to point the last arg in the array
						cmp 	eax, 0 						; if eax = 0, there are no arg to this function
						jz      OkNoArg
PushNextArg:
						mov     ebx, [esi + eax]            ; edi + eax points to the arg
                        push    ebx                         ; push the argument on the stack
                        sub     eax, 4						; point to the ext arg to push
                        jnz     PushNextArg					; loop to get next arg in the structure
OkNoArg:
						mov     eax, address				; get the address to Call_Execute
                        cmp     eax, 0  					; avoid calling 0 
                        jz      OneArgIsZero
						Call eax  							; call the address
                        jmp     All_Ok
OneArgIsZero:
                        mov     eax, 0                      ; returns 0 = ERROR
All_Ok:
                        pop     ebx
                        pop     esi
                        ret
CallAddress  endp
;
; --------------- CallPointer
;     RQ Declaration and Prototype :
;
;       Declare Function CallPointer Lib "RqUtils.dll" Alias "CallPointer" _
;                                (PointerToCall As Long, ptrToArgumentsStructure As Long) As Long
;
;     The structure is an Array of DWORDs (Long or Integer or DWORD in RapidQ), the first
;     being the number of arguments in the structure, the other one are the arguments ordered
;     as in a RapidQ function. These arguments will be pushed on stack begining by the last
;     one to respect the ???C??? calling convention.
;       Array(0) = Number of argument
;       Array(1) = Argument_1
;       Array(2) = Argument_2
;       ...
;       Array(n) = Argument_n           '      No limit on n here
;
;     The function returns 0 if one or both of the two arguments passed are 0, in that case,
;     the AddressToCall is NOT called. If the two arguments are different from 0, the function
;     returns the value returned by the function called at AddressToCall.
;
CallPointer             proc    pointer:dword,ptrStructArg:dword
                        push    esi
                        push    ebx
                        mov     esi, ptrStructArg			; get pointer to structure
                        cmp     esi, 0						; avoid pointer = 0
                        jz      OneArgIsZero
                        mov     eax, [esi]         			; number of args. Error was here : mov eax, [ptrStructArg] equal to mov eax, ptrStructArg
                        shl     eax, 2                      ; multipled by 4 to point the last arg in the array
                        cmp		eax, 0                      ; if eax = 0 there are no arg to this function
						jz		OkNoArg
PushNextArg:
						mov     ebx, [esi + eax]            ; edi + eax points to the arg
                        push    ebx                         ; push the argument on the stack
                        sub     eax, 4						; point to the ext arg to push				
                        jnz     PushNextArg					; loop to get next arg in the structure

OkNoArg:	
						mov     eax, pointer				; get the pointer to the address to Call/Run
                        cmp     eax, 0					    ; avoid 0
                        jz      OneArgIsZero
						mov     eax, [eax]					; get the Address to call/Run				
                        cmp     eax, 0						; avoid 0
                        jz      AddressToCallIsZero
						Call 	eax							; Call/Run the address
                        jmp     All_Ok
OneArgIsZero:
AddressToCallIsZero:
                        mov     eax, 0						; return 0 on ERROR
All_Ok:
                        pop     ebx
                        pop     esi
                        ret
CallPointer             endp

; --------------- ReadDWordAtAddress 
;		RQ Declaration :
;		Declare Function ReadDWordAtAddress Lib "RqUtils.dll" Alias "ReadDWordAtAddress" _
;                                (AddressToRead As Long) As Long
ReadDWordAtAddress		proc	address:dword
						mov 	eax, address
						mov		eax, [eax]
						ret
ReadDWordAtAddress		endp

; --------------- ReadDWordAtAddress 
;		RQ Declaration :
;		Declare Function ReadWordAtAddress Lib "RqUtils.dll" Alias "ReadWordAtAddress" _
;                                (AddressToRead As Long) As Long
ReadWordAtAddress		proc	address:dword
						push 	esi
						mov		esi, address
						mov		eax, 0
						mov		ax, [esi]
						pop 	esi
						ret
ReadWordAtAddress		endp

; --------------- ReadByteAtAddress 
;		RQ Declaration :
;		Declare Function ReadByteAtAddress Lib "RqUtils.dll" Alias "ReadByteAtAddress" _
;                                (AddressToRead As Long) As Long
ReadByteAtAddress		proc	address:dword
						push 	esi
						mov		esi, address
						mov		eax, 0
						mov		al, [esi]
						pop 	esi
						ret
ReadByteAtAddress		endp

; --------------- ReadDWordAtPointer 
;		RQ Declaration :
;		Declare Function ReadDWordAtPointer Lib "RqUtils.dll" Alias "ReadDWordAtPointer" _
;                                (PointerToRead As Long) As Long
ReadDWordAtPointer		proc	pointer:dword
						mov 	eax, pointer
						mov		eax, [eax]
						mov		eax, [eax]
						ret
ReadDWordAtPointer		endp

; --------------- ReadDWordAtPointer 
;		RQ Declaration :
;		Declare Function ReadWordAtPointer Lib "RqUtils.dll" Alias "ReadWordAtPointer" _
;                                (PointerToRead As Long) As Long
ReadWordAtPointer		proc	pointer:dword
						push 	esi
						mov		esi, pointer
						mov		esi, [esi]
						mov		eax, 0
						mov		ax, [esi]
						pop 	esi
						ret
ReadWordAtPointer		endp

; --------------- ReadByteAtPointer 
;		RQ Declaration :
;		Declare Function ReadByteAtPointer Lib "RqUtils.dll" Alias "ReadByteAtPointer" _
;                                (PointerToRead As Long) As Long
ReadByteAtPointer		proc	pointer:dword
						push 	esi
						mov		esi, pointer
						mov 	esi, [esi]
						mov		eax, 0
						mov		al, [esi]
						pop 	esi
						ret
ReadByteAtPointer		endp

; --------------- ReadByteAtPointer 
end LibMain
;
