Jump to content
Trolleule

[solved] DllCall on 64-Bit AutoIT Version not work properly

Recommended Posts

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

#AutoIt3Wrapper_UseX64=y

 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

Edited by Trolleule

Share this post


Link to post
Share on other sites

AutoIT breaks on line 1255 in DISM.au3

Your description is very vague. What you you mean by "breaks"? Does it give an error message? Crash? Or ???

Also, this line is commented code. Post the section of code that is problematic so that we can see exactly which line the error is occurring.

Share this post


Link to post
Share on other sites

sorry, it's line 1251. AutoIT crashes on this line, where i try to read the pointer in a array of WCHAR.

MsgBox(0, "ProductName", GetPCWSTR($tImageInfo_sub, "ProductName"))

 The function GetPCWSTR can be found in Misc.au3 and looks like:

Func GetPCWSTR(ByRef $struct, $sElementName) ; avoids memory access conflicts
    Local $char_struct
    Local $anz = 0 ; counter for signs
    Local $ptr = DllStructGetData($struct, $sElementName) ; ptr
    Do
        $char_struct = DllStructCreate("WCHAR", $ptr + $anz) ; get memory location
        $anz += 2
    Until DllStructGetData($char_struct, 1) = Chr(0) ; end of string
    Local $PCWSTR_struct = DllStructCreate("WCHAR[" & $anz / 2 & "]", $ptr) ; create struct with correct amount of bytes
    Local $PCWSTR = DllStructGetData($PCWSTR_struct, 1)
    _DISM_Delete($PCWSTR_struct) ; free resources
    Return $PCWSTR ; return string
EndFunc

The problem only occurs when i use 64-bit AutoIT and 64-bit dll version. I think some of the data types are not compatible with 64-bit anymore, although the first 6 elements are readable properly:

MsgBox(0, "ImageType", _DISM_GetImageType(DllStructGetData($tImageInfo_sub, "ImageType")))
            MsgBox(0, "ImageIndex", DllStructGetData($tImageInfo_sub, "ImageIndex"))
            MsgBox(0, "ImageName", GetPCWSTR($tImageInfo_sub, "ImageName"))
            MsgBox(0, "ImageDescription", GetPCWSTR($tImageInfo_sub, "ImageDescription"))
            MsgBox(0, "ImageSize", DllStructGetData($tImageInfo_sub, "ImageSize"))
            MsgBox(0, "Architecture", DllStructGetData($tImageInfo_sub, "Architecture"))
            MsgBox(0, "ProductName", GetPCWSTR($tImageInfo_sub, "ProductName")) ; autoit crashes

EDIT: The exact line where it crashes is in Misc.au3

$char_struct = DllStructCreate("WCHAR", $ptr + $anz) ; get memory location

, when i try to read the pointer of 

"ProductName" in DISM.au3 on line 1251.

I'm not able to read one char of this pointer :S

Edited by Trolleule

Share this post


Link to post
Share on other sites
Local $tagDismImageInfo = "INT ImageType;UINT ImageIndex;PTR ImageName;PTR ImageDescription;UINT64 ImageSize;UINT Architecture;PTR ProductName;PTR EditionId;PTR InstallationType;" & _
                                 "PTR Hal;PTR ProductType;PTR ProductSuite;UINT MajorVersion;UINT MinorVersion;UINT Build;UINT SpBuild;UINT SpLevel;INT Bootable;PTR SystemRoot;" & _
                                 "PTR Language;UINT LanguageCount;UINT DefaultLanguageIndex;PTR CustomizedInfo"

Local $tImageInfo_sub = DllStructCreate($tagDismImageInfo, $pImageInfo)

My first expection was to change some of these data types... otherwise it might be more complicated :S

Perhaps you can test it. You only need Windows ADK + some .wim file. Thanks in advance!

EDIT: Try this DISM.au3, it's better to understand :) (i updated the DISM.au3 in my first post too)

DISM.au3

Edited by Trolleule

Share this post


Link to post
Share on other sites

A friend tested it in C++, the x64 dismapi.dll works properly.

Are there some debug techniques i can use to check what is wrong with pointers or a possibility to read the pointer byte by byte?

Share this post


Link to post
Share on other sites

ui that sounds nice. What do you mean with reverse? ->

Local $tagDismImageInfo = "INT ImageType;UINT ImageIndex;PTR ImageName;PTR ImageDescription;UINT64 ImageSize;UINT Architecture;" & _
                              "PTR;SystemRoot;PTR ProductType;PTR Hal;PTR InstallationType;PTR EditionId;PTR ProductName;" & _
                              "PTR ProductSuite;UINT MajorVersion;UINT MinorVersion;UINT Build;UINT SpBuild;UINT SpLevel;INT Bootable;" & _
                              "PTR Language;UINT LanguageCount;UINT DefaultLanguageIndex;PTR CustomizedInfo"

