smashly Posted June 25, 2011 Posted June 25, 2011 (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. expandcollapse popup#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 June 25, 2011 by smashly
trancexx Posted June 25, 2011 Posted June 25, 2011 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
smashly Posted June 25, 2011 Author Posted June 25, 2011 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).
ProgAndy Posted June 25, 2011 Posted June 25, 2011 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
trancexx Posted June 25, 2011 Posted June 25, 2011 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
smashly Posted June 25, 2011 Author Posted June 25, 2011 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
trancexx Posted June 25, 2011 Posted June 25, 2011 (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.CheersBut DllCall works that way, LoadLibrary->GetProcAddress->Call pointer.Check calling convention, type of parameters and other little things. Edited June 25, 2011 by trancexx ♡♡♡ . eMyvnE
ProgAndy Posted June 25, 2011 Posted June 25, 2011 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
smashly Posted June 25, 2011 Author Posted June 25, 2011 (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 codeexpandcollapse popupGlobal 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 June 25, 2011 by smashly
Andreik Posted June 25, 2011 Posted June 25, 2011 (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 June 25, 2011 by Andreik
smashly Posted June 25, 2011 Author Posted June 25, 2011 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
Andreik Posted June 25, 2011 Posted June 25, 2011 (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 June 25, 2011 by Andreik
trancexx Posted June 25, 2011 Posted June 25, 2011 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
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now