Announcement

Collapse
No announcement yet.

Other architecture DLL in PowerBASIC

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

  • Other architecture DLL in PowerBASIC

    The advantage of using a true low level compiler shows when you need to
    do something different from normal, where "method" based languages do
    not give you the freedom to do unusual things, PowerBASIC has the low
    level grunt needed to be original.

    Below is the code for a different interface in a DLL, instead of having an
    EXPORT for each function that is called, this design only has one which is
    the despatch function which calls the required internal function and
    passes back any return value to the calling EXE.

    It allows very large parameter counts to be passed in a way that normal
    functions find difficult to handle. This example is limited to 32 bit
    return values but of course, the address of a different size parameter can
    be used in the array or structure parameters for different size return
    values.

    It can use either an array or a structure to pass the parameters,
    depending if you need different size parameters or not. The advantage of
    an architecture of this type is that it does not require the operating
    system to look up a large EXPORT table. A DLL of this type is also a lot
    harder to hack as there is no EXPORT to look up.

    There are 2 techniques used to get the parameters at the DLL function end,
    the first uses inline asm to dereference the parameters, the second uses
    the standard PowerBASIC pointers and is clean and easy to understand code.
    This example is still a little rough around the edges and it needs to be
    civilised some but it is a viable technique that can be done in the
    current PowerBASIC DLL compiler.

    James Fuller has a different design that is also original and that has a
    number of advantages when understood, perhaps James if time allows would
    make an example available as I am sure many would appreciate his design
    work here.

    Regards,

    [email protected]

    Code:
      ' Include file components
      
          TYPE IF1
            par1 as DWORD
            par2 as DWORD
            par3 as DWORD
            par4 as DWORD
          END TYPE
      
          GLOBAL RemoteMessageBoxS as DWORD
          GLOBAL RemoteMessageBoxA as DWORD
      
      ' runtime code
      
        ' --------------------------
        ' give DLL functions a name
        ' --------------------------
          RemoteMessageBoxA = 1
          RemoteMessageBoxS = 2
      
      ' call the DLL functions
      
            LOCAL if1p      as IF1
            LOCAL mbMsg     as ASCIIZ * 128
            LOCAL mbTit     as ASCIIZ * 128
      
            Case  50
      
              mbMsg = "This messagebox in displayed in iface.dll !!!"
              mbTit = "Parameters passed in structure"
      
              if1p.par1 = hWin
              if1p.par2 = VarPtr(mbMsg)
              if1p.par3 = VarPtr(mbTit)
              if1p.par4 = %MB_OK
      
              rv& = icall(RemoteMessageBoxS,VarPtr(if1p))
      
            Case  51
      
              mbMsg = "This messagebox in displayed in iface.dll !!!"
              mbTit = "Parameters passed in array"
      
              redim pars&(4)
      
              pars&(0) = hWin
              pars&(1) = VarPtr(mbMsg)
              pars&(2) = VarPtr(mbTit)
              pars&(3) = %MB_OK
              
              rv& = icall(RemoteMessageBoxA,VarPtr(pars&(0)))
      
      
          ' The basic despatch DLL interface
      
      ' ###########################################################################
      
          #COMPILE DLL
      
          #INCLUDE "d:\pb6\winapi\win32api.inc"
      
          GLOBAL hInstance as LONG    ' the DLLs instance handle
      
          DECLARE FUNCTION One(ByVal Address as LONG) as LONG
          DECLARE FUNCTION Two(ByVal Address as DWORD) as LONG
          DECLARE FUNCTION Three(ByVal Address as LONG) as LONG
          DECLARE FUNCTION Four(ByVal Address as LONG) as LONG
          DECLARE FUNCTION Five(ByVal Address as LONG) as LONG
      
      ' ###########################################################################
      
      FUNCTION LibMain(BYVAL hInst    AS LONG, _
                       BYVAL Reason   AS LONG, _
                       BYVAL Reserved AS LONG) EXPORT AS LONG
      
          LOCAL RetVal as LONG
      
          Select Case Reason
            Case %DLL_PROCESS_ATTACH
              hInstance = hInst       ' make DLL instance global
              RetVal = 1              ' needed so DLL will start
      
            ' -------------------
            ' uncomment if needed
            ' -------------------
            ' Case %DLL_PROCESS_DETACH
            
            ' Case %DLL_THREAD_ATTACH
            
            ' Case %DLL_THREAD_DETACH
            
          End Select
      
          FUNCTION = RetVal
      
      END FUNCTION
      
      ' ###########################################################################
      
      FUNCTION icall ALIAS "icall"(ByVal FuncNum as LONG, _
                                   ByVal Address as LONG) EXPORT as LONG
      
          Select Case FuncNum
            Case 1
              FUNCTION = One(Address)
            Case 2
              FUNCTION = Two(Address)
            Case 3
              FUNCTION = Three(Address)
            Case 4
              FUNCTION = Four(Address)
            Case 5
              FUNCTION = Five(Address)
          End Select
      
          FUNCTION = -1   '< function not supported
      
      END FUNCTION
      
      ' ###########################################################################
      
      FUNCTION One(ByVal Address as LONG) as LONG
      
          LOCAL par1 as LONG
          LOCAL par2 as LONG
          LOCAL par3 as LONG
          LOCAL par4 as LONG
      
          ! mov eax, Address
      
          ! mov ecx, [eax]
          ! mov par1, ecx
      
          ! mov ecx, [eax + 4]
          ! mov par2, ecx
      
          ! mov ecx, [eax + 8]
          ! mov par3, ecx
      
          ! mov ecx, [eax + 12]
          ! mov par4, ecx
      
          FUNCTION = MessageBox(par1,ByVal par2,ByVal par3,par4)
      
      END FUNCTION
      
      ' ###########################################################################
      
      FUNCTION Two(ByVal Address as DWORD) as LONG
      
          LOCAL par1 as DWORD PTR
          LOCAL par2 as DWORD PTR
          LOCAL par3 as DWORD PTR
          LOCAL par4 as DWORD PTR
      
          par1 = Address
          par2 = Address + 4
          par3 = Address + 8
          par4 = Address + 12
      
          FUNCTION = MessageBox(@par1,ByVal @par2,ByVal @par3,@par4)
      
      END FUNCTION
      
      ' ###########################################################################
      
      FUNCTION Three(ByVal Address as LONG) as LONG
      
      
          FUNCTION = 0
      
      END FUNCTION
      
      ' ###########################################################################
      
      FUNCTION Four(ByVal Address as LONG) as LONG
      
      
          FUNCTION = 0
      
      END FUNCTION
      
      ' ###########################################################################
      
      FUNCTION Five(ByVal Address as LONG) as LONG
      
      
          FUNCTION = 0
      
      END FUNCTION
      
      ' ###########################################################################
    ------------------
    hutch at movsd dot com
    The MASM Forum - SLL Modules and PB Libraries

    http://www.masm32.com/board/index.php?board=69.0

  • #2
    Here is my rendition which shows two similiar methods.

    Method one would be used when the dll contains many functions but the application
    only uses a few functions or there are a small number of times the application calls
    the functions.

    Method two would be used when the application relies heavily on the functions in the dll.

    James

    Code:
    '==============================================================================
    'DLL CODE:
    '------------------------------------------------------------------------------
    #COMPILE DLL "MYWAY.DLL"
    #REGISTER NONE
    #DIM ALL
    
    FUNCTION _
      One& ( _
        BYVAL a& _
      )
      
      MsgBox "In Dll Function One"+ $CR + "a& = " + FORMAT$(a&) 
      FUNCTION = a& * 10 
    END FUNCTION    
    '------------------------------------------------------------------------------
    FUNCTION _
      Two& ( _
        BYVAL a&,BYVAL b& _
      )
      
        MsgBox "In Dll Function Two"+ $CR + " a& = " + FORMAT$(a&) + $CR + " b& = " + FORMAT$(b&)  
        FUNCTION = a& + b&
    END FUNCTION    
    '------------------------------------------------------------------------------
    FUNCTION _
      Three$ ( _
        StrIn$ _
      )
      
      FUNCTION = StrIn$ + " More Characters Added" + $CR + "Another Line"
      
    END FUNCTION    
    '------------------------------------------------------------------------------
    FUNCTION _
      Test01& ALIAS "Test01" ( _
        BYVAL Id& _
      )EXPORT
    
      SELECT CASE Id&
        CASE 1
        FUNCTION = CODEPTR(One&)
        CASE 2
          FUNCTION = CODEPTR(Two&) 
        CASE 3
          FUNCTION = CODEPTR(Three$) 
      END SELECT 
    END FUNCTION    
    '------------------------------------------------------------------------------
    FUNCTION _
      Test02& ALIAS "Test02" ( _
        IdArray???() _
      )EXPORT
    
      IF UBOUND(IdArray???) < 3 THEN
        FUNCTION = -1
        EXIT FUNCTION
      END IF   
    
      IdArray???(1) = CODEPTR(One&)
      IdArray???(2) = CODEPTR(Two&)
      IdArray???(3) = CODEPTR(Three&)
    END FUNCTION    
    '==============================================================================
    
    '=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
    'Test Code
    'Method #1
    '=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
    #COMPILE EXE
    #DIM ALL
    #REGISTER NONE
    '------------------------------------------------------------------------------
    DECLARE _
      FUNCTION _
        Test  LIB "MYWAY.DLL" ALIAS "Test01" ( _
          BYVAL Id& _
        )  AS DWORD
    '------------------------------------------------------------------------------
    FUNCTION _
      One& ( _
        BYVAL a& _
        )
      LOCAL pAdd???
      pAdd??? = Test(1)  
      CALL DWORD pAdd USING One&(a&) 
     !mov FUNCTION,eax
    END FUNCTION    
    '------------------------------------------------------------------------------
    FUNCTION _
      Two& ( _
        BYVAL a&, _
        BYVAL b& _
      )
      LOCAL pAdd???
      pAdd??? = Test(2)  
      CALL DWORD pAdd USING Two&(a&,b&) 
     !mov FUNCTION,eax
        
    END FUNCTION  
    '------------------------------------------------------------------------------
    FUNCTION _
      Three$ ( _
        StrIn$ _
      )
    
      LOCAL pAdd???
      pAdd??? = Test(3)  
      CALL DWORD pAdd USING Three$(StrIn$)
     !mov FUNCTION,eax
      
    END FUNCTION      
    '------------------------------------------------------------------------------    
    
    FUNCTION _
      PBMain ( _
      ) AS LONG
      
      LOCAL RetVal& ,Temp$
      
      RetVal& = One&(1)
      MsgBox "RetVal From One = " +FORMAT$(RetVal&)
      RetVal& = Two&(1,2)
      MsgBox "RetVal From Two = " + FORMAT$(RetVal&)
      Temp$ = Three$("some text")
      MsgBox Temp$
    END FUNCTION
    '==============================================================================
    '=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
    'Test Code      
    'Method #2
    '=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
    #COMPILE EXE
    #DIM ALL
    #REGISTER NONE
    '------------------------------------------------------------------------------
    DECLARE _
      FUNCTION _
        Test  LIB "MYWAY.DLL" ALIAS "Test02" ( _
          IdArray???() _
        )  AS DWORD
    '------------------------------------------------------------------------------
    GLOBAL IdArray???()
    '------------------------------------------------------------------------------
    FUNCTION _
      One& ( _
        BYVAL a& _
        )
      CALL DWORD IdArray???(1) USING One&(a&) 
     !mov FUNCTION,eax
    END FUNCTION    
    '------------------------------------------------------------------------------
    FUNCTION _
      Two& ( _
        BYVAL a&, _
        BYVAL b& _
      )
    
      CALL DWORD IdArray???(2) USING Two&(a&,b&) 
     !mov FUNCTION,eax
        
    END FUNCTION  
    '------------------------------------------------------------------------------
    FUNCTION _
      Three$ ( _
        StrIn$ _
      )
    
      CALL DWORD IdArray???(3) USING Three$(StrIn$)
     !mov FUNCTION,eax
      
    END FUNCTION      
    '------------------------------------------------------------------------------    
    
    FUNCTION _
      PBMain ( _
      ) AS LONG
      
      LOCAL RetVal& ,Temp$
      REDIM IdArray???(1:3)
      RetVal& = Test(IdArray())
      
      RetVal& = One&(1)
      MsgBox "RetVal From One = " +FORMAT$(RetVal&)
      RetVal& = Two&(1,2)
      MsgBox "RetVal From Two = " + FORMAT$(RetVal&)
      Temp$ = Three$("some text")
      MsgBox Temp$
    END FUNCTION


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

    Comment

    Working...
    X