instead of

Local $tagDismImageInfo = "INT ImageType;UINT ImageIndex;PTR ImageName;PTR ImageDescription;UINT64 ImageSize;UINT Architecture;" & _
                              "PTR ProductName;PTR EditionId;PTR InstallationType;PTR Hal;PTR ProductType;PTR ProductSuite;" & _
                              "UINT MajorVersion;UINT MinorVersion;UINT Build;UINT SpBuild;UINT SpLevel;INT Bootable;PTR SystemRoot;" & _
                              "PTR Language;UINT LanguageCount;UINT DefaultLanguageIndex;PTR CustomizedInfo"

?

Reversed:

reversed.png

Normal:

normal.png

Edited by Trolleule

Share this post


Link to post
Share on other sites

No, reverse the actual high / low order values. Here's how I did it:

MsgBox(0, "ProductName", GetPCWSTR($tImageInfo, "ProductName", True))
Func GetPCWSTR(ByRef $struct, $sElementName, $lSwap = False) ; avoids memory access conflicts
    Local $char_struct
    Local $anz = 0 ; counter for signs
    Local $ptr = DllStructGetData($struct, $sElementName) ; ptr

    If $lSwap Then
        $ptr = '0x' & hex(_WinAPI_LoDWord($ptr), 8) & hex(_WinAPI_HiDWord($ptr), 8)
    EndIf

    Do
        $char_struct = DllStructCreate("WCHAR", $ptr + $anz) ; get memory location
        $anz += 2
    Until DllStructGetData($char_struct, 1) = Chr(0) ; end of string
    Local $PCWSTR_struct = DllStructCreate("WCHAR[" & $anz / 2 & "]", $ptr) ; create struct with correct amount of bytes
    Local $PCWSTR = DllStructGetData($PCWSTR_struct, 1)
    _DISM_Delete($PCWSTR_struct) ; free resources
    Return $PCWSTR ; return string
EndFunc

You'll need to add "#include <WinAPIMisc.au3>" to Misc.au3.

 

Share this post


Link to post
Share on other sites

big thanks! Now i can read from pointer, but something is strange:

ConsoleWrite("ImageType: " & DllStructGetData($tImageInfo, "ImageType") & @CRLF) ; ok
ConsoleWrite("ImageIndex: " & DllStructGetData($tImageInfo, "ImageIndex") & @CRLF) ; ok
ConsoleWrite("ImageName: " & GetPCWSTR($tImageInfo, "ImageName") & @CRLF) ; ok
ConsoleWrite("ImageDescription: " & GetPCWSTR($tImageInfo, "ImageDescription") & @CRLF) ; ok
ConsoleWrite("ImageSize: " & DllStructGetData($tImageInfo, "ImageSize") & @CRLF) ; ok
ConsoleWrite("Architecture: " & DllStructGetData($tImageInfo, "Architecture") & @CRLF) ; ok
ConsoleWrite("ProductName: " & GetPCWSTR($tImageInfo, "ProductName", True) & @CRLF) ; x86: Betriebssystem Microsoft® Windows® x64: Professional
ConsoleWrite("EditionId: " & GetPCWSTR($tImageInfo, "EditionId", True) & @CRLF) ; x86: Professional x64: Client
ConsoleWrite("InstallationType: " & GetPCWSTR($tImageInfo, "InstallationType", True) & @CRLF) ; x86: Client x64:
ConsoleWrite("Hal: " & GetPCWSTR($tImageInfo, "Hal", True) & @CRLF) ; x86:  x64: WinNT
ConsoleWrite("ProductType: " & GetPCWSTR($tImageInfo, "ProductType", True) & @CRLF) ; x86: WinNT x64: Terminal Server
ConsoleWrite("ProductSuite: " & DLLStructGetData($tImageInfo, "ProductSuite") & @CRLF) ; x86: Terminal Server x64: 0x0000000A000000C8 (PCWSTR will crash AutoIT)
ConsoleWrite("MajorVersion: " & DllStructGetData($tImageInfo, "MajorVersion") & @CRLF) ; x86: 10 x64: 0
ConsoleWrite("MinorVersion: " & DllStructGetData($tImageInfo, "MinorVersion") & @CRLF) ; x86: 0 x64: 10586
ConsoleWrite("Build: " & DllStructGetData($tImageInfo, "Build") & @CRLF) ; x86: 10586 x64: 0
ConsoleWrite("SpBuild: " & DllStructGetData($tImageInfo, "SpBuild") & @CRLF) ; x86: 0 x64: 0
ConsoleWrite("SpLevel: " & DllStructGetData($tImageInfo, "SpLevel") & @CRLF) ; x86: 0 x64: 1
ConsoleWrite("Bootable: " & DllStructGetData($tImageInfo, "Bootable") & @CRLF) ; x86: 1 x64: -1950295936
ConsoleWrite("SystemRoot: " & GetPCWSTR($tImageInfo, "SystemRoot", True) & @CRLF) ; x86: WINDOWS x64: ??o
ConsoleWrite("Language: " & DllStructGetData($tImageInfo, "Language") & @CRLF) ; x86: ok x64: 0x000000010000006F
ConsoleWrite("LanguageCount: " & DllStructGetData($tImageInfo, "LanguageCount") & @CRLF) ; x86: 1 x64: 0
ConsoleWrite("DefaultLanguageIndex: " & DllStructGetData($tImageInfo, "DefaultLanguageIndex") & @CRLF) ; x86: 0 x64: 2291066752
ConsoleWrite("CustomizedInfo: " & DllStructGetData($tImageInfo, "CustomizedInfo") & @CRLF) ; x86: ok x64: 0x000000000000006F

