Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

CallDll: Generic function to call external DLL procedures at RunTime

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • CallDll: Generic function to call external DLL procedures at RunTime

    Code:
    #If 0
      =============================================================================
      File name   : CallDll.INC
      Author      : Eros Olmi
      Version     : 1.0.0
      Description : Generic function to call external DLL procedures at RunTime
                    No DLL static link needed
      Web site    : [url="http://www.autoapfp.com"]http://www.autoapfp.com[/url] 
      =============================================================================
      COPYRIGHT AND PERMISSION NOTICE
      =============================================================================
      Copyright (c) 2004 - 2004, Eros Olmi, <[email protected]>
       
      All rights reserved.
       
      Permission to use and copy this software for any non commercial purpose
      with or without fee is hereby granted, provided that the above copyright
      notice and this permission notice appear in all copies.
    
      For commercial purpose, contact the copyright holder.
       
      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
      IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
      DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
      OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
      USE OR OTHER DEALINGS IN THE SOFTWARE.
      =============================================================================
      Target:
         - create a generic function able to call API DLL procedures at RunTime
         - avoid static linking of DLL when possible
      =============================================================================
      Edit History:       (Legend: +Add -Fix *Modify #Note)
      -----------------------------------------------------------------------------
      Date (YMD) Version  Comments
      -----------------------------------------------------------------------------
      2004.03.04 01.00.00 # First beta version
      =============================================================================
    #EndIf
    
      '----------------------------------------------------------------------------
      FUNCTION MemAlloc( BYVAL nSize AS DWORD ) AS LONG
      '----------------------------------------------------------------------------
        IF nSize = 0 THEN EXIT FUNCTION
        FUNCTION = HeapAlloc( GetProcessHeap(), %HEAP_ZERO_MEMORY, MAX( 16, nSize + 1 ) )
      END FUNCTION
    
      '----------------------------------------------------------------------------
      FUNCTION MemAllocByVal( BYVAL sData AS STRING ) AS LONG
      '----------------------------------------------------------------------------
        DIM pData AS DWORD
        pData = MemAlloc( LEN( sData ) )
        IF pData > 0 THEN POKE$ pData, sData
        FUNCTION = pData
      END FUNCTION
    
      '----------------------------------------------------------------------------
      FUNCTION MemFree( BYVAL pMem AS LONG ) AS LONG
      '----------------------------------------------------------------------------
        IF pMem = 0 THEN EXIT FUNCTION
        IF HeapSize( GetProcessHeap(), 0, BYVAL pMem ) > 0 THEN
          HeapFree GetProcessHeap(), 0, BYVAL pMem
          FUNCTION = 1
        END IF
      END FUNCTION
    
      '----------------------------------------------------------------------------
      FUNCTION MemSize( BYVAL pMem AS LONG ) AS DWORD
      '----------------------------------------------------------------------------
        DIM nSize   AS DWORD
        IF pMem = 0 THEN EXIT FUNCTION
        nSize = HeapSize( GetProcessHeap(), 0, BYVAL pMem )
        IF nSize = 0 OR nSize = %MAXDWORD THEN EXIT FUNCTION
        FUNCTION = nSize
      END FUNCTION
    
      '----------------------------------------------------------------------------
      FUNCTION MemReAlloc( BYVAL pMem AS LONG, BYVAL nNewSize AS DWORD ) AS LONG
      '----------------------------------------------------------------------------
        DIM nSize   AS DWORD
        DIM pNewMem AS LONG
        IF nNewSize = 0 THEN EXIT FUNCTION
        IF pMem THEN
            nSize = MemSize( pMem )
            IF nSize = 0 THEN EXIT FUNCTION
            pNewMem = MemAlloc( nNewSize )
            MoveMemory BYVAL pNewMem, BYVAL pMem, MIN( nNewSize, nSize )
            MemFree pMem
        ELSE
            pNewMem = MemAlloc( nNewSize )
        END IF
        FUNCTION = pNewMem
      END FUNCTION
    
      '----------------------------------------------------------------------------
      'Equates for every data type defined
      '----------------------------------------------------------------------------
      %ParamType_Byte    =  1
      %ParamType_Integer =  2
      %ParamType_Word    =  3
      %ParamType_Long    =  4
      %ParamType_DWord   =  5
      %ParamType_String  =  6
      %ParamType_Double  =  7
      %ParamType_Quad    =  8
      %ParamType_Ext     =  9
      %ParamType_Asciiz  = 10
      %ParamType_UDT     = 11
    
      '----------------------------------------------------------------------------
      'Possible methods for passing data
      '----------------------------------------------------------------------------
      %ByType_ByVal      = 1
      %ByType_ByRef      = 2
      %ByType_ByCopy     = 3
    
      '----------------------------------------------------------------------------
      'Used to store all different data type value
      '----------------------------------------------------------------------------
      Type ParamValue                            ' --|
        lByte    As Byte                         '   |
        lInteger As Integer                      '   |
        lWord    As Word                         '   |
        lLong    As Long                         '   |--------|
        lDWord   As Dword                        '   |        |
        lString  As Long                         '   |        |
        lDouble  As Double                       '   |        |
        lQuad    AS QUAD                         '   |        |
        lExt     AS EXT                          '   |        |
        lUDT     AS DWORD                        ' --|        |
      END TYPE                                   '            |
    
      '-------------------------------------------------------|--------------------
      'Used to store function parameters                      |
      '-------------------------------------------------------|--------------------
      TYPE Parameter                             '            |
        Used         AS LONG                     '            |
        ByType       AS LONG                     '            |
        DataType     AS LONG                     '            |
        DataValue    AS ParamValue               '  <<--------|
      END TYPE
      
    
      '----------------------------------------------------------------------------
      'Generic function for API function calling
      'Parameters:
      '  sLibMain  : name of the DLL file containing sProcName
      '  sProcName : name of the function to call
      '  sParams() : Array of parameters. Must be in the following format: BYTYPE DATATYPE THEDATA
      '              Example:  Param(0) = "BYVAL LONG 123534"
      '  lError    : return code error
      '              1 = Error calling function
      '              2 = Error loading library
      '----------------------------------------------------------------------------
       
      '----------------------------------------------------------------------------
      FUNCTION CallDll(BYVAL sLibName AS STRING, BYVAL sProcName AS STRING, sParams() AS STRING, lError AS LONG) AS LONG
      '----------------------------------------------------------------------------
        Dim hLib          As Long
        Dim hProc         As Long
        Dim nParams       As Long
        Dim sParam        As String
        Dim pCount        As Long
        Dim RetVal        As Long
        Dim PushParams()  As Parameter
        Dim PushParam     As Long     
        Dim sNumericType  As String
        
        Local lb          As Long   'lbound of PushParams()
        Local ub          As Long   'ubound of PushParams()
        LOCAL TheData     AS STRING
        
        LOCAL sByType     AS STRING
        LOCAL lByTypePresent  AS LONG
        LOCAL sDataType   AS STRING
                                       
        LOCAL lPos        AS LONG
                                       
        'Try to load the library
        hLib = LoadLibrary( ByCopy sLibName )
        IF hLib <> %NULL THEN
      
          'Try to returns the address of the DLL function.
          hProc = GetProcAddress(hLib, BYCOPY sProcName )
          
          lb = LBOUND(sParams)
          ub = UBOUND(sParams)
          
          REDIM PushParams(lb:ub) AS Parameter
          REDIM DynamicStrings(lb:ub) AS STRING
                              
                              
          IF hProc <> %NULL THEN
    
            '---
            'Parse the passed parameters
            '---
            FOR pCount = lb TO ub
                
              '---
              'Get the ByType identification
              '---
              sByType = UCASE$(TRIM$(PARSE$(sParams(pCount), " ", 1)))    
              IF LEFT$(sByType, 2) = "BY" then
                lByTypePresent = %TRUE  
                SELECT CASE sByType    
                  CASE "BYVAL" : PushParams(pCount).ByType = %ByType_ByVal
                  CASE "BYREF" : PushParams(pCount).ByType = %ByType_ByRef
                  CASE "BYCOPY": PushParams(pCount).ByType = %ByType_ByCopy
                END SELECT                               
              ELSE               
                lByTypePresent = %FALSE  
                PushParams(pCount).ByType = %ByType_ByRef
              END IF              
          
              '---
              'Get the Data itself
              'The data is immediatelly after the second blank space
              '---
              lPos = INSTR(1, sParams(pCount), " ")
              IF lByTypePresent = %TRUE THEN
                IF lPos THEN 
                   lPos = INSTR(lPos + 1, sParams(pCount), " ")
                END IF                    
              END IF
              TheData = MID$(sParams(pCount), lPos + 1)
                  
                  
              '---
              'Get the Data Type. It can be first or second parameter.
              'It depends if ByType has been specified
              '---
              sDataType = UCASE$(TRIM$(PARSE$(sParams(pCount), " ", IIF&(lByTypePresent = %TRUE, 2, 1))))    
              SELECT CASE sDataType    
                CASE "STRING"
                  '---
                  'If the string was passed ByRef then the address to the 
                  'string descriptor was passed. Therefore, treat this
                  'information like a LONG value.
                  '---
                  IF PushParams(pCount).ByType = %ByType_ByRef THEN
                    PushParams(pCount).DataType           = %ParamType_Long
                    PushParams(pCount).DataValue.lLong    = CLNG(VAL(TheData))
                  ELSE
                    'ByVal/ByCopy
                    DynamicStrings(pCount) = TheData
                    PushParams(pCount).DataType = %ParamType_String
                    PushParams(pCount).DataValue.lString = STRPTR(DynamicStrings(pCount))   
                  END IF
                     
                CASE "ASCIIZ"
                  PushParams(pCount).DataType          = %ParamType_Asciiz
                  PushParams(pCount).DataValue.lString = MemAllocByVal(TheData)
                
                CASE "BYTE"
                  PushParams(pCount).DataType           = %ParamType_Byte
                  PushParams(pCount).DataValue.lByte    = CBYT(VAL(TheData))
          
                CASE "WORD"
                  PushParams(pCount).DataType           = %ParamType_Word
                  PushParams(pCount).DataValue.lWord    = CWRD(VAL(TheData))
          
                CASE "DWORD"
                  PushParams(pCount).DataType           = %ParamType_DWord
                  PushParams(pCount).DataValue.lDWord   = CDWD(VAL(TheData))
    
                CASE "UDT"
                  PushParams(pCount).DataType           = %ParamType_UDT
                  PushParams(pCount).DataValue.lUDT     = CDWD(VAL(TheData))
    
                CASE "INTEGER"
                  PushParams(pCount).DataType           = %ParamType_Integer
                  PushParams(pCount).DataValue.lInteger = CINT(VAL(TheData))
                
                CASE "LONG"
                  PushParams(pCount).DataType           = %ParamType_Long
                  PushParams(pCount).DataValue.lLong    = CLNG(VAL(TheData))
                
                CASE "QUAD"
                  PushParams(pCount).DataType           = %ParamType_Quad
                  PushParams(pCount).DataValue.lQuad    = CQUD(VAL(TheData))
                
                CASE "DOUBLE"
                  PushParams(pCount).DataType           = %ParamType_Double
                  PushParams(pCount).DataValue.lDouble  = CDBL(VAL(TheData))
    
                CASE "EXT"
                  PushParams(pCount).DataType           = %ParamType_Ext
                  PushParams(pCount).DataValue.lExt     = CEXT(VAL(TheData))
    
              END SELECT
              
            Next
      
            '---
            'Push parameters into the stack in reverse order
            '---
            FOR pCount = ub TO lb STEP -1
              
              SELECT CASE PushParams(pCount).DataType
    
                CASE %ParamType_String, %ParamType_Asciiz
                  PushParam = PushParams(pCount).DataValue.lString
                  ! push PushParam
    
                CASE %ParamType_Byte  
                  PushParam = PushParams(pCount).DataValue.lByte
                  ! push PushParam  
    
                CASE %ParamType_Word
                  PushParam = PushParams(pCount).DataValue.lWord
                  ! push PushParam  
    
                CASE %ParamType_DWord  
                  PushParam = PushParams(pCount).DataValue.lDWord
                  ! push PushParam  
    
                CASE %ParamType_UDT
                  PushParam = PushParams(pCount).DataValue.lUDT
                  ! push PushParam  
    
                CASE %ParamType_Integer
                  PushParam = PushParams(pCount).DataValue.lInteger
                  ! push PushParam  
    
                CASE %ParamType_Long
                  PushParam = PushParams(pCount).DataValue.lLong
                  ! push PushParam  
                  
                CASE %ParamType_Quad
                  SELECT CASE PushParams(pCount).ByType
                    CASE %ByType_ByRef, %ByType_ByCopy
                      PushParam = VARPTR(PushParams(pCount).DataValue.lQuad)
                      ! push PushParam
    
                    CASE %ByType_ByVal
                      PushParam = VarPtr(PushParams(pCount).DataValue.lQuad)
                      !mov eax,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
                  END SELECT
    
                CASE %ParamType_Ext
                  SELECT CASE PushParams(pCount).ByType
                    CASE %ByType_ByRef, %ByType_ByCopy
                      PushParam = VARPTR(PushParams(pCount).DataValue.lExt)
                      ! push PushParam
    
                    CASE %ByType_ByVal
                      PushParam = VARPTR(PushParams(pCount).DataValue.lExt)
                      !mov eax,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  
    
                  END SELECT
    
                CASE %ParamType_Double
                  SELECT CASE PushParams(pCount).ByType
                    CASE %ByType_ByRef, %ByType_ByCopy
                      PushParam = VARPTR(PushParams(pCount).DataValue.lDouble)
                      ! push PushParam
    
                    CASE %ByType_ByVal
                      PushParam = VARPTR(PushParams(pCount).DataValue.lDouble)
                      !mov eax,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
    
                  END SELECT
              END SELECT
    
            NEXT
      
            '---
            'Call the function and get return code
            '---
            ! Xor eax, eax
            ! Call hProc
            ! mov RetVal, eax
      
            '---
            'Unload the DLL
            '---
            FreeLibrary hLib
      
            '---
            'If necessary, deallocate allocated memory
            '---
            FOR pCount = lb TO ub
              SELECT CASE PushParams(pCount).DataType
                CASE %ParamType_Asciiz
                  MemFree PushParams(pCount).DataValue.lString
              END SELECT
            NEXT
      
            FUNCTION = RetVal
          ELSE
            '---
            'Error calling function
            '---
            lError = 1
    
          END IF
      
        ELSE
          '---
          'Error loading library
          '---
          lError = 2
          
        END IF
        
      END FUNCTION

    Example code

    Code:
    #Compile Exe
    
    #Include "win32api.inc"
    #Include "CallDll.inc"
    
    
      FUNCTION PBMAIN() AS LONG
      
        LOCAL lError AS LONG
    
        '---
        'Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long
        '---
        REDIM Params(3) AS STRING
        Params(0) = "BYVAL LONG 0"
        Params(1) = "BYVAL ASCIIZ Message Text"
        Params(2) = "BYVAL ASCIIZ Window caption"
        Params(3) = "BYVAL LONG 0"
        CallDll "user32.Dll", "MessageBoxA", Params(), lError
       
        '---
        'DECLARE FUNCTION GetVersionEx LIB "KERNEL32.DLL" ALIAS "GetVersionExA" (lpVersionInformation AS ANY) AS LONG
        '---
        DIM os AS OSVERSIONINFO
        DIM s  AS STRING 
        os.dwOSVersionInfoSize = SIZEOF(os)
    
        REDIM Params(0) AS STRING
        Params(0) = "BYVAL UDT " + STR$(VARPTR(os))
        CallDll "KERNEL32.DLL", "GetVersionExA", Params(), lError
    
        SELECT CASE os.dwPlatformId
          CASE %VER_PLATFORM_WIN32_NT
            IF os.dwMajorVersion = 5 THEN
                    SELECT CASE os.dwMinorVersion
                       CASE 0
                           s = "Windows 2K"
                       CASE 1
                           s = "Windows XP"
                       CASE 2
                           s = "WinDotNet Server"
                  END SELECT
      
            ELSE
              s = "Windows NT " & FORMAT$(os.dwMajorVersion) & "." & FORMAT$(os.dwMinorVersion)
            END IF
            s = s & " Build" & STR$(os.dwBuildNumber)
            IF LEN(os.szCSDVersion) THEN
              s = s & " (" & os.szCSDVersion & ")"
            END IF
          CASE ELSE
            IF os.dwMinorVersion = 0 THEN
              s = "Windows 95"
              IF os.szCSDVersion = "B" THEN
                s = s & " OSR2"
              END IF
            ELSEIF os.dwMinorVersion = 10 THEN
              s = "Windows 98"
              IF os.szCSDVersion = "A" THEN
                s = s & " SE"
              END IF
            ELSEIF os.dwMinorVersion = 90 THEN
              s = "Windows ME"
            ELSE
              s = "Windows" & FORMAT$(os.dwMajorVersion) & "." & FORMAT$(os.dwMinorVersion)
            END IF
            s = s & " Build" & STR$(os.dwBuildNumber AND &HFFFF)
        END SELECT
        MSGBOX s
    
    
        '---
        'Declare Function GetCurrentDirectory Lib "kernel32" Alias "GetCurrentDirectoryA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
        '---
        tmpStr$ = STRING$(%MAX_PATH, CHR$(0))
        REDIM Params(1) AS STRING
        Params(0) = "BYVAL LONG " + FORMAT$(%MAX_PATH)
        Params(1) = "BYVAL LONG " + FORMAT$(STRPTR(tmpStr$))
        CallDll "kernel32.dll", "GetCurrentDirectoryA", Params(), lError
        MSGBOX "GetCurrentDirectoryA" + $CRLF + tmpStr$
    
        '---
        'Declare Function GetWindowsDirectory Lib "kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
        '---
        tmpStr$ = STRING$(%MAX_PATH, CHR$(0))
        REDIM Params(1) AS STRING
        Params(0) = "BYVAL LONG " + FORMAT$(STRPTR(tmpStr$))
        Params(1) = "BYVAL LONG " + FORMAT$(%MAX_PATH)
        CallDll "kernel32.dll", "GetWindowsDirectoryA", Params(), lError
        MSGBOX "GetWindowsDirectoryA" + $CRLF + tmpStr$
    
        '---
        'Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
        '---
        tmpStr$ = STRING$(%MAX_PATH, CHR$(0))
        REDIM Params(1) AS STRING
        Params(0) = "BYVAL LONG " + FORMAT$(%MAX_PATH)
        Params(1) = "BYVAL LONG " + FORMAT$(STRPTR(tmpStr$))
        CallDll "kernel32.dll", "GetTempPathA", Params(), lError
        MSGBOX "GetTempPathA" + $CRLF + tmpStr$
    
        '---
        'Declare Function PathMakePretty Lib "shlwapi.dll" Alias "PathMakePrettyA" (ByVal pszPath As String) As Long
        '---
        tmpStr$ = UCASE$(tmpStr$)
        REDIM Params(1) AS STRING
        Params(0) = "BYVAL LONG " + FORMAT$(STRPTR(tmpStr$))
        CallDll "kernel32.dll", "PathMakePrettyA", Params(), lError
        MSGBOX "PathMakePrettyA" + $CRLF + tmpStr$
    
        '---
        'DECLARE FUNCTION GetUserName LIB "advapi32.dll" ALIAS "GetUserNameA" (BYVAL lpBuffer AS STRING, nSize AS LONG) AS LONG
        '---
        tmpStr$ = STRING$(%MAX_PATH, CHR$(0))
        tmpLong& = %MAX_PATH
        REDIM Params(1) AS STRING
        Params(0) = "BYVAL LONG " + FORMAT$(STRPTR(tmpStr$))
        Params(1) = "BYVAL LONG " + FORMAT$(VARPTR(tmpLong&))
        CallDll "advapi32.dll", "GetUserNameA", Params(), lError
        MSGBOX "GetUserNameA" + $CRLF + LEFT$(tmpStr$, tmpLong&)
    
        '---
        'Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long
        '---
        tmpStr$ = STRING$(%MAX_PATH, CHR$(0))
        tmpLong& = %MAX_PATH
        REDIM Params(1) AS STRING
        Params(0) = "BYVAL LONG " + FORMAT$(STRPTR(tmpStr$))
        Params(1) = "BYVAL LONG " + FORMAT$(VARPTR(tmpLong&))
        CallDll "kernel32.dll", "GetComputerNameA", Params(), lError
        MSGBOX "GetComputerNameA" + $CRLF + LEFT$(tmpStr$, tmpLong&)
    
        '---
        'DECLARE FUNCTION URLDownloadToFile LIB "urlmon.dll" ALIAS "URLDownloadToFileA" (pCaller AS ANY, szURL AS ASCIIZ, szFileName AS ASCIIZ, BYVAL dwReserved AS DWORD, BYVAL lpfnCB AS DWORD) AS LONG
        '---
        tmpStr1$ = "http://www.powerbasic.com"
        tmpStr2$ = "c:\PowerBasicHomePage.htm"
        REDIM Params(5) AS STRING
        Params(0) = "BYVAL LONG 0"
        Params(1) = "BYVAL LONG " + FORMAT$(STRPTR(tmpStr1$))
        Params(2) = "BYVAL LONG " + FORMAT$(STRPTR(tmpStr2$))
        Params(3) = "BYVAL DWORD 0"
        Params(4) = "BYVAL DWORD 0"
        CallDll "urlmon.dll", "URLDownloadToFileA", Params(), lError
        MSGBOX "URLDownloadToFileA executed" + $CRLF + "See file " + tmpStr2$
                   
    End Function

    ------------------
    mailto:[email protected][email protected]</A>
    www.autoapfp.com

    [This message has been edited by Eros Olmi (edited March 04, 2004).]
    thinBasic programming language
    Win10 64bit - 8GB Ram - i7 M620 2.67GHz - NVIDIA Quadro FX1800M 1GB

  • #2
    Eros,

    Nice code!
    I did something similar to your code, but used encoded function's names.
    Just little amendmend:
    If you'd like to hide function calls/names from disassemblers simply encode string references.
    and escpecially - hide code that calls MSGBOX.

    Code:
    ' replacement for MSGBOX, to hide actual calling code.
    ' 
    MACRO PRINT_TEXT (Text, Caption)
        ' encode these strings
        'dll$    = "user32.dll"      
        'fnname$ = "MessageBoxA"  ' 
        REDIM Params(3) AS STRING
        Params(0) = "BYVAL LONG 0"
        Params(1) = "BYVAL ASCIIZ " + Text
        Params(2) = "BYVAL ASCIIZ " + Caption
        Params(3) = "BYVAL LONG 0" 
        ' CallDll dll$, fnname$, Params(), lError
        CallDll "user32.Dll", "MessageBoxA", Params(), lError
    END MACRO
    I have replaced all MSGBOX with macro below, compile it and then run
    Dependency Walker utility. I didn't find any references to MSGBOX function ..

    Regards,
    Aslan.


    ------------------

    Comment


    • #3
      Yes, that's good. Nice improve.

      I think everyone can take this code and adapt to personal specific needs.

      Also passing parameters can be encoded I think and even assembled into
      a single string with some sort of parameter delimiter instead of using an array.

      Regards
      Eros

      ------------------
      mailto:[email protected][email protected]</A>
      www.autoapfp.com
      thinBasic programming language
      Win10 64bit - 8GB Ram - i7 M620 2.67GHz - NVIDIA Quadro FX1800M 1GB

      Comment

      Working...
      X