Jump to content
Sign in to follow this  
OldNoob

Help with DLLCALL - Kernel32.dll

Recommended Posts

 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

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

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
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

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

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

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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By IndianSage
      Hi,
      My AutoIt script is as folllows:
      ;use for calling function add2NosA in dll ;Local $vNo1 = 33 ;Local $vNo2 = 11 ;use for calling function sortNos in dll Local $vNo1 = [11,7,9] Local $vNo2 = [1,3,2] ; _ArrayDisplay($vNo1, "vNo1 display") ; _ArrayDisplay($vNo2, "vNo2 display") ;Local $hWnd = DllOpen("E:\CV-Dell-1\autoit3\myComObj1.dll") Local $hWnd = ObjCreate("myComObj1.clsMath") if (@error) Then MsgBox (0, "Error", "Error1 = " & @error) Exit EndIf ;function call method - DllCall with function name ;Local $aRes = DllCall($hWnd, "int", "addNosA", "int", $vNo1, "int", $vNo2) ;Local $aRes = DllCall($hWnd, "Ptr", "sortNos", "Array", $vNo1, "Array", $vNo2) ;function call method - $hWnd.<function name> ;Local $aRes = $hWnd.add2NosA($vNo1, $vNo2) ; this works fine with ObjCreate Local $aRes = $hWnd.sortNos($vNo1, $vNo2) if (@error) Then MsgBox (0, "Error", "Error2 = " & @error) DllClose($hWnd) Exit EndIf ;use appropriate msgbox ;MsgBox(0,"Result", "Result = " & $vNo1[0]) MsgBox(0,"Result", "Result = " & $aRes) _ArrayDisplay($vNo1, "vNo1 display") _ArrayDisplay($aRes , "aRes display") DllClose($hWnd) My VB.Net - ClassLibrary - Dll - COM obj is as follows - has 2 functions - add2NosA and sortNos:
      <ComClass(clsMath.ClassId, clsMath.InterfaceId, clsMath.EventsId)> Public Class clsMath Public Const ClassId As String = "3A42F85E-24C8-4BAA-91B5-AE56C4683C13" Public Const InterfaceId As String = "D99D7C79-2BA7-4A33-B7BC-9B7F19FDF828" Public Const EventsId As String = "CA128AC4-580C-4112-9EAD-8D1599E3F37A" Public Sub New() MyBase.New() End Sub Public Function add2NosA(ByVal no1 As Integer, ByVal no2 As Integer) As Integer Return (no1 + no2) End Function Public Sub sortNos(ByRef no1 As Array, ByRef no2 As Array) Array.Sort(no1) no2 = no1 End Sub End Class  Over all I tried various 8 options mentioned in the attached Excel file - with only 1 combination working.
      Overall could not make Array returned capture in AutoIt script. 
      Can someone help please?
      Thanks in  advance.
      Options-Tried-Matrix-Results.xlsx
    • By IndianSage
      I have create a function in FreeBasic like below:
      Extern "Windows-MS" Type tA f1 As Integer f2 As Integer End Type Public Function _switchOrder(ByVal no1 As Integer, ByVal no2 As Integer) As tA Export Dim result As Integer Dim taa As tA taa.f1 = no2 taa.f2 = no1 Return taa End Function End Extern Caller AutoIt code is:
      #include <MsgBoxConstants.au3> Global Const $sTag_ftdi_version_info="struct; int no1a; int no2a; endstruct" Local $aRet=DllCall("Math1.dll","Ptr","_switchOrder", "Int", 10, "Int", 30) ;MsgBox (0,"",@error & "-" & $aRet[0] & "-" & $aRet[1]& "-" & $aRet[2]) Local $t_ftdi_version_info=DllStructCreate($sTag_ftdi_version_info,$aRet[0]) MsgBox (0,"msg1=",@error & "---" & $aRet[0] & "-" & $aRet[1]& "-" & $aRet[2]) ;Local $retData1 = DllStructGetData($t_ftdi_version_info,"",1) Local $retData1 = DllStructGetData($t_ftdi_version_info,"no1a") MsgBox (0,"msg2=",@error & "--" & $retData1) ;Local $retData1 = DllStructGetData($t_ftdi_version_info,"",2) Local $retData1 = DllStructGetData($t_ftdi_version_info,"no2a") MsgBox (0,"msg2=",@error & "--" & $retData1) ;ConsoleWrite(DllStructGetData($t_ftdi_version_info,"",2) & "--" & @error) ;ConsoleWrite(DllStructGetData($t_ftdi_version_info,"no2a") & @CRLF) ;ConsoleWrite(DllStructGetData($tversion_str,1) & @CRLF) Getting error 2 for DllStructGetData or it give Close Application AutoIt popup message. 
      Certainly DllCall is not returning pointer to the Structure in $aRet[0] hence issue.
      Can someone help me fix this please?
      Thanks in advance.
       
       
    • By xYuri
      This simple dllcall gives me error 5, access denied,
      Func _WinAPI_VkKeyScan($__key) _WinAPI_SetLastError(0) $res = DllCall('User32.dll', 'SHORT', 'VkKeyScan', 'CHAR', $__key) _xConsole('res: '&$res) $_LastErr = _WinAPI_GetLastError() If $_LastErr <> 0 Then _xConsole('Err: {' & $_LastErr & '}> ' & _WinAPI_GetLastErrorMessage()) Return $res EndFunc Am i doing something wrong?
      Also tried VkKeyScanA and W
      Edit:
      I want to send `:` via PostMessage() WM_KEYDOWN
    • By Skysnake
      This is relevant
      From here https://stackoverflow.com/questions/3454315/is-it-possible-to-pin-a-dll-in-memory-to-prevent-unloading
      I use several UDFs on the Forum to do various things.  Those UDFs work very well.
      Effectively the UDFs are DLL wrappers, that make it possible to access DLL functions easily without the long hard slog of DLLCall() every time.
      However, I have now run into the issue that multiple UDF DLLCalls are slow. Not mind numbingly slow, but slow enough to become noticeable with a large of repeated function calls.
      So I was wondering, is it possible to "load a DLL into memory" and leave it there for the duration of my script's lifetime, avoid repeated DLL on-disk reads with a persistent in memory DLL?
      From Microsoft
      https://docs.microsoft.com/en-us/windows/desktop/dlls/about-dynamic-link-libraries
      Looks like what I want to do is: load-time dynamic linking,
      So next question, (a) how do I do this with AutoIt (b) How would this impact on standard AutoIt type DLL calls?
       
      The point is speed.  Is there a different approach?
      Or am I barking up the wrong tree?
      Skysnake
    • By supersonic
      Hi -
      Currently I'm playing around with Windows Credential Manager. I'm trying to access it with DllCall("advapi32.dll", ...) using the functions 'CredWriteW', 'CredReadW' and 'CredDeleteW'. All well. Another function I have to deal with is 'CredEnumerateW': https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credenumeratew/ .
      That's the test code I have so far:
      #include <Array.au3> #include <String.au3> Local $tCredentialsCount = DllStructCreate("DWORD;") Local $tPointerToArrayOfPointers = DllStructCreate("PTR;") ; Local $tPointerToArrayOfPointers = DllStructCreate(_StringRepeat("PTR;", 200)) ; ??? Local $aResult = DllCall("advapi32.dll", "BOOL", "CredEnumerateW", _ "WSTR", Null, "DWORD", 1, "DWORD", DllStructGetPtr($tCredentialsCount), "PTR", DllStructGetPtr($tPointerToArrayOfPointers)) If (Not @error) Then Local $iCredentialsCount = DllStructGetData($tCredentialsCount, 1) _ArrayDisplay($aResult, $iCredentialsCount) Local $hPointerToArrayOfPointers = DllStructGetData($tPointerToArrayOfPointers, 1) MsgBox(0, "$hPointerToArrayOfPointers", $hPointerToArrayOfPointers) ; Fails... For $i = 1 To 10 ; $iCredentialsCount MsgBox(0, $i & "___" & (($i * 2) - 1), DllStructGetData($tPointerToArrayOfPointers, ($i * 2) - 1)) Next $tCredentialsCount = 0 $tPointerToArrayOfPointers = 0 DllCall("advapi32.dll", "NONE", "CredFreeW", "PTR", $hPointerToArrayOfPointers) EndIf The DllCall seems to function properly - I get a valid count of credentials (on my computer ~ 133) and a pointer "to array of pointers".
      What is meant by "array of pointers"?
      Microsoft says: Pointer to an array of pointers to credentials. The returned credential is a single allocated block. Any pointers contained within the buffer are pointers to locations within this single allocated block.
      How to access these pointers... Contained within the buffer???
      Any information you can provide me would be greatly appreciated.
×
×
  • Create New...