Tool to call DLL functions from command line

Windows specific questions.
Post Reply
Vortex
Posts: 108
Joined: Sep 19, 2005 9:50

Tool to call DLL functions from command line

Post by Vortex »

Here is a small tool to call DLL functions from command line. A quick example, Demo.bat :

Code: Select all

@ECHO OFF

SET MB_OK=0

CallDllFunc.exe msvcrt printf "Hex representation of 35 = 0x%%X" @35
CallDllFunc.exe msvcrt.dll puts

callDllFunc.exe user32.dll MessageBoxA @0 "This is a test." "Hello" @%MB_OK%

CallDllFunc.exe msvcrt printf "Backslash symbol \ to escape the ASCII to UInt converter @ , %%s" \@2022
The leading symbol @ instructs the tool to convert strings to numerical values. This can be bypassed with a leading backslash symbol.

CallDllFunc.bas :

Code: Select all

' Source code compiled with
' FreeBASIC Compiler - Version 1.09.0 (2021-12-31), built for win32 (32bit)

'CallDllFunc Version 1.0

#include "windows.bi"

Const ASCII_At_Symbol = 64

Dim As Ulong argc = __fb_argc__
Dim As ZString Ptr Ptr argv = __fb_argv__

Dim param(1 To 64) As Integer
Dim As Integer stack,i,LastParam,NumbOfParams,ParamNumb=1
Dim As HMODULE hMod
Dim As FARPROC DllFunc

If argc < 3 Then
    
    Print "CallDllFunc library.dll function [parameter1] [parameter2] ..."
    End
    
End If

hMod=LoadLibrary(argv[1])

If hMod=0 Then 
    
    Print "LoadLibrary could not load ";*argv[1]
    End
    
End If

DllFunc=GetProcAddress(hMod,argv[2])

If DllFunc=0 Then 
    
    Print "GetProcAddress could not find the address of ";*argv[2]
    FreeLibrary hMod
    End
    
End If

If argc = 3 Then
    
    Asm Call DWORD Ptr [DllFunc]
    
Else    
    
    For i=3 To argc-1
        
        ' ASCII 92 = \
        ' ASCII 64 = @
        ' \Q => 64+256*92 = 16476
        
        If *Cast(Ushort Ptr,argv[i])=16476 Then
            
            param(ParamNumb)=Cast(Uinteger,argv[i]+1)
            
            
        Elseif *Cast(Byte Ptr,argv[i]) = ASCII_At_Symbol Then 
            
            param(ParamNumb)=Valuint(*(argv[i]+1))
            
        Else
            
            param(ParamNumb)=Cast(Uinteger,argv[i])
            
        End If
        
        ParamNumb=ParamNumb+1
        
    Next i
    
    LastParam=Cast(Uinteger,@param(ParamNumb-1))
    
    NumbOfParams=argc-3
    
    Asm
        
        push DWORD Ptr [NumbOfParams]
        pop  ecx
        
        push DWORD Ptr [LastParam]
        pop  edx 
        
        push esp
        pop  DWORD Ptr [stack]
        
_loop:
        
        push DWORD Ptr [edx]
        sub  edx,4
        dec  ecx
        
        jnz  _loop
        
        Call  DWORD Ptr [DllFunc]
        
'Take care to balance the stack if DllFunc is a C function \ __cdecl
        
        push DWORD Ptr [stack]
        pop  esp
        
    End Asm
    
End If

FreeLibrary(hMod)
jj2007
Posts: 2327
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Tool to call DLL functions from command line

Post by jj2007 »

Nice idea, Vortex!
Vortex
Posts: 108
Joined: Sep 19, 2005 9:50

Re: Tool to call DLL functions from command line

Post by Vortex »

Hi jj2007,

Thanks. The built-in Windows application rundll32.exe has limited capabilities. CallDllFunc should provide more functionality at this point.
Vortex
Posts: 108
Joined: Sep 19, 2005 9:50

Re: Tool to call DLL functions from command line

Post by Vortex »

New version : If the return value of the called function is a pointer to a string then CallDllFunc can print this string to the console. The preceeding symbol # before the function name instructs the tool to output the string pointed by the register eax .

Demo.bat :

Code: Select all

@ECHO OFF

SET MB_OK=0