the order is messy. "ProductName" keeps information of "EditionId" and so on, but i think if we can get the order right, the rest would be right too...

Do you know why this happens and do you have a solution?

 

EDIT:

I tested around and campe up with this:

Local $tagDismImageInfo = "INT ImageType;UINT ImageIndex;PTR ImageName;PTR ImageDescription;UINT64 ImageSize;" & _
                          "UINT Architecture;PTR EditionId;PTR InstallationType;" & _
                          "PTR Hal;PTR ProductType;PTR ProductSuite;UINT MajorVersion;UINT MinorVersion;" & _
                          "UINT Build;UINT SpBuild;UINT SpLevel;UINT Bootable;INT SystemRoot;" & _
                         "PTR Language;PTR LanguageCount;UINT DefaultLanguageIndex;UINT CustomizedInfo;PTR ProductName"

ConsoleWrite("ImageType: " & DllStructGetData($tImageInfo, "ImageType") & @CRLF)
ConsoleWrite("ImageIndex: " & DllStructGetData($tImageInfo, "ImageIndex") & @CRLF)
ConsoleWrite("ImageName: " & GetPCWSTR($tImageInfo, "ImageName") & @CRLF)
ConsoleWrite("ImageDescription: " & GetPCWSTR($tImageInfo, "ImageDescription") & @CRLF)
ConsoleWrite("ImageSize: " & DllStructGetData($tImageInfo, "ImageSize") & @CRLF)
ConsoleWrite("Architecture: " & DllStructGetData($tImageInfo, "Architecture") & @CRLF)
ConsoleWrite("ProductName: " & DllStructGetData($tImageInfo, "ProductName") & @CRLF)
ConsoleWrite("EditionId: " & GetPCWSTR($tImageInfo, "EditionId", True) & @CRLF)
ConsoleWrite("InstallationType: " & GetPCWSTR($tImageInfo, "InstallationType", True) & @CRLF)
ConsoleWrite("Hal: " & GetPCWSTR($tImageInfo, "Hal", True) & @CRLF)
ConsoleWrite("ProductType: " & GetPCWSTR($tImageInfo, "ProductType", True) & @CRLF)
ConsoleWrite("ProductSuite: " & GetPCWSTR($tImageInfo, "ProductSuite", True) & @CRLF)
ConsoleWrite("MajorVersion: " & DllStructGetData($tImageInfo, "MajorVersion") & @CRLF)
ConsoleWrite("MinorVersion: " & DllStructGetData($tImageInfo, "MinorVersion") & @CRLF)
ConsoleWrite("Build: " & DllStructGetData($tImageInfo, "Build") & @CRLF)
ConsoleWrite("SpBuild: " & DllStructGetData($tImageInfo, "SpBuild") & @CRLF)
ConsoleWrite("SpLevel: " & DllStructGetData($tImageInfo, "SpLevel") & @CRLF)
ConsoleWrite("Bootable: " & DllStructGetData($tImageInfo, "Bootable") & @CRLF)
ConsoleWrite("SystemRoot: " & DllStructGetData($tImageInfo, "SystemRoot") & @CRLF)
ConsoleWrite("Language: " & GetPCWSTR($tImageInfo, "Language", True) & @CRLF)
ConsoleWrite("LanguageCount: " & DllStructGetData($tImageInfo, "LanguageCount") & @CRLF)
ConsoleWrite("DefaultLanguageIndex: " & DllStructGetData($tImageInfo, "DefaultLanguageIndex") & @CRLF)
ConsoleWrite("CustomizedInfo: " & DllStructGetData($tImageInfo, "CustomizedInfo") & @CRLF)

You can see, the order is wrong, but this gives the best results...

Output:

