OldNoob

Help with DLLCALL - Kernel32.dll

11 posts in this topic

#1 ·  Posted

 I'm attempting to call the winapi function EnumSystemFirmwareTables using DllCall "Kernel32.dll" without success. I am a total noob when it comes to this and could use some direction. Based on the documentation "Dealing with Dlls in AutoIt" by Andreas Karlsson, I have tried using the following code to obtain the buffersize of the Firmware Table Buffer.

Thanks in advance for any help

#include <WinAPI.au3>

MsgBox(0, "ESFT BufferSize", "BufferSize = " & _EnumSystemFirmwareTables())

Func _EnumSystemFirmwareTables()
    $aRet = DllCall ("Kernel32.dll", "UINT", "EnumSystemFirmwareTables", "DWORD", "ACPI", "PVOID" ,Null , "DWORD" ,Null)
    if @error Then
        MsgBox (0,"Error","An error ocurred with the DLLCALL, error returned = " & @error &@CRLF & "GetLastError =  " & _WinAPI_GetLastError ( ),0)
        Exit
    else
    Return $aRet
    endif
EndFunc

 

Share this post


Link to post
Share on other sites



#2 ·  Posted

Hello. You need to convert the str to dword. and get the requiered size before get the firewaretable dword array.

 

Saludos

Share this post


Link to post
Share on other sites

#3 ·  Posted

Thanks for the response I am still not understanding though. The following is from Microsoft's documentation

UINT WINAPI EnumSystemFirmwareTables(
  _In_  DWORD FirmwareTableProviderSignature,
  _Out_ PVOID pFirmwareTableBuffer,
  _In_  DWORD BufferSize
);

Parameters

FirmwareTableProviderSignature [in]

The identifier of the firmware table provider to which the query is to be directed. This parameter can be one of the following values.

Value Meaning
'ACPI' The ACPI firmware table provider.
'FIRM' The raw firmware table provider. Not supported for UEFI systems; use 'RSMB' instead.
'RSMB' The raw SMBIOS firmware table provider.

pFirmwareTableBuffer [out]

A pointer to a buffer that receives the list of firmware tables. If this parameter is NULL, the return value is the required buffer size.

 

Can you elaborate more on what 'str' I need to first convert?

 

Thanks

 

 

 

 

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

5 hours ago, Danyfirex said:

Hello. You need to convert the str to dword. and get the requiered size before get the firewaretable dword array.

That is true, but also the type "PVOID" need to be converted i think it's "ptr"

here's an example that works.

$aRet = DllCall ("Kernel32.dll", "UINT", "EnumSystemFirmwareTables", "DWORD", Dec(_StringToHex("ACPI")), "PTR", Null, "DWORD", Null)

Edit:

#include <Array.au3>
#include <String.au3>
#include <WinAPIDiag.au3>

$aRet = DllCall ("Kernel32.dll", "UINT", "EnumSystemFirmwareTables", "DWORD", Dec(_StringToHex("ACPI")), "PTR", Null, "DWORD", Null)
$tDWORD = DllStructCreate("DWORD["&($aRet[0]/4)&"]")
$aRet = DllCall ("Kernel32.dll", "UINT", "EnumSystemFirmwareTables", "DWORD", Dec(_StringToHex("ACPI")), "STRUCT*", $tDWORD, "DWORD", DllStructGetSize($tDWORD))
_ArrayDisplay($aRet)
_WinAPI_DisplayStruct($tDWORD, "DWORD["&($aRet[0]/4)&"]")

This is a more helpful snippet i would say. Looked into using the identifiers with "GetSystemFirmwareTable" but i had trouble finding the struct to use with "ACPI". Closest thing i found was this: FADT structure, but i am not even going to try with that unless I'm certain.

Edited by genius257

Share this post


Link to post
Share on other sites

#5 ·  Posted

You're right @genius257

You can do something like this.

#include <Array.au3>

Local $aTables = _EnumSystemFirmwareTables("ACPI")
_ArrayDisplay($aTables)

Func _EnumSystemFirmwareTables($sSignature)
    Local $aTables[1] = [0]
    Local $aRet = DllCall("Kernel32.dll", "uint", "EnumSystemFirmwareTables", "dword", _Signature($sSignature), "ptr", Null, "dword", 0)
    If @error Or Not $aRet[0] Then Return SetError(@error, @extended, $aTables)
    Local $iSize = $aRet[0]
    Local $iBound = $iSize / 4
    Local $tFirewareTable = DllStructCreate("dword[" & $iBound & "]")
    $aRet = DllCall("Kernel32.dll", "uint", "EnumSystemFirmwareTables", "dword", _Signature($sSignature), "ptr", DllStructGetPtr($tFirewareTable), "dword", $iSize)
    If @error Or Not $aRet[0] Then Return SetError(@error, @extended, $aTables)
    ReDim $aTables[$iBound + 1]
    $aTables[0] = UBound($aTables) - 1
    For $i = 1 To UBound($aTables) - 1
        $aTables[$i] = DllStructGetData($tFirewareTable, 1, $i)
    Next

    Return $aTables
EndFunc   ;==>_EnumSystemFirmwareTables



Func _Signature($sString)
    Return "0x" & Hex(Binary($sString))
EndFunc   ;==>_Signature

Saludos

Share this post


Link to post
Share on other sites

#6 ·  Posted

Thank you for those working examples, I'll study the code to get a better understanding of the results they return.

Share this post


Link to post
Share on other sites

So I confirmed the results returned are a list of the Signatures present by converting the returned data using BinaryToString ($aTables[$i]). My goal is to extract the digital product key stored in the MSDM firmware table. I followed the example to get the buffersize and then  set up a structure to match Microsoft's spec.  I'm reasonably certain I've got the buffersize but I haven't quite figured out how to extract the product key. 

 

Thanks

 

#include <Array.au3>
#include <MsgBoxConstants.au3>
#include <StringConstants.au3>
#include <WinAPIDiag.au3>

