OldNoob

Help with DLLCALL - Kernel32.dll

11 posts in this topic

 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

#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

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

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

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

  • Similar Content

    • cheeroke
      By cheeroke
      Hi all,
      I got this code and would like to be able to change Baud Rate and instead of sending character by character i would like to be able (if possible) to send whole string. But i don't know how to change it.
      I am taking input from file and processing whole line (this is done in FilesHandling.au3).
      To execute this i am just calling SendData("FileName", int) in "main" script.
      Any help very appreciated.
      #include <WinAPI.au3> #include <Array.au3> #include "FilesHandling.au3" ;init DLL function, we need handle to call the function $h = DllCall("Kernel32.dll", "hwnd", "CreateFile", "str", "\\.\COM19", "int", BitOR($GENERIC_READ,$GENERIC_WRITE), "int", 0, "ptr", 0, "int", $OPEN_EXISTING, "int", $FILE_ATTRIBUTE_NORMAL, "int", 0) $handle=$h[0] Func SendData($FileName, $LineNumber) ;string to be send $c = readFile($FileName, $LineNumber) $cLenght = StringLen($c) $aArray = StringSplit($c, "") ;_ArrayDisplay($aArray, "", Default, 64) For $i = 1 To $cLenght writeChar($handle, $aArray[$i], $cLenght) Next ;move to next line writeChar($handle, @CR,1) EndFunc ;write a single char func writeChar($handle,$c,) $stString = DLLStructCreate("char str") $lpNumberOfBytesWritten = 0 DllStructSetData($stString, 1, $c) $res = _WinAPI_WriteFile($handle, DllStructGetPtr($stString, "str"), 1,$lpNumberOfBytesWritten) if ($res<>true) then ConsoleWrite ( _WinAPI_GetLastErrorMessage() & @LF) EndIf EndFunc  
    • luckyluke
      By luckyluke
      Hello,
      Im trying to read the output from CMD using Dllcall, here is my code:
      #include <WinAPI.au3> #include <array.au3> Global Const $STD_OUTPUT_HANDLE = -11 Global Const $_CONSOLE_SCREEN_BUFFER_INFO = _ "struct;int dwSizeX;" & _ "short dwSizeY;" & _ "short dwCursorPositionX;" & _ "short dwCursorPositionY;" & _ "short wAttributes;" & _ "short Left;" & _ "short Top;" & _ "short Right;" & _ "short Bottom;" & _ "short dwMaximumWindowSizeX;" & _ "short dwMaximumWindowSizeY;endstruct" $pCmd = Run( "cmd.exe" ) Sleep(1000) $hCmd = WinGetHandle("") ConsoleWrite('handle:' & $hCmd & @CRLF) $aRet = DllCall("kernel32.dll", "int", "AttachConsole", "dword", $pCmd) ;_ArrayDisplay($aRet) If $aRet[0] <> 0 Then $vHandle_data='' $vHandle='' $vHandle_data = DllStructCreate($_CONSOLE_SCREEN_BUFFER_INFO) ; Screen Buffer structure $aRet1 = DllCall("kernel32.dll", "hwnd", "GetStdHandle", "dword", $STD_OUTPUT_HANDLE) if not @error Then $vHandle = $aRet1[0] $aRet = DllCall("kernel32.dll", "int", "GetConsoleScreenBufferInfo", "hwnd", $vHandle, _ "ptr", $vHandle_data) MsgBox(0, '1',DllStructGetData($vHandle_data, 'dwSizeX') & _WinAPI_GetLastErrorMessage()) EndIf It did not work, i got the message 'The handle is invalid'. Please help?
      Thank you in advance!
    • MazeM
      By MazeM
      Hi
      here's another UDF for the serial port. It is very similar to CommAPI using kernel32.dll, but all code is packed into a single file without any dependencies, not even using WinAPI.au3. It differs from existing UDF that it doesn't allow a timeout when reading, instead it always returns immediately, either with the requested amount ob bytes read or with a failure status. And of course there is a function provided to query the amount of available bytes in the receive buffer. The reason behind this design decision: You can do 1000 other things in the main loop while checking from time to time if enough data bytes arrived. There's no point to block the program waiting for the serial port.
      It is currently a work-in-progress, as I didn't test all functions yet. The code was developed and tested on Windows 7 64 bit.  The ComUDF-Tests.au3 shows some tests and basic usage of the UDF. Maybe there's no reason to use this UDF, given the existence of the others UDFs, but I did it to get to know DllCall better - I use structs no only to pass but also to get data back (I don't use the array returned by DllCall to read that data, unless required). You're welcome to test it on older and newer Windows versions.
      Here's a list of the implemented functions:
      ; _ComListPorts ; _ComOpenPort ; _ComSetTimeouts ; _ComClosePort ; ; _ComSetBreak ; _ComClearBreak ; _ComGetInputcount ; _ComGetOutputcount ; _ComClearOutputBuffer ; _ComClearInputBuffer ; ; _ComSendByte ; _ComReadByte ; _ComSendBinary ; _ComReadBinary ; ; _ComSendChar ; _ComReadChar ; _ComSendCharArray ; _ComReadCharArray ; _ComSendString ; _ComReadString ; ; __ComClearCommError ; __PurgeComm Maze
       
      ComUDF.au3
      ComUDF-Tests.au3
    • astrionn
      By astrionn
      So I had this Idea of creating a tooltip which shows me my ping.
      That itself was made quickly and I thought too add a couple features.
      I want the tooltip background to be a different color depending on the ping. (good ping is green, medium ping is yellow,...)
      So how do I color in a tooltip? google brought me to this: 
       
      where in the comments I found this:
      $s = "LOW" ToolTip($s, 0, 0, "Battery Information");, $icon) $H_TOOLTIP1 = WinGetHandle($s) DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", $H_TOOLTIP1, "wstr", "", "wstr", "") DllCall("user32.dll", "int", "SendMessage", "hwnd", $H_TOOLTIP1, "int", 1043, "int", 2552550, "int", 0) Sleep(1000) Which I then used in my code with different color codes... Trial and Error brought me these that I wanted to use:
       
      The Problem is if I loop through my code it only sets the color for the 1st loop and then sticks to it.
      The real problem is tho that I don't exactly understand the dllcalls... And I guess that's why it isn't working
      So if someone would be so awesome to explain to me how they work, or at least can give me a list of these parameters then I would really appreciate that and learn something new
      Obviously a solution to my problem is awesome aswell ^^
      I run this under Windows 8.1
      There is my code in a paste.
      https://pastebin.com/q525f7mS