ImageType: 0
ImageIndex: 1
ImageName: Windows 10 Pro Technical Preview
ImageDescription: Windows 10 Pro Technical Preview
ImageSize: 13298258120
Architecture: 9
EditionId: Professional
InstallationType: Client
Hal: 
ProductType: WinNT
ProductSuite: Terminal Server
MajorVersion: 224
MinorVersion: 10
Build: 0
SpBuild: 10586
SpLevel: 0
Bootable: 0
SystemRoot: 1
Language: ?°Ã
LanguageCount: 0x00000001000000E0
DefaultLanguageIndex: 0
CustomizedInfo: 572084256

Something is really strange :S

 

testing.png

Edited by Trolleule

Share this post


Link to post
Share on other sites

Fuck...i got it and i don't know why :D

I only add "align 4" to my struct, default is "align 8". Now it works properly and without Lo/Hi reverse.

$tagDismImageInfo = "align 4;INT ImageType;UINT ImageIndex;PTR ImageName;PTR ImageDescription;UINT64 ImageSize;" & _
                    "UINT Architecture;PTR ProductName;PTR EditionId;PTR InstallationType;" & _
                    "PTR Hal;PTR ProductType;PTR ProductSuite;UINT MajorVersion;UINT MinorVersion;UINT Build;UINT SpBuild;" & _
                    "UINT SpLevel;INT  Bootable;PTR SystemRoot;" & _
                    "PTR Language;UINT LanguageCount;UINT DefaultLanguageIndex;PTR CustomizedInfo"

Big thanks Danp2! I think i have to change the topic title to mark this as resolved right?

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

    • 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.
    • By bladem2003
      Hello,
      i need help to translate the c code to autoit .
      I don't understand the callback function.
       
      #include <windows.h> #include <stdio.h> // native IR Data by PAnsiChar typedef void CALLBACK CallBackPAnsiChar(char*, char*, char*, char*); typedef int (__stdcall *impInitPAnsiChar)(CallBackPAnsiChar); CALLBACK MyCallBackPAnsiChar(char* Protocol, char* Address, char* Command, char* Flags) { printf("\nIR Data received: Protocol: %s, Address: 0x%s, Command: 0x%s, Flags: 0x%s", Protocol, Address, Command, Flags); fflush(stdout); } int main(int argc, char **argv) { impInitPAnsiChar InitPAnsiChar = NULL; // Load DLL file HINSTANCE hinstLib = LoadLibrary(TEXT("USB_IR_Remote_Receiver.dll")); if (hinstLib == NULL) { printf("\nERROR: unable to load DLL\n"); return 1; } // Get function pointer InitPAnsiChar InitPAnsiChar = (impInitPAnsiChar)GetProcAddress(hinstLib, "InitPAnsiChar"); if (InitPAnsiChar == NULL) { printf("\nERROR: unable to find DLL function\n"); FreeLibrary(hinstLib); return 1; } if (InitPAnsiChar(*MyCallBackPAnsiChar)) { printf("\nInit DLL with InitPAnsiChar successfull"); } else { // Unload DLL file FreeLibrary(hinstLib); return 0; } while(1) { } //return 0; }  
    • By Yirrlaar
      Hello All,
      I'm using "ImageSearch2015.au3" and i'm trying to figure out WHY, for the life of me, I can't find an image is hidden.
      So what I came up with, is as follows:
      _ImageSearchAreaHidden("C:\icon.png", 1, 0, 0, 800, 600, $x1, $y1, 80, 0) Func _ImageSearchAreaHidden($findImage, $resultPosition, $x1, $y1, $right, $bottom, ByRef $x, ByRef $y, $tolerance, $transparency = 0) Local $h, $result local $TestScreen = "C:\TestScreen.png" ;previsous screenshot of the image looking for, fully visible If Not FileExists($findImage) Then Return "Image File not found" If $transparency <> 0 Then $findImage = "*" & $transparency & " " & $findImage If $tolerance < 0 Or $tolerance > 255 Then $tolerance = 0 If $h_ImageSearchDLL = -1 Then _ImageSearchStartup() If $tolerance > 0 Then $findImage = "*" & $tolerance & " " & $findImage $result = DllCall($h_ImageSearchDLL, "str", "ImageSearchEx", "str", $TestScreen, "int", $x1, "int", $y1, "int", $right, "int", $bottom, "str", $findImage) If @error Then Return "DllCall Error=" & @error If $result = "0" Then Return False $array = StringSplit($result[0], "|") If (UBound($array) >= 4) Then $x = Int(Number($array[2])) ; Get the x,y location of the match $y = Int(Number($array[3])) If $resultPosition = 1 Then $x = $x + Int(Number($array[4]) / 2) ; Account for the size of the image to compute the centre of search $y = $y + Int(Number($array[5]) / 2) EndIf Return True EndIf EndFunc ;==>_ImageSearchAreaHidden Now when the folder with the icon is completely visible, it finds the icon without any issues, however if I cover up the icon, it no longer finds the image in the folder.
      Any ideas?
×
×
  • Create New...