Local $aTables = _EnumSystemFirmwareTables("ACPI")
_ArrayDisplay($aTables)

Func _EnumSystemFirmwareTables($sSignature)
    Local $MSDM_FirmwareTable = "struct;CHAR Signature[4];UINT Length;BYTE Revision;BYTE Checksum;CHAR OemId[6];CHAR OemTableId[8];UINT OemRevision;CHAR CreatorId[4];UINT CreatorRevision;CHAR ProductKey[49];endstruct"
    Local $bTables[1] = [0]
    Local $bRet = 0
    Local $aTables[1] = [0]
    Local $aRet = DllCall("Kernel32.dll", "uint", "EnumSystemFirmwareTables", "dword", _Signature($sSignature), "ptr", Null, "dword", 0)
    If @error Or Not $aRet[0] Then Return SetError(@error, @extended, $aTables)
    Local $iSize = $aRet[0]
    Local $iBound = $iSize / 4
    Local $tFirewareTable = DllStructCreate("dword[" & $iBound & "]")
    $aRet = DllCall("Kernel32.dll", "uint", "EnumSystemFirmwareTables", "dword", _Signature($sSignature), "ptr", DllStructGetPtr($tFirewareTable), "dword", $iSize)
    If @error Or Not $aRet[0] Then Return SetError(@error, @extended, $aTables)
    ReDim $aTables[$iBound + 1]
    $aTables[0] = UBound($aTables) - 1
    For $i = 1 To UBound($aTables) - 1
        $aTables[$i] = DllStructGetData($tFirewareTable, 1, $i)
        $k = BinaryToString ($aTables[$i])
        msgbox (0,"", Hex($aTables[$i]) & " : " & $k ,1)
        if $k = "MSDM" Then
            $bRet = DllCall("Kernel32.dll", "uint","GetSystemFirmwareTable", "dword", _Signature($sSignature), "dword", _Signature(StringReverse($k)), "ptr", Null, "dword", 0)
            if @error or Not $bRet[0] Then Return SetError(@error, @extended, $aTables)
            Local $jsize = $bRet[0]
            Local $jBound = $jsize / 4
            Local $tFirmwareTable = DllStructCreate($MSDM_FirmwareTable)
            $bTables = DllCall("Kernel32.dll", "uint","GetSystemFirmwareTable", "dword", _Signature($sSignature), "dword", _Signature(StringReverse($k)), "ptr",DllStructGetptr ($tFirmwareTable), "dword", $jBound)
            $ProductKey = DllStructGetData ($tFirmwareTable, "ProductKey")
            MsgBox (0,"", $ProductKey,0)
            $tFirmwareTable = 0
            Return ($bTables)
        endif
    Next

    Return $aTables
EndFunc   ;==>_EnumSystemFirmwareTables



Func _Signature($sString)
    Return "0x" & Hex(Binary($sString))
EndFunc   ;==>_Signature

 

Share this post


Link to post
Share on other sites

I'm not sure if you're topic is breaking the rules, so I will not post  code till  moderator's judgment.

But you can check MSDN resource. https://msdn.microsoft.com/en-us/Library/Windows/Hardware/dn653305(v=vs.85).aspx

 

Saludos

Share this post


Link to post
Share on other sites

Thanks for the link however I get a file not found message when trying to download the whitepaper.

Are there any other resources you can suggest that would help me better understand the DLLStructCreate as well as pulling data from the structure? I do have a legitimate reason for extracting the data however if I'm in violation of breaking the rules then I'll 'cease and desist'.

 

Thanks

 

 

Share this post


Link to post
Share on other sites

#11 ·  Posted