CallDllFunc msvcrt printf "Hex representation of 35 = 0x%%X" @35
CallDllFunc msvcrt.dll puts

callDllFunc user32.dll MessageBoxA @0 "This is a test." "Hello" @%MB_OK%

CallDllFunc msvcrt printf "Backslash symbol \ to escape the ASCII to UInt converter @ , %%s" \@2022
CallDllFunc msvcrt.dll puts

CallDllFunc testdll.dll sum @90 @10
@Echo 90 + 10 = %ErrorLevel%

@REM Assigning the output of CallDllFunc to a variable

@FOR /f "tokens=*" %%a IN ('CallDllFunc msvcrt.dll #_strupr "This is another test."') DO Set string=%%a

echo %String%
CallDllFunc.bas :

Code: Select all

' Source code compiled with
' FreeBASIC Compiler - Version 1.09.0 (2021-12-31), built for win32 (32bit)

'CallDllFunc Version 1.1

#include "windows.bi"

Const ASCII_At_Symbol = 64
Const ASCII_Number_Symbol = 35

Dim As Ulong argc = __fb_argc__
Dim As ZString Ptr Ptr argv = __fb_argv__

Dim param(1 To 64) As Integer
Dim As Integer stack,i,LastParam
Dim As Integer NumbOfParams,ParamNumb=1
Dim As Integer RetVal,flag=0
Dim As HMODULE hMod
Dim As FARPROC DllFunc

If argc < 3 Then
    
    Print "CallDllFunc library.dll function [parameter1] [parameter2] ..."
    End
    
End If

hMod=LoadLibrary(argv[1])

If hMod=0 Then 
    
    Print "LoadLibrary could not load ";*argv[1]
    End
    
End If


If  *Cast(Byte Ptr,argv[2])=ASCII_Number_Symbol Then
    
    argv[2]+=1
    flag=1
    
End If 


DllFunc=GetProcAddress(hMod,argv[2])

If DllFunc=0 Then 
    
    Print "GetProcAddress could not find the address of ";*argv[2]
    FreeLibrary hMod
    End
    
End If

If argc = 3 Then
    
    Asm Call DWORD Ptr [DllFunc]
    
Else    
    
    For i=3 To argc-1
        
        ' ASCII 92 = \
        ' ASCII 64 = @
        ' \Q => 64+256*92 = 16476
        
        If *Cast(Ushort Ptr,argv[i])=16476 Then
            
            param(ParamNumb)=Cast(Uinteger,argv[i]+1)
            
            
        Elseif *Cast(Byte Ptr,argv[i]) = ASCII_At_Symbol Then 
            
            param(ParamNumb)=Valuint(*(argv[i]+1))
            
        Else
            
            param(ParamNumb)=Cast(Uinteger,argv[i])
            
        End If
        
        ParamNumb=ParamNumb+1
        
    Next i
    
    LastParam=Cast(Uinteger,@param(ParamNumb-1))
    
    NumbOfParams=argc-3
    
    Asm
        
        mov  ecx,DWORD Ptr [NumbOfParams]
        mov  edx,DWORD Ptr [LastParam]
        mov  DWORD Ptr [stack],esp
        
        _loop:
        
        push DWORD Ptr [edx]
        Sub  edx,4
        dec  ecx
        
        jnz  _loop
        
        Call DWORD Ptr [DllFunc]
        
        mov  DWORD Ptr [RetVal],eax
        
        'Take care to balance the stack if DllFunc is a C function \ __cdecl
        
        mov  esp,DWORD Ptr [stack]
        
    End Asm
    
End If

Asm
    
    mov     ecx,DWORD Ptr [flag]
    test    ecx,ecx
    jz      _exit
    
    .extern _printf
    
    push    DWORD Ptr [RetVal]
    Call    _printf
    add     esp,4
    
_exit:
    
End Asm

FreeLibrary(hMod)

End RetVal
testdll.dll for the batch file Demo.bat :

Code: Select all

Function sum Cdecl Alias "sum" (Byval x As Integer, Byval y As Integer) As Integer Export
    
    Return(x+y)
    
End Function

Function subs Cdecl Alias "subs" (Byval x As Integer, Byval y As Integer) As Integer Export
    
    Return(x-y)
    
End Function
Post Reply