Sign in to follow this  
Followers 0
smashly

[Solved] WinAPI GetProcAddress and call function

14 posts in this topic

#1 ·  Posted (edited)

Hi and thank you for taking the time to read my post.

I'm using LoadLibrary to load a dll, GetProcAddress to find the address of a function but I'm having trouble trying to understand how to call the function from process address using autoit.

I wrote a small dll wrapper which works fine to do exactly that and it works fine, but I was wondering how to do it in AutoIt without using my dll.

Here's a non working example of where I'm trying to do such a thing.

#include <WinAPI.au3>

_ASPI_Init()
ConsoleWrite("_ASPI_Init Error: " & @error & @LF)


Func _ASPI_Init()
    Local $hASPI, $pGetASPI32SupportInfo, $pSendASPI32Command

    ;load WNASPI32.DLL
    $hASPI = _WinAPI_LoadLibrary("WNASPI32.DLL")

    ; Failed to load WNASPI32.DLL
    If Not $hASPI Then Return SetError(2, 0, 0)


    ;Load the address of GetASPI32SupportInfo
    $pGetASPI32SupportInfo = _WinAPI_GetProcAddress($hASPI, "GetASPI32SupportInfo")

    ; Failed to find function address of GetASPI32SupportInfo
    If Not $pGetASPI32SupportInfo Then Return SetError(3, 0, 0)



    ;Load the address of SendASPI32Command
    $pSendASPI32Command = _WinAPI_GetProcAddress($hASPI, "SendASPI32Command")

    ; Failed to find function address of GetASPI32SupportInfo
    If Not $pSendASPI32Command Then Return SetError(4, 0, 0)


    ; From here I need to call "GetASPI32SupportInfo" and or "SendASPI32Command" and use the return to proceed..
    ; But currently I have no idea how to do this in AutoIt.....
EndFunc   ;==>_ASPI_Init

Func _WinAPI_GetProcAddress($hModule, $sProcess)
    Local $aReturn

    $aReturn = DllCall('kernel32.dll', 'ptr', 'GetProcAddress', 'ptr', $hModule, 'str', $sProcess)
    If @error Then Return SetError(@error, 0, 0)
    Return SetError(0, 0, $aReturn[0])
EndFunc   ;==>_WinAPI_GetProcAddress

Any advice or pointers if it's possible or how to accomplish calling functions in AutoIt would be appreciated.

Cheers

Edited by smashly

Share this post


Link to post
Share on other sites



There are more than one way of doing that. Using proper depends on the needs of the code.

What do you need it for? Is it just exercise or there is more to it?


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Hi, just exercise mainly.

Was playing with winaspi and talking to my cd/dvd drive and ripping sectors to a buffer and dumping the data to bin file.

All seems to work ok (in most cases).

I think the proper way would be to use DeviceIoControl (structures seem the same thing as what I was doing with winaspi).

Share this post


Link to post
Share on other sites

Then just use DllCall.


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

Hi, just exercise mainly.

Was playing with winaspi and talking to my cd/dvd drive and ripping sectors to a buffer and dumping the data to bin file.

All seems to work ok (in most cases).

I think the proper way would be to use DeviceIoControl (structures seem the same thing as what I was doing with winaspi).

Why can't you just use DllCall?

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Or even better, what ProgAndy said.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Hi and thanks for taking the time to respond,

DllCall to winaspi32.dll works for GetASPI32SupportInfo successfully, but fails with SendASPI32Command and results in autoit crash.