I now have a working version that needs to be cleaned up, when and if the moderators give the ok I will post what I have for discussion

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

  • Similar Content

    • PoojaKrishna
      Help with DLLCall
      By PoojaKrishna
      Hi friends,
      I'm working on a licensing project and we are using LexActicvator of Cryptlex.
      I'm trying to call a function of a DLL using DLLCall method. I'm calling the method 'SetProductFile' of DLL 'LexActivator_64.dll'. The parameter to the method is path to the product file and the method should return 1 on successful execution. But the method always returns 7 in my test run.
      #define LA_E_PFILE ((HRESULT)0x00000007L)   /*     CODE: LA_E_FPATH       MESSAGE: Invalid product file path. */   The DLL and the product file I use are attached, please save to the script folder to test the script. Can anyone please help? I'm stuck for many days. Link to the documentation  https://cryptlex.com/help/using-lexactivator   #RequireAdmin #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <WinAPIReg.au3> #include <WinAPI.au3> #include<array.au3> #include <WinAPISys.au3> $sDLLPath = @ScriptDir& "\LexActivator_64.dll" ;Path to DLL file $sDataFilePath = @ScriptDir& "\Product.dat" ;Path to product data file $hDLL = DllOpen ( $sDLLPath) ;Opening DLL If $hDLL = -1 Then ;If error Msgbox(0,"Error", "Couldn't open the DLL file.") exit EndIf If Not FileExists($sDataFilePath) Then ;Checking product file Msgbox(0,"Error", "Product file does not exist.") exit EndIf $aArray = DllCall ( $hDLL , "int:cdecl", "SetProductFile", "STR", $sDataFilePath ) ;calling SetProductFile method If @error Then ;If error MsgBox(0, "Error","Error occured while calling DLL method: " & @error) Else Msgbox(0,"Result","Result received: " & $aArray[0]) ;result EndIF DllClose ( $hDLL )  
      LexActivator_64.dll
      Product.dat
    • DHL
      Problems comparing two (in memory) bitmaps using memcmp
      By DHL
      Hi, 
      I'm trying to compare two bitmaps (screenshots of the desktop) that I create using BitBlt. The bitmaps can be successfully saved to disk, but when I run the two bitmaps through a CompareBitmaps()-function I found in this thread, which calls memcmp, the script crashes with "Exit code: -1073741819". 
      This crash only happens when I try to compare bitmaps that I got by using BitBlt. If I use the CompareBitmaps()-function on bitmaps created by _GDIPlus_ImageLoadFromFile, everything works fine. (I'm using AutoIT 3.3.6.1)
      I'll attach my script that crashes, and the  CompareBitmaps() example script that works (which I got from the thread previosly mentioned)
      My script, that for some reason crashes : 
      #include <ScreenCapture.au3> #include <GDIPlus.au3> #include <WinAPI.au3> _GDIPlus_Startup() Local $hDesktop = _WinAPI_GetDesktopWindow() $clientS = WinGetClientSize($hDesktop) Local $Width = $clientS[0] Local $Height = $clientS[1] Local $hDC = _WinAPI_GetDC($hDesktop) Local $memDC = _WinAPI_CreateCompatibleDC($hDC) Local $memBmp = _WinAPI_CreateCompatibleBitmap($hDC, $Width, $Height) _WinAPI_SelectObject ($memDC, $memBmp) _WinAPI_BitBlt($memDC, 0, 0, $Width, $Height, $hDC, 0,0, $__SCREENCAPTURECONSTANT_SRCCOPY) _WinAPI_DeleteDC($memDC) _WinAPI_ReleaseDC($hDesktop, $hDC) Local $hImage1 = _GDIPlus_BitmapCreateFromHBITMAP($memBmp) _WinAPI_DeleteObject($memBmp) _GDIPlus_ImageSaveToFile($hImage1, @ScriptDir & "\GDIPlus_Image1.jpg") MsgBox(0, "Debug", "Screenshot taken & saved to disk. Ready to take new screenshot" ) Local $hDC2 = _WinAPI_GetDC($hDesktop) Local $memDC2 = _WinAPI_CreateCompatibleDC($hDC2) Local $memBmp2 = _WinAPI_CreateCompatibleBitmap($hDC2, $Width, $Height) _WinAPI_SelectObject ($memDC2, $memBmp2) _WinAPI_BitBlt($memDC2, 0, 0, $Width, $Height, $hDC2, 0,0, $__SCREENCAPTURECONSTANT_SRCCOPY) _WinAPI_DeleteDC($memDC2) _WinAPI_ReleaseDC($hDesktop, $hDC2) Local $hImage2 =_GDIPlus_BitmapCreateFromHBITMAP($memBmp2) _WinAPI_DeleteObject($memBmp2) _GDIPlus_ImageSaveToFile($hImage2, @ScriptDir & "\GDIPlus_Image2.jpg") MsgBox(0, "Debug", "Screenshot2 taken & saved to disk. Ready to compare images (from memory)" ) MsgBox(0, "bm1==bm2", CompareBitmaps($hImage1, $hImage2) ) ; Clean up resources _GDIPlus_ImageDispose($hImage1) _GDIPlus_ImageDispose($hImage2) ; Shut down GDI+ library _GDIPlus_ShutDown () Func CompareBitmaps($bm1, $bm2) $Bm1W = _GDIPlus_ImageGetWidth($bm1) $Bm1H = _GDIPlus_ImageGetHeight($bm1) $BitmapData1 = _GDIPlus_BitmapLockBits($bm1, 0, 0, $Bm1W, $Bm1H, $GDIP_ILMREAD, $GDIP_PXF32RGB) $Stride = DllStructGetData($BitmapData1, "Stride") $Scan0 = DllStructGetData($BitmapData1, "Scan0") $ptr1 = $Scan0 $size1 = ($Bm1H - 1) * $Stride + ($Bm1W - 1) * 4 $Bm2W = _GDIPlus_ImageGetWidth($bm2) $Bm2H = _GDIPlus_ImageGetHeight($bm2) $BitmapData2 = _GDIPlus_BitmapLockBits($bm2, 0, 0, $Bm2W, $Bm2H, $GDIP_ILMREAD, $GDIP_PXF32RGB) $Stride = DllStructGetData($BitmapData2, "Stride") $Scan0 = DllStructGetData($BitmapData2, "Scan0") $ptr2 = $Scan0 $size2 = ($Bm2H - 1) * $Stride + ($Bm2W - 1) * 4 $smallest = $size1 If $size2 < $smallest Then $smallest = $size2 $call = DllCall("msvcrt.dll", "int:cdecl", "memcmp", "ptr", $ptr1, "ptr", $ptr2, "int", $smallest) _GDIPlus_BitmapUnlockBits($bm1, $BitmapData1) _GDIPlus_BitmapUnlockBits($bm2, $BitmapData2) Return ($call[0]=0) EndFunc ;==>CompareBitmaps  
      Example Script (that basically does the same thing, but works fine)
      #include <GDIPlus.au3> _GDIPlus_Startup() $fname1=FileOpenDialog("First image","","All images(*.bmp;*.jpg;*.png;)") If $fname1="" Then Exit $fname2=FileOpenDialog("Second image image","","All images(*.bmp;*.jpg;*.png;)") If $fname2="" Then Exit $bm1 = _GDIPlus_ImageLoadFromFile($fname1) $bm2 = _GDIPlus_ImageLoadFromFile($fname2) MsgBox(0, "bm1==bm2", CompareBitmaps($bm1, $bm2)) _GDIPlus_ImageDispose($bm1) _GDIPlus_ImageDispose($bm2) _GDIPlus_Shutdown() Func CompareBitmaps($bm1, $bm2) $Bm1W = _GDIPlus_ImageGetWidth($bm1) $Bm1H = _GDIPlus_ImageGetHeight($bm1) $BitmapData1 = _GDIPlus_BitmapLockBits($bm1, 0, 0, $Bm1W, $Bm1H, $GDIP_ILMREAD, $GDIP_PXF32RGB) $Stride = DllStructGetData($BitmapData1, "Stride") $Scan0 = DllStructGetData($BitmapData1, "Scan0") $ptr1 = $Scan0 $size1 = ($Bm1H - 1) * $Stride + ($Bm1W - 1) * 4 $Bm2W = _GDIPlus_ImageGetWidth($bm2) $Bm2H = _GDIPlus_ImageGetHeight($bm2) $BitmapData2 = _GDIPlus_BitmapLockBits($bm2, 0, 0, $Bm2W, $Bm2H, $GDIP_ILMREAD, $GDIP_PXF32RGB) $Stride = DllStructGetData($BitmapData2, "Stride") $Scan0 = DllStructGetData($BitmapData2, "Scan0") $ptr2 = $Scan0 $size2 = ($Bm2H - 1) * $Stride + ($Bm2W - 1) * 4 $smallest = $size1 If $size2 < $smallest Then $smallest = $size2 $call = DllCall("msvcrt.dll", "int:cdecl", "memcmp", "ptr", $ptr1, "ptr", $ptr2, "int", $smallest) _GDIPlus_BitmapUnlockBits($bm1, $BitmapData1) _GDIPlus_BitmapUnlockBits($bm2, $BitmapData2) Return ($call[0]=0) EndFunc ;==>CompareBitmaps  
      Any one got a clue why my script crashes? 
    • tarretarretarre
      Advanced DllCall and DllStruct AutoIt Code Generator BETA v0.6
      By tarretarretarre
      Hello fellas!
      The other night night i was converting a Msdn function to autoit and I stumbled across this topic

       Which inspired me like crazy and I decided to take it a step further and require the user to make almost ZERO effort to export a c++ Msdn function and or a Structure to AutoIt
      Shoutout to toasterking
       
      So after 18-20 effective hours: 
      The GUI is really simple, all you need is a link to a MSDN page and the program does the rest, most of the options is just for user preferences.
      On the inside I have spent a decent amount of work to make sure the code come out correctly, any particular event during the conversion will get fed-back to the user, so he or she will know if anything noticeable happen.
       
      Regular DllCall example
      http://i.imgur.com/HZLijeu.png
      Struct example
      http://i.imgur.com/l3j6wTR.png
       
      Expand spoiler for more pictures
      In the "Msdn Examples" folder you will find some examples of code i have generated, in most of them I only manually added 2-3 lines to make them work. 
      If you dont know where to get these functions you can browse the MSDN Library https://msdn.microsoft.com/en-us/library/ee663300(v=vs.85).aspx and look for any function refrence, or just google "somethingsomething msdn" and the first result will almost always contain the function you are looking for.
      Here is some functions you can play around with
      https://msdn.microsoft.com/en-us/library/windows/desktop/ms724390(v=vs.85).aspx
      https://msdn.microsoft.com/en-us/library/windows/desktop/ms633519(v=vs.85).aspx
      https://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=vs.85).aspx
      https://msdn.microsoft.com/en-us/library/windows/desktop/ms724408(v=vs.85).aspx
       
      I would really appreciate any kind of feedback, improvements or requests 
      If you get any type of error just post the MSDN url + the error message and ID and I will troubleshoot it.
       
      Update 0.2
      Fixed some minor issues Added highlight for a more pleasent view  Fixed minor bugs Made it run faster when working with the same URL (It dosent load the page entierly) No struct search is now done when no POINTER is used in the call Added more options for the user Update 0.3
      Removed _IeNavigate and fixed the template for DllCall not including function name Update 0.4
      Switched method to InetGet from _Ie* H0tfix3s Update 0.5
      Added more options for function-layout Removed old code Added more auto detection Now using @TmpDir instead of @ScriptDir for html files etc. Update 0.6
      More Output logic added Added a detection for SAL aswell, since it seems to be inconsistent according to MSDN community and myself. Better feedback on what happend with parse Code cleanup / Removed old code /Tarre
      DllCall and Struct Generator V 0.6.zip
      DllCall and Struct Generator V 0.5.zip
      DllCall and Struct Generator V 0.4.zip
    • Trolleule
      [solved] DllCall on 64-Bit AutoIT Version not work properly
      By Trolleule
      Hey,
      i'm working with a dll which comes with Windows 10 (Pro x64) called dismapi.dll, which is located under C:\Windows\system32\dismapi.dll.
      I tested some of it's functions with my compiled script on Windows 10 (x86) and it worked properly, but when i run my script on my x64 system with
       directive set, it doesn't work anymore (AutoIT breaks on line 1255 in DISM.au3). Without this directive it works.
      Is there something i have to change to get it work? Thanks for help...(You can use my attach. If you use WIndows 10, it will work directly, on Windows 8 you might have to adjust the dism api path ($ghdismapi) in DISM.au3. On Windows 7, you will need Windows ADK to get DISM.) _DLLStructDisplay.au3 is only for debug.
      https://msdn.microsoft.com/de-de/library/windows/desktop/hh825837.aspx
       
      Misc.au3
      _DLLStructDisplay.au3
      DismConstants.au3
      DismExample.au3
      DISM.au3
    • toasterking
      DllCall Code Generator
      By toasterking
      DllCall is a powerful way to use AutoIt code to run functions that were created in other languages and are stored in shared libraries outside of AutoIt.  With DllCall, you can call Windows APIs directly, execute pieces of code that shipped with another vendor's product, and pass information between that code and your own script.
      However, DllCall is intended for the advanced user who is already familiar with how that stuff works.  That definitely isn't me, and I find the process of converting variable types, handling ByRefs with odd syntax, and keeping track of return values in an array cumbersome.  So I wrote a script to help me with it.  It should help beginners get started with DllCall too.  I was a little surprised that I didn't find something like this on the forum already.  Maybe the intended audience doesn't have the same trouble that I do, or maybe those who don't "get" it don't care enough to.  I'm hoping to bridge that gap a little.
      With this script, you can input the information from the MSDN documentation on a DLL function straight into the GUI and it will generate AutoIt code to call it and return its data.  You can choose whether to report debugging information via ConsoleWrite or MsgBox or neither.  It doesn't handle fancy things like DllStructs and callbacks, but it may help you get started.
      A great tutorial I used when I was starting to learn this stuff myself is Dealing with DLLs in AutoIt by Andreas Karlsson.  My script is intended as a programmatic approximation of the concepts on pages 1 to 8 of that document.  It is not a replacement for a good tutorial and self-learning.  I wrote it as a shortcut for my own future use because I only wanted to learn it once. :-)
      Here it is.  I'm curious to know what you all think.
      #include <ComboConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <ListViewConstants.au3> #include <WindowsConstants.au3> #Region ### START Koda GUI section ### Form=C:\Library\Repositories #NO BACKUP#\Google Drive - Toastyking\Development\Snippet Library\AutoIt\CodeWizards\DllCallCodegen\FormMain.kxf $FormMain = GUICreate("DllCall Code Generator", 825, 421) $Label1 = GUICtrlCreateLabel("DLL Name", 16, 32, 55, 17) $InputDll = GUICtrlCreateInput("user32.dll", 120, 29, 121, 21) $Label2 = GUICtrlCreateLabel("Function Name", 16, 59, 76, 17) $InputFunc = GUICtrlCreateInput("", 120, 56, 121, 21) $RadioFuncAnsi = GUICtrlCreateRadio("ANSI", 256, 57, 49, 17) $RadioFuncUnicode = GUICtrlCreateRadio("Unicode", 312, 56, 73, 17) GUICtrlSetState(-1, $GUI_CHECKED) $Label3 = GUICtrlCreateLabel("Return Type", 16, 85, 63, 17) $InputReturnType = GUICtrlCreateInput("int", 120, 82, 121, 21) $ComboCallConv = GUICtrlCreateCombo("", 120, 110, 121, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL)) GUICtrlSetData(-1, "stdcall|cdecl") $ListViewParams = GUICtrlCreateListView("#|Type|Value|Method", 16, 245, 362, 126, BitOR($GUI_SS_DEFAULT_LISTVIEW,$LVS_NOSORTHEADER)) GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 50) GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 50) GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 2, 50) GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 3, 50) $Label4 = GUICtrlCreateLabel("For all types, use the type name specified on MSDN.", 16, 8, 251, 17) $Label5 = GUICtrlCreateLabel("Parameters:", 16, 136, 60, 17) $Label6 = GUICtrlCreateLabel("Type", 24, 157, 28, 17) $Label7 = GUICtrlCreateLabel("Value (0 for null)", 152, 157, 80, 17) $Label8 = GUICtrlCreateLabel("Method", 280, 157, 39, 17) $InputParamType = GUICtrlCreateInput("", 24, 176, 121, 21) $InputParamValue = GUICtrlCreateInput("", 152, 176, 121, 21) $ComboParamByref = GUICtrlCreateCombo("", 280, 176, 89, 25, BitOR($CBS_DROPDOWNLIST,$CBS_AUTOHSCROLL)) GUICtrlSetData(-1, "Input/ByVal|Output/ByRef") $ButtonParamAdd = GUICtrlCreateButton("Add Parameter", 24, 213, 91, 25) $ButtonParamDelete = GUICtrlCreateButton("Clear All", 128, 213, 107, 25) $Label9 = GUICtrlCreateLabel("Calling convention", 16, 112, 91, 17) $Label10 = GUICtrlCreateLabel("Generated AutoIt code:", 409, 8, 115, 17) $EditCode = GUICtrlCreateEdit("", 408, 29, 401, 342, BitOR($ES_READONLY,$WS_HSCROLL,$WS_VSCROLL)) $ButtonTest = GUICtrlCreateButton("Test Code", 344, 381, 107, 25) $ButtonCopy = GUICtrlCreateButton("Copy to Clipboard", 464, 381, 107, 25) $ButtonInsert = GUICtrlCreateButton("Insert in SciTE", 586, 381, 107, 25) $ButtonGenonly = GUICtrlCreateButton("Nothing Else", 704, 381, 107, 25) $ComboOutput = GUICtrlCreateCombo("", 98, 383, 121, 25, BitOR($CBS_DROPDOWNLIST,$CBS_AUTOHSCROLL)) GUICtrlSetData(-1, "ConsoleWrite|MsgBox|$vDllCallReturn only") $Label11 = GUICtrlCreateLabel("Output method:", 16, 387, 77, 17) $Label12 = GUICtrlCreateLabel("Generate code and:", 232, 387, 99, 17) ;~ GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### Global $aParams[1][3] GUICtrlSetData($ComboParamByref,"Input/ByVal") GUICtrlSetData($ComboOutput,"ConsoleWrite") GUICtrlSetData($ComboCallConv,"stdcall") GUISetState(@SW_SHOW) While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $ButtonParamAdd _ConvertType(GUICtrlRead($InputParamType)) ; Use the parameter type selected If @error Then If MsgBox(49,"Unrecognized Type","Unrecognized parameter type """ & GUICtrlRead($InputParamType) & """. Make sure you are using an MSDN return type." & @CRLF & @CRLF & "If you are certain that the parameter type is correct and you happen to know the equivalent AutoIt parameter type, click OK. You will be prompted later for the AutoIt parameter type.",0,$FormMain) = 2 Then ContinueLoop EndIf If GUICtrlRead($ComboParamByref) = "Output/ByRef" And StringLeft(GUICtrlRead($InputParamValue),1) <> "$" Then MsgBox(48,"Error","To use this parameter value as a ByRef, you must specify the name of a variable used in your AutoIt script, which must begin with a '$' symbol.",0,$FormMain) ContinueLoop EndIf ; Input seems okay; proceed. ReDim $aParams[UBound($aParams) + 1][3] ; Add a "row" to the array $aParams[UBound($aParams) - 1][0] = GUICtrlRead($InputParamType) $aParams[UBound($aParams) - 1][1] = GUICtrlRead($InputParamValue) $aParams[UBound($aParams) - 1][2] = GUICtrlRead($ComboParamByref) ; Clear input fields and refocus GUICtrlSetData($InputParamType,"") GUICtrlSetData($InputParamValue,"") GUICtrlSetData($ComboParamByref,"Input/ByVal") GUICtrlCreateListViewItem(UBound($aParams) - 1 & "|" & $aParams[UBound($aParams) - 1][0] & "|" & $aParams[UBound($aParams) - 1][1] & "|" & $aParams[UBound($aParams) - 1][2],$ListViewParams) ControlFocus($FormMain,"",$InputParamType) Case $ButtonParamDelete ; Delete all items _GUICtrlListView_DeleteAllItems($ListViewParams) ReDim $aParams[1][3] Case $ButtonTest $sDllCallOut = _GenerateCode("MsgBox") ; Always use MsgBox for output when generating for testing. GUICtrlSetData($EditCode,$sDllCallOut) If $sDllCallOut <> "" Then GUISetState(@SW_DISABLE,$FormMain) GUICtrlSetData($ButtonTest,"Executing...") FileDelete(@TempDir & "\DllCallExec.au3") FileWrite(@TempDir & "\DllCallExec.au3",$sDllCallOut); Write code to temporary file to be executed. $nExit = RunWait(@AutoItExe & ' /AutoIt3ExecuteScript "' & @TempDir & '\DllCallExec.au3"',@TempDir) ; Execute the temporary file. If $nExit <> 0 Then Switch $nExit Case 1 MsgBox(16,"DLL Code Generator","The AutoIt interpreter encountered an error while parsing or executing the generated code." & @CRLF & "Exit code: " & $nExit,0,$FormMain) Case Else MsgBox(16,"DLL Code Generator","There was a problem with the DllCall (possibly incorrect parameters). The AutoIt interpreter ended unexpectedly." & @CRLF & "Exit code: " & $nExit,0,$FormMain) EndSwitch EndIf GUICtrlSetData($ButtonTest,"Test Code") GUISetState(@SW_ENABLE,$FormMain) FileDelete(@TempDir & "\DllCallExec.au3") WinActivate($FormMain) EndIf Case $ButtonGenonly $sDllCallOut = _GenerateCode(GUICtrlRead($ComboOutput)) GUICtrlSetData($EditCode,$sDllCallOut) Case $ButtonCopy $sDllCallOut = _GenerateCode(GUICtrlRead($ComboOutput)) GUICtrlSetData($EditCode,$sDllCallOut) If ClipPut($sDllCallOut) Then ToolTip("Copied!") Else ToolTip("Copy failed!") EndIf Sleep(1000) ToolTip("") Case $ButtonInsert $sDllCallOut = _GenerateCode(GUICtrlRead($ComboOutput)) GUICtrlSetData($EditCode,$sDllCallOut) If ClipPut($sDllCallOut) Then ControlSend("[CLASS:SciTEWindow]","","Scintilla1","^v") Case $InputFunc If StringRight(GUICtrlRead($InputFunc),1) == "W" Then ; Check if last character of entered function name is a capital "W" GUICtrlSetState($RadioFuncUnicode,$GUI_CHECKED) Else GUICtrlSetState($RadioFuncAnsi,$GUI_CHECKED) EndIf Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func _GenerateCode($sOutputType = "") Local $sArch, $sReturnTypeOut, $sParamTypeOut, $sDllFuncName, $sDllCallOut, $sCmdOutStart, $sCmdOutEnd, $fOutputGen Switch $sOutputType Case "ConsoleWrite" $sCmdOutStart = 'ConsoleWrite(' $sCmdOutEnd = ' & @CRLF)' $fOutputGen = 1 Case "MsgBox" $sCmdOutStart = 'MsgBox(0,"DllCall Code Generator",' $sCmdOutEnd = ')' $fOutputGen = 1 Case Else $sCmdOutStart = "" $sCmdOutEnd = "" $fOutputGen = 0 EndSwitch If GUICtrlRead($RadioFuncAnsi) = $GUI_CHECKED Then $sArch = "a" If GUICtrlRead($RadioFuncUnicode) = $GUI_CHECKED Then $sArch = "w" $sDllFuncName = GUICtrlRead($InputDll) & "/" & GUICtrlRead($InputFunc) $sReturnTypeOut = _ConvertType(GUICtrlRead($InputReturnType)) If @error Then $sReturnTypeOut = InputBox("Unrecognized Type","Unrecognized return type """ & GUICtrlRead($InputReturnType) & """. Make sure you are using an MSDN return type." & @CRLF & @CRLF & "If you are certain that the return type is correct and you happen to know the equivalent AutoIt return type, you may enter the AutoIt return type here.","","",Default,220,Default,Default,0,$FormMain) If $sReturnTypeOut = "" Then Return SetError(1,0,"") EndIf $sReturnTypeOut = _ConvertTypeArch($sReturnTypeOut,$sArch) If GUICtrlRead($ComboCallConv) <> "stdcall" Then $sReturnTypeOut &= ':' & GUICtrlRead($ComboCallConv) $sDllCallOut = 'Local $aDllCallReturn,$vDllCallReturn' $sDllCallOut = '$aDllCallReturn = DllCall("' & GUICtrlRead($InputDll) & '","' & $sReturnTypeOut & '","' & GUICtrlRead($InputFunc) & '"' If UBound($aParams) > 1 Then For $x = 1 To UBound($aParams) - 1 $sParamTypeOut = '' $sParamTypeOut = _ConvertTypeArch(_ConvertType($aParams[$x][0]),$sArch) If $sParamTypeOut = '' Then $sParamTypeOut = InputBox("Unrecognized Type","Unrecognized parameter type """ & $aParams[$x][0] & """. Make sure you are using an MSDN parameter type." & @CRLF & @CRLF & "If you are certain that the parameter type is correct and you happen to know the equivalent AutoIt parameter type, you may enter the AutoIt parameter type here.","","",Default,220,Default,Default,0,$FormMain) If $sParamTypeOut = "" Then Return(SetError(1,0,"")) If StringRight($sParamTypeOut,1) = "*" Then $sParamTypeOut = StringTrimRight($sParamTypeOut,1) ; If the user added an asterisk to the end of the parameter type, remove it; it will be added back later if necessary. EndIf $sDllCallOut &= ',"' & $sParamTypeOut If $aParams[$x][2] = "Output/ByRef" Then $sDllCallOut &= '*' $sDllCallOut &= '","' & $aParams[$x][1] & '"' Next EndIf $sDllCallOut &= ')' & @CRLF ; Generate code to check for DllCall execution error. If $fOutputGen = 1 Then $sDllCallOut &= _ 'If @error Then' & @CRLF & _ ' Switch @error' & @CRLF & _ ' Case 1' & @CRLF & _ ' ' & $sCmdOutStart & '"DllCall error (' & $sDllFuncName & '): Unable to use the DLL file. Possibly a problem with the parameters."' & $sCmdOutEnd & @CRLF & _ ' Case 2' & @CRLF & _ ' ' & $sCmdOutStart & '"DllCall error (' & $sDllFuncName & '): Unknown return type."' & $sCmdOutEnd & @CRLF & _ ' Case 3' & @CRLF & _ ' ' & $sCmdOutStart & '"DllCall error (' & $sDllFuncName & '): Function not found in DLL file. Remember that function names are case sensitive."' & $sCmdOutEnd & @CRLF & _ ' Case 4' & @CRLF & _ ' ' & $sCmdOutStart & '"DllCall error (' & $sDllFuncName & '): Incorrect number of parameters."' & $sCmdOutEnd & @CRLF & _ ' Case 5' & @CRLF & _ ' ' & $sCmdOutStart & '"DllCall error (' & $sDllFuncName & '): Bad parameter."' & $sCmdOutEnd & @CRLF & _ ' Case Else' & @CRLF & _ ' ' & $sCmdOutStart & '"DllCall error (' & $sDllFuncName & '): Unknown/unspecified error."' & $sCmdOutEnd & @CRLF & _ ' EndSwitch' & @CRLF & _ ' $vDllCallReturn = ""' & @CRLF & _ 'Else' & @CRLF If $fOutputGen = 1 Then $sDllCallOut &= ' ' $sDllCallOut &= '$vDllCallReturn = $aDllCallReturn[0]' & @CRLF ; Generate code to assign returned ByRef values back to their AutoIt variables. If UBound($aParams) > 1 Then For $x = 1 To UBound($aParams) - 1 If $aParams[$x][2] = "Output/ByRef" Then If $fOutputGen = 1 Then $sDllCallOut &= ' ' $sDllCallOut &= $aParams[$x][1] & ' = $aDllCallReturn[' & $x & ']' & @CRLF EndIf Next EndIf ; Generate code to output values of the variables passed to the DllCall via ByRef. If $fOutputGen = 1 Then $sDllCallOut &= ' ' & $sCmdOutStart If UBound($aParams) > 1 Then For $x = 1 To UBound($aParams) - 1 If $aParams[$x][2] = "Output/ByRef" Then $sDllCallOut &= '"' & $aParams[$x][1] & ' = " & ' & $aParams[$x][1] & ' & @CRLF & ' EndIf Next EndIf $sDllCallOut &= '"DllCall return value: " & $vDllCallReturn' & $sCmdOutEnd & @CRLF $sDllCallOut &= "EndIf" & @CRLF EndIf Return $sDllCallOut EndFunc ; Convert the MSDN variable type to AutoIt variable type Func _ConvertType($MSDN_Type) Switch $MSDN_Type Case 'ATOM' Return 'WORD' Case 'BOOL' Return 'BOOL' Case 'BOOLEAN' Return 'BOOLEAN' Case 'BYTE' Return 'BYTE' Case 'CHAR' Return 'str' Case 'COLORREF' Return 'DWORD' Case 'CONST' Return 'const' Case 'DWORD' Return 'DWORD' Case 'DWORDLONG' Return 'ULONG' Case 'DWORD_PTR' Return 'DWORD_PTR' Case 'DWORD32' Return 'UINT' Case 'DWORD64' Return 'INT64' Case 'FLOAT' Return 'FLOAT' Case 'HACCEL' Return 'HANDLE' Case 'HALF_PTR' Return 'ptr' Case 'HANDLE' Return 'HANDLE' Case 'HBITMAP' Return 'HANDLE' Case 'HBRUSH' Return 'HANDLE' Case 'HCONV' Return 'HANDLE' Case 'HCONVLIST' Return 'HANDLE' Case 'HCURSOR' Return 'HICON' Case 'HDC' Return 'HANDLE' Case 'HDDEDATA' Return 'HANDLE' Case 'HDESK' Return 'HANDLE' Case 'HDROP' Return 'HANDLE' Case 'HDWP' Return 'HANDLE' Case 'HENHMETAFILE' Return 'HANDLE' Case 'HFILE' Return 'int' Case 'HFONT' Return 'HANDLE' Case 'HGIDOBJ' Return 'HANDLE' Case 'HGLOBAL' Return 'HANDLE' Case 'HHOOK' Return 'HANDLE' Case 'HICON' Return 'HANDLE' Case 'HINSTANCE' Return 'HANDLE' Case 'HKEY' Return 'HANDLE' Case 'HKL' Return 'HANDLE' Case 'HLOCAL' Return 'HANDLE' Case 'HMENU' Return 'HANDLE' Case 'HMETAFILE' Return 'HANDLE' Case 'HMODULE' Return 'HANDLE' Case 'HMONITOR' Return 'HANDLE' Case 'HPALETTE' Return 'HANDLE' Case 'HPEN' Return 'HANDLE' Case 'HRESULT' Return 'LONG' Case 'HRGN' Return 'HANDLE' Case 'HRSRC' Return 'HANDLE' Case 'HSZ' Return 'HANDLE' Case 'HWINSTA' Return 'HANDLE' Case 'HWND' Return 'HWND' Case 'INT_PTR' Return 'INT_PTR' Case 'INT32' Return 'int' Case 'INT' Return 'int' Case 'INT64' Return 'INT64' Case 'LANGID' Return 'WORD' Case 'LARGE_INTEGER' Return 'INT64' Case 'LCID' Return 'DWORD' Case 'LGRPID' Return 'DWORD' Case 'LONG' Return 'LONG' Case 'LONGLONG' Return 'INT64' Case 'LONG_PTR' Return 'LONG_PTR' Case 'LONG32' Return 'int' Case 'LONG64' Return 'INT64' Case 'LPARAM' Return 'LPARAM' Case 'LPBOOL' Return 'int' Case 'LPBYTE' Return 'int' Case 'LPCOLORREF' Return 'DWORD' Case 'LPCSTR' Return 'str' Case 'LPCTSTR' Return 'str' Case 'LPCWSTR' Return 'wstr' Case 'LPDWORD' Return 'DWORD' Case 'LPHANDLE' Return 'HANDLE' Case 'LPINT' Return 'int' Case 'LPLONG' Return 'long' Case 'LPSTR' Return 'str' Case 'LPTSTR' Return 'str' Case 'LPVOID' Return 'ptr' Case 'LPWORD' Return 'WORD' Case 'LPWSTR' Return 'wstr' Case 'LRESULT' Return 'LRESULT' Case 'PBOOL' Return 'BOOL' Case 'PBOOLEAN' Return 'BOOLEAN' Case 'PBYTE' Return 'BYTE' Case 'PCHAR' Return 'str' Case 'PCSTR' Return 'str' Case 'PCTSTR' Return 'str' Case 'PCWSTR' Return 'wstr' Case 'PDWORD' Return 'DWORD' Case 'PDWORDLONG' Return 'UINT64' Case 'PDWORD_PTR' Return 'DWORD_PTR' Case 'PDWORD32' Return 'UINT' Case 'PDWORD64' Return 'INT64' Case 'PFLOAT' Return 'FLOAT' Case 'PHALF_PTR' Return 'ptr' Case 'PHANDLE' Return 'HANDLE' Case 'PHKEY' Return 'HANDLE' Case 'PINT' Return 'int' Case 'PINT_PTR' Return 'INT_PTR' Case 'PINT32' Return 'int' Case 'PINT64' Return 'INT64' Case 'PLCID' Return 'DWORD' Case 'PLONG' Return 'LONG' Case 'PLONGLONG' Return 'INT64' Case 'PLONG_PTR' Return 'LONG_PTR' Case 'PLONG32' Return 'long' Case 'PLONG64' Return 'INT64' Case 'POINTER_32' Return 'ptr' Case 'POINTER_64' Return 'ptr' Case 'POINTER_SIGNED' Return 'ptr' Case 'POINTER_UNSIGNED' Return 'ULONG_PTR' Case 'PSHORT' Return 'SHORT' Case 'PSIZE_T' Return 'ULONG_PTR' Case 'PSSIZE_T' Return 'LONG_PTR' Case 'PSTR' Return 'str' Case 'PTBYTE' Return 'BYTE' Case 'PTCHAR' Return 'wstr' Case 'PTSTR' Return 'wstr' Case 'PUCHAR' Return 'BYTE' Case 'PUHALF_PTR' Return 'ptr' Case 'PUINT' Return 'UINT' Case 'PUINT_PTR' Return 'UINT_PTR' Case 'PUINT32' Return 'UINT' Case 'PUINT64' Return 'UINT64' Case 'PULARGE_INTEGER' Return 'UINT64' Case 'PULONG' Return 'ULONG' Case 'PULONGLONG' Return 'UINT64' Case 'PULONG_PTR' Return 'ULONG_PTR' Case 'PULONG32' Return 'ULONG' Case 'PULONG64' Return 'UINT64' Case 'PUSHORT' Return 'USHORT' Case 'PVOID' Return 'ptr' Case 'PWCHAR' Return 'wstr' Case 'PWORD' Return 'WORD' Case 'PWSTR' Return 'wstr' Case 'SC_HANDLE' Return 'HANDLE' Case 'SC_LOCK' Return 'ptr' Case 'SERVICE_STATUS_HANDLE' Return 'HANDLE' Case 'SHORT' Return 'SHORT' Case 'SIZE_T' Return 'ULONG_PTR' Case 'SSIZE_T' Return 'LONG_PTR' Case 'TBYTE' Return 'wstr' Case 'TCHAR' Return 'wstr' Case 'UCHAR' Return 'BYTE' Case 'UHALF_PTR' Return 'ptr' Case 'UINT' Return 'UINT' Case 'UINT_PTR' Return 'UINT_PTR' Case 'UINT32' Return 'UINT' Case 'UINT64' Return 'UINT64' Case 'ULARGE_INTEGER' Return 'UINT64' Case 'ULONG' Return 'ULONG' Case 'ULONGLONG' Return 'UINT64' Case 'ULONG_PTR' Return 'ULONG_PTR' Case 'ULONG32' Return 'ULONG' Case 'ULONG64' Return 'UINT64' Case 'UNICODE_STRING' Return 'ptr' Case 'USHORT' Return 'USHORT' Case 'USN' Return 'INT64' Case 'VOID' Return 'none' Case 'WCHAR' Return 'wstr' Case 'WORD' Return 'WORD' Case 'WPARAM' Return 'WPARAM' Case Else SetError(1) Return "" EndSwitch EndFunc ;==> ; Some variable types should be converted from their ANSI to Unicode types or vice versa. Func _ConvertTypeArch($MSDN_Type,$sArch) Switch $MSDN_Type Case 'STR' If $sArch = "a" Then Return "str" If $sArch = "w" Then Return "wstr" Case 'WSTR' If $sArch = "a" Then Return "str" If $sArch = "w" Then Return "wstr" Case Else Return $MSDN_Type EndSwitch EndFunc Here is an example:
      Function: GetDiskFreeSpaceW (MSDN page: http://msdn.microsoft.com/en-us/library/aa364935(VS.85).aspx)
      Input this:

      Click Test Code, and get this:

      Click Insert in SciTE to insert the code into your script.
      Updated 2014/01/28:  
      Edit 2015/11/25: Fixed broken link