'----------------------------------------------------------------------------
'Generic function for API function calling
'Parameters:
' lError : return code error
' 2 = Error calling function
' 3 = Error loading library
'----------------------------------------------------------------------------
Function DllApi_Call( ByVal lptr_tFunction As tFunction Ptr, ByRef lResultExt As Ext) As Quad
Local ApiCall_pCount As Long
Local hLib As Long
Local hProc As Long
Local RetVal As Long
Local ApiCall_PushParam As Long
Local ApiCall_PushParam_Single As Single
Local glApiLib As tAPILIB
Local ptr_lApiLib As tAPILIB Ptr
Local ApiCall_WhereFound As Long
'Local HowManyBytesPushed As Long
Local savedSP As Long
'---Save current stack pointer
! mov savedSP,esp
'---
'---Get the lib and proc address from function just in case they were already defined
hProc = @lptr_tFunction.hProc
If @lptr_tFunction.IsAPI Then
hLib = @lptr_tFunction.hLib
If hLib = 0& Then
'---Search if library is already loaded
ptr_lApiLib = HashTable_KeyFind(gScript.APILIB_Dict, @lptr_tFunction.LibName & "")
'---If not, try to load the library
If ptr_lApiLib Then
'---If already loaded, just get its handle
hLib = @ptr_lApiLib.LibHandle
Else
hLib = thinBasic_LoadLibrary(@lptr_tFunction.LibName, ApiCall_WhereFound)
If hLib Then
glApiLib.LibName = @lptr_tFunction.LibName
glApiLib.LibHandle = hLib
APILIB_Add(VarPtr(glApiLib))
End If
End If
If hLib Then
@lptr_tFunction.hLib = hLib
Else
'---
'Error loading library
'---
RunTimeError(%ERR__API_LIB_NOT_FOUND, "LibName: " & Trim$(@lptr_tFunction.LibName))
gdwStatus = %OS_ERROR_LOADLIBRARY
Exit Function
End If
End If
'---Now check hProc
If hProc = 0& Then
hProc = GetProcAddress(hLib, @lptr_tFunction.AliasName )
If hProc Then
@lptr_tFunction.hProc = hProc
Else
'---
'Error calling function
'---
RunTimeError(%ERR__API_FUNCTION_NOT_FOUND_IN_LIB, "LibName: " & Trim$(@lptr_tFunction.LibName) & " - Alias: " & Trim$(@lptr_tFunction.AliasName))
gdwStatus = %OS_ERROR_CALLFUNCTION
Exit Function
End If
End If
End If
'---PUSH parameters reverse order
For ApiCall_pCount = @lptr_tFunction.NumberOfParams To 1& Step -1&
Select Case Long @lptr_tFunction.params(ApiCall_pCount).ParamMainType
Case %ArrayType_IsNumber
If @lptr_tFunction.params(ApiCall_pCount).ParamPassBy = %PARAM_ByVal Then
Select Case Long @lptr_tFunction.params(ApiCall_pCount).ParamSubType
Case %ArrayType_Long
ApiCall_PushParam = @lptr_tFunction.params(ApiCall_pCount).DataValue.lLong
! push ApiCall_PushParam
'HowManyBytesPushed += 4
Case %ArrayType_DWord
ApiCall_PushParam = @lptr_tFunction.params(ApiCall_pCount).DataValue.lDWord
! push ApiCall_PushParam
'HowManyBytesPushed += 4
Case %ArrayType_Ext
ApiCall_PushParam = VarPtr(@lptr_tFunction.params(ApiCall_pCount).DataValue.lExt)
!mov eax,ApiCall_PushParam ;'point EAX To the 8 Byte variable
!mov edx,[eax+8] ;'Get latest 4 bytes
!push edx ;'push them
!mov edx,[eax+4] ;'Get mid 4 bytes
!push edx ;'push them
!mov edx,[eax] ;'Get the 1st 4 bytes
!push edx ;'push them
'HowManyBytesPushed += 12
Case %ArrayType_Double
ApiCall_PushParam = VarPtr(@lptr_tFunction.params(ApiCall_pCount).DataValue.lDouble)
!mov eax,ApiCall_PushParam ;'point EAX To the 8 Byte variable
!mov edx,[eax+4] ;'Get latest 4 bytes
!push edx ;'push them
!mov edx,[eax] ;'Get the 1st 4 bytes
!push edx ;'push them
'HowManyBytesPushed += 8
Case %ArrayType_Single
ApiCall_PushParam_Single = @lptr_tFunction.params(ApiCall_pCount).DataValue.lSingle
! push ApiCall_PushParam_Single
'HowManyBytesPushed += 4
Case %ArrayType_Byte
ApiCall_PushParam = @lptr_tFunction.params(ApiCall_pCount).DataValue.lByte
! push ApiCall_PushParam
'HowManyBytesPushed += 4
Case %ArrayType_Word
ApiCall_PushParam = @lptr_tFunction.params(ApiCall_pCount).DataValue.lWord
! push ApiCall_PushParam
'HowManyBytesPushed += 4
Case %ArrayType_Integer
ApiCall_PushParam = @lptr_tFunction.params(ApiCall_pCount).DataValue.lInteger
! push ApiCall_PushParam
'HowManyBytesPushed += 4
Case %ArrayType_Quad
ApiCall_PushParam = VarPtr(@lptr_tFunction.params(ApiCall_pCount).DataValue.lQuad)
!mov eax,ApiCall_PushParam ;'point EAX To the 8 Byte variable
!mov edx,[eax+4] ;'Get latest 4 bytes
!push edx ;'push them
!mov edx,[eax] ;'Get the 1st 4 bytes
!push edx ;'push them
'HowManyBytesPushed += 8
End Select
Else '---BYREF
ApiCall_PushParam = @lptr_tFunction.params(ApiCall_pCount).DataValue.GenericPtr
! push ApiCall_PushParam
'HowManyBytesPushed += 4
End If
Case %ArrayType_IsString, %ArrayType_IsGUID
'IF @lptr_tFunction.params(ApiCall_pCount).ParamPassBy = %PARAM_ByRef THEN
ApiCall_PushParam = @lptr_tFunction.params(ApiCall_pCount).DataValue.GenericPtr
! push ApiCall_PushParam
'ELSE
' SELECT CASE LONG @lptr_tFunction.params(ApiCall_pCount).ParamSubType
' CASE %ArrayType_String, %ArrayType_Asciiz
' ApiCall_PushParam = @lptr_tFunction.params(ApiCall_pCount).DataValue.lString
' ! push ApiCall_PushParam
' END SELECT
'END IF
'HowManyBytesPushed += 4
Case %ArrayType_UDT
ApiCall_PushParam = @lptr_tFunction.params(ApiCall_pCount).DataValue.GenericPtr
! push ApiCall_PushParam
'HowManyBytesPushed += 4
Case %ArrayType_Variant
If @lptr_tFunction.params(ApiCall_pCount).ParamPassBy = %PARAM_ByRef Then
ApiCall_PushParam = @lptr_tFunction.params(ApiCall_pCount).DataValue.GenericPtr
! push ApiCall_PushParam
'HowManyBytesPushed += 4
Else
'---ORIGINAL
' '---Push 16 bytes into the stack in reverse order
' ApiCall_PushParam = @lptr_tFunction.params(ApiCall_pCount).DataValue.GenericPtr
' !mov eax,ApiCall_PushParam ;point EAX To the 8 Byte variable
' !mov edx,[eax+16] ;Get latest 4 bytes
' !push edx ;push them
' !mov edx,[eax+12] ;Get latest 4 bytes
' !push edx ;push them
' !mov edx,[eax+8] ;Get latest 4 bytes
' !push edx ;push them
' !mov edx,[eax+4] ;Get mid 4 bytes
' !push edx ;push them
' !mov edx,[eax] ;Get the 1st 4 bytes
' !push edx ;push them
'---NEW
'---Push 16 bytes into the stack in reverse order
ApiCall_PushParam = @lptr_tFunction.params(ApiCall_pCount).DataValue.GenericPtr
!mov eax,ApiCall_PushParam ;'point EAX To the 16 Byte variable
!mov edx,[eax+12] ;'Get latest 4 bytes
!push edx ;'push them
!mov edx,[eax+8] ;'Get latest 4 bytes
!push edx ;'push them
!mov edx,[eax+4] ;'Get mid 4 bytes
!push edx ;'push them
!mov edx,[eax] ;'Get the 1st 4 bytes
!push edx ;'push them
'---
'HowManyBytesPushed += 16
End If
End Select
Next
'---
'Call the function and get return code
If @lptr_tFunction.ReturnMainType = %ArrayType_IsNumber Then
Select Case Long @lptr_tFunction.ReturnSubType
Case %ArrayType_Ext
Static ve As Extended
'---
'!Xor eax, eax
!Call hProc
'! fstp Qword Ptr ve
! fstp ve
lResultExt = ve
Case _
%ArrayType_Long , _
%ArrayType_DWord , _
%ArrayType_Word , _
%ArrayType_Integer, _
%ArrayType_Byte
'---
!Xor eax, eax
!Call hProc
!mov RetVal, eax
lResultExt = RetVal
Case %ArrayType_Double
Static vd As Double
'---
'!Xor eax, eax
!Call hProc
! fstp Qword Ptr vd
lResultExt = vd
Case %ArrayType_Single
Static vs As Single
'---
'!Xor eax, eax
!Call hProc
! fstp Dword Ptr vs
lResultExt = vs
Case %ArrayType_Quad
Static vq As Quad
' '---
' '!Xor eax, eax
' !Call hProc
' '! fstp Qword Ptr ve
' ! fistp vq
' lResultExt = vq
'---
'!Xor eax, eax
!Call hProc
! PUSH EBX
! LEA EBX, vq
! MOV [EBX], EAX
! MOV [EBX + 4], EDX
! POP EBX
lResultExt = vq
End Select
ElseIf @lptr_tFunction.ReturnMainType = %ArrayType_IsString Then
'---
!Xor eax, eax
!Call hProc
!mov RetVal, eax
lResultExt = RetVal
End If
'---CDECL
If @lptr_tFunction.CallingMode = %PA__CDECL Then
'---Restore previous stack position
! mov esp,savedSP
'If HowManyBytesPushed Then
' !Add esp, HowManyBytesPushed
'End If
End If
Function = RetVal
End Function
Bookmarks