This was why I was using LoadLibrary (it's the way I did in my wrapper dll) as it works as expected.

Cheers

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Hi and thanks for taking the time to respond,

DllCall to winaspi32.dll works for GetASPI32SupportInfo successfully, but fails with SendASPI32Command and results in autoit crash.

This was why I was using LoadLibrary (it's the way I did in my wrapper dll) as it works as expected.

Cheers

But DllCall works that way, LoadLibrary->GetProcAddress->Call pointer.

Check calling convention, type of parameters and other little things.

Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Oh, and if you have to keep the Dll loaded between two Dllcalls, you should use DllOpen


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Hi,

Thank you for the advice, but DllCall fails at "SendASPI32Command" regardless of what I try.

The call is simple so it doesn't leave that much room for error.

I'd say it's the DllStruct or alignment issue for what I'm passing but..

There is one parameter in the call and it's a pointer to an autoit dllstruct.

The same autoit dllstruct I pass from autoit to my wrapper works as expected.

Passing the same autoit struct using DllCall to directly call WINASPI.dll makes AutoIt hard crash.

Calling my dll that talks to WINASPI.dll works.

My dll wrapper I use LoadLibrary->GetProcAddress->Call pointer.

Using AutoIt to DllOpen, DllCall directly with WINASPI.dll hard crashes autoit at "SendASPI32Command" function.

I've tried changing return types, and ptr param eg: long_pointer, uint_ptr, ptr* and any other type as well :)

I've tried _Mem functions and pasing a pointer to a pointer and god knows how many other illogical ideas..lol

In the code below if I replace "WNASPI32.DLL" with my own wrapper dll (ASPIwrapper.dll) then the code works as expected.

Example of non working, autoit hard crash code

Global Const $SS_COMP = 0x01                   ;// SRB completed without error
Global Const $SS_OLD_MANAGER = 0xE1             ;// Invalid parameter set in SRB
Global Const $SS_ILLEGAL_MODE = 0xE2           ;// Unsupported Windows mode
Global Const $SS_NO_ASPI = 0xE3                ;// No ASPI managers resident

Global Const $SC_HA_INQUIRY = 0x00             ;// Host adapter inquiry

; SRB - HOST ADAPTER INQUIRY - SC_HA_INQUIRY
Global Const $tag_SRB_HAInquiry = _
                "BYTE SRB_Cmd;" & _  ;            ; 00/000 ASPI command code = SC_HA_INQUIRY
                "BYTE SRB_Status;" & _  ;         ; 01/001 ASPI command status byte
                "BYTE SRB_HaId;" & _  ;           ; 02/002 ASPI host adapter number
                "BYTE SRB_Flags;" & _  ;          ; 03/003 ASPI request flags
                "DWORD SRB_Hdr_Rsvd;" & _  ;      ; 04/004 Reserved, MUST = 0
                "BYTE HA_Count;" & _  ;           ; 08/008 Number of host adapters present
                "BYTE HA_SCSI_ID;" & _  ;         ; 09/009 SCSI ID of host adapter
                "BYTE HA_ManagerId[16];" & _  ;   ; 0A/010 String describing the manager
                "BYTE HA_Identifier[16];" & _  ;  ; 1A/026 String describing the host adapter
                "BYTE HA_Unique[16];" & _  ;      ; 2A/042 Host Adapter Unique parameters
                "WORD HA_Rsvd1"                   ; 3A/058 Reserved, MUST = 0

Global $_ASPIDLL = -1

_ASPI_Init()

If $_ASPIDLL <> -1 Then DllClose($_ASPIDLL)

Func _ASPI_Init()
    Local $aReturn
;~  $_ASPIDLL = DllOpen("ASPIwrapper.dll")
    $_ASPIDLL = DllOpen("WNASPI32.DLL")
    If $_ASPIDLL = -1 Then Return ConsoleWrite("DllOpen failed to open WNASPI32.DLL")

    ; this works fine
;~  $aReturn = DllCall($_ASPIDLL, "dword", "GetASPI32SupportInfoEx")
    $aReturn = DllCall($_ASPIDLL, "dword", "GetASPI32SupportInfo")
    If @error Then Return ConsoleWrite("DllCall GetASPI32SupportInfo Failed Error: " & @error)
    ConsoleWrite("DllCall GetASPI32SupportInfo Succes Return: " & $aReturn[0] & @LF)

    $iHaCount = BitAND($aReturn[0], 0xFF ) ; LoByte
    $iASPIStatus = BitAND(BitShift($aReturn[0], 8), 0xFF) ; HiByte
    Switch $iASPIStatus
        Case $SS_COMP
            ConsoleWrite("$SS_COMP: ASPI support OK: " & $SS_COMP & @LF)
            ConsoleWrite("Number of host adapters present: " & $iHaCount & @LF)
        Case $SS_NO_ASPI
            ConsoleWrite("$SS_NO_ASPI: Could not find the ASPI manager." & @LF)
        Case $SS_ILLEGAL_MODE
            ConsoleWrite("$SS_ILLEGAL_MODE ASPI: ASPI for Windows does not support real mode." & @LF)
        Case $SS_OLD_MANAGER
            ConsoleWrite("$SS_OLD_MANAGER: Old ASPI manager." & @LF)
    EndSwitch

    If $iASPIStatus <> $SS_COMP Then Return ConsoleWrite("Error initializing ASPI." & @LF)


    $tSRB_HAInquiry = DllStructCreate($tag_SRB_HAInquiry)
    DllStructSetData($tSRB_HAInquiry, "SRB_Cmd", $SC_HA_INQUIRY)
    DllStructSetData($tSRB_HAInquiry, "SRB_HaId", 0)

    ; prepare for autoit crash....
;~  $aReturn = DllCall($_ASPIDLL, "dword", "SendASPI32CommandEx", "ptr", DllStructGetPtr($tSRB_HAInquiry))
    $aReturn = DllCall($_ASPIDLL, "dword", "SendASPI32Command", "ptr", DllStructGetPtr($tSRB_HAInquiry))
    If @error Then ConsoleWrite("DllCall SendASPI32Command Failed Error: " & @error)
    ConsoleWrite("DllCall SendASPI32Command Succes: " & $aReturn[0] & @LF)
EndFunc   ;==>_ASPI_Init
Edited by smashly

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

I tried your example and failed. After that I replace:

$aReturn = DllCall($_ASPIDLL, "dword", "SendASPI32Command", "ptr", DllStructGetPtr($tSRB_HAInquiry))
with

$aReturn = DllCall($_ASPIDLL, "dword:cdecl", "SendASPI32Command", "ptr", DllStructGetPtr($tSRB_HAInquiry))
and I get this:

DllCall GetASPI32SupportInfo Succes Return: 256

$SS_COMP: ASPI support OK: 1

Number of host adapters present: 0

DllCall SendASPI32Command Succes: 1

Edited by Andreik

When the words fail... music speaks

Share this post


Link to post
Share on other sites

Hi,

Thank You Andreik :)

I can't believe I didn't see it! *slaps own forehead.. doh

Odd how DllCall($_ASPIDLL, "dword", "GetASPI32SupportInfo") passes without error.

Cheers

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

I think it depends on how the function was written in dll [extern "C"] but indeed it's odd why in same dll they are written in different ways.

Edited by Andreik

When the words fail... music speaks

Share this post


Link to post
Share on other sites

First function doesn't crash because it takes no arguments and calling convention isn't important when that's the case.

It's all about stack. Strictly speaking, first one should be cdecl too.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0