Jump to content
supersonic

DllCall - trying to read an array of pointers

Recommended Posts

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"? :blink:

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.

Edited by supersonic

Share this post


Link to post
Share on other sites

hello. you need to do something like this:

#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*", 0, "PTR*", 0)
If (Not @error) Then


    Local $iCredentialsCount = $aResult[3]
    Local $pArrayCredentials = $aResult[4]
;~     _ArrayDisplay($aResult, $iCredentialsCount)

    Local $taPointer = DllStructCreate("ptr[" & $iCredentialsCount & "]", $pArrayCredentials)

    ;show each pointer to credential
    For $i = 1 To $iCredentialsCount
        MsgBox(0, $i, DllStructGetData($taPointer, 1, $i))
    Next

    ;free
    For $i = 1 To $iCredentialsCount
        MsgBox(0, $i,)
        DllCall("advapi32.dll", "NONE", "CredFreeW", "PTR", DllStructGetData($taPointer, 1, $i))
    Next
    $taPointer = 0
EndIf
 

 

 

PD: sorry for syntax highlighting not working in my slow connection

 

Saludos

Share this post


Link to post
Share on other sites

Oh dear - an error occurs if running AutoIt in 64 bit :(

The code to reproduce:

;~ #AutoIt3Wrapper_UseX64 = Y


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


Local $aResult = DllCall("advapi32.dll", "BOOL", "CredEnumerateW", "WSTR", Null, "DWORD", 1, "DWORD*", 0, "PTR*", 0)
If (Not @error) Then


    Local $iCredentialsCount = $aResult[3]
    Local $pArrayCredentials = $aResult[4]
    ; _ArrayDisplay($aResult, $iCredentialsCount)


    Local $taPointer = DllStructCreate("ptr[" & $iCredentialsCount & "]", $pArrayCredentials)
    For $i = 1 To $iCredentialsCount
        ; MsgBox(0, $i, DllStructGetData($taPointer, 1, $i))


        DllCall("advapi32.dll", "NONE", "CredFree", "PTR", DllStructGetData($taPointer, 1, $i))
        ConsoleWrite("___" & @error & @CRLF)
    Next
    $taPointer = 0


EndIf

In 32 bit everything works fine. In 64 bit the first 10-12 pointers are read. Then AutoIt crashes.

Any idea to resolve that issue?

P.S.: There is no function 'CredFreeA' or 'CredFreeW'... Only 'CredFree'.

Edited by supersonic

Share this post


Link to post
Share on other sites

sorry my fault. I read wrong in msdn. the correct way is free the pointer to the array.

#AutoIt3Wrapper_UseX64 = Y


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


Local $aResult = DllCall("advapi32.dll", "BOOL", "CredEnumerateW", "WSTR", Null, "DWORD", 1, "DWORD*", 0, "PTR*", 0)
If (Not @error) Then


    Local $iCredentialsCount = $aResult[3]
    Local $pArrayCredentials = $aResult[4]
    ; _ArrayDisplay($aResult, $iCredentialsCount)


    Local $taPointer = DllStructCreate("ptr[" & $iCredentialsCount & "]", $pArrayCredentials)
    For $i = 1 To $iCredentialsCount
        MsgBox(0, $i, DllStructGetData($taPointer, 1, $i))
    Next
    DllCall("advapi32.dll", "NONE", "CredFree", "PTR", $pArrayCredentials)
    $taPointer = 0


EndIf

Saludos

Share this post


Link to post
Share on other sites

Thank you - I tried this before, too. And it worked. But 'pArrayCredentials' is a structure not a pointer!? Or am I wrong? :blink:

Furthermore... Running in 32 bit works for all entries. Do you know why?

Edited by supersonic

Share this post


Link to post
Share on other sites

1.- pArrayCredentials Its Pointer to an array of pointers to credentials

2.- just luck I think. But it's wrong. MSDN says.

Credential

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. The single returned buffer must be freed by calling CredFree.

Saludos

 

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 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 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?
    • By tukangusil7
      Overview
      _Security__GetTokenInformation() returns a struct containing raw bytes that represents the requested token information.
      Take for example, if _Security__GetTokenInformation()  called with  $iClass parameter is set to $TokenUser, the function returns raw bytes that represents a TOKEN_USER struct, which is defined as follows:
      typedef struct _TOKEN_USER { SID_AND_ATTRIBUTES User; } TOKEN_USER, *PTOKEN_USER; Subsequently, the SID_AND_ATTRIBUTES struct is defined as follows:
      typedef struct _SID_AND_ATTRIBUTES {   PSID  Sid;   DWORD Attributes; } SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES; Problems
      Since SID has variable length, I suppose that interpreting the returned bytes as SID_AND_ATTRIBUTES struct won't be easy as usual.
      Questions
      Please inspect my GetTokenInfoUser function below.
      Have I got a correct value of Attributes member of SID_AND_ATTRIBUTES struct? If I have got the correct value, is my approach efficient? #include <Security.au3> #include <WinAPIHObj.au3> #include <Array.au3> Opt("MustDeclareVars", 1) Func GetTokenInfoUser($hToken) Do ; _Security__GetTokenInformation() returns a struct containing bytes that represents the ; requested token information. Local $tRawTokenInfo = _Security__GetTokenInformation($hToken, $TokenUser) If @error Then MsgBox($MB_SYSTEMMODAL, _WinAPI_GetLastError(), "_Security__GetTokenInformation() fails.") ExitLoop EndIf Local $pRawTokenInfo = DllStructGetPtr($tRawTokenInfo) ; Since SID has variable length, I do not know how to interpret the raw bytes as SID_AND_ATTRIBUTES ; struct unless the SID length is known. Local $tagPtrSid = "align 4; PTR Sid" Local $tPtrSid = DllStructCreate($tagPtrSid, $pRawTokenInfo) Local $pSid = DllStructGetData($tPtrSid, 1) If Not _Security__IsValidSid($pSid) Then ; Just to make sure $pSid is a pointer to a valid SID MsgBox($MB_SYSTEMMODAL, "", "The SID is invalid.") ExitLoop EndIf Local $iSidBytesLen = _Security__GetLengthSid($pSid) ; The length of the binary SID, in bytes ; After the SID length is known, the raw bytes are interpreted as SID_AND_ATTRIBUTES struct Local $tagSID_AND_ATTRIBUTES = "align 4; PTR Sid; BYTE[" & $iSidBytesLen & "]; ULONG Attributes" Local $tSID_AND_ATTRIBUTES = DllStructCreate($tagSID_AND_ATTRIBUTES, $pRawTokenInfo) ; Return the results Local $avResults[2] $avResults[0] = $pSid $avResults[1] = DllStructGetData($tSID_AND_ATTRIBUTES, "Attributes") Return $avResults Until False Return SetError(1, 0, 0) EndFunc ; GetTokenInfoUser Func Main() Do Local $hToken = _Security__OpenProcessToken(_WinAPI_GetCurrentProcess(), $TOKEN_QUERY) If Not $hToken Then MsgBox($MB_SYSTEMMODAL, _WinAPI_GetLastError(), "_Security__OpenProcessToken() fails.") ExitLoop EndIf Local $avResults = GetTokenInfoUser($hToken) If @error Then ExitLoop _ArrayDisplay($avResults) ; Display the results of GetTokenInfoUser() If $hToken Then _WinAPI_CloseHandle($hToken) Return Until False If $hToken Then _WinAPI_CloseHandle($hToken) EndFunc ; Main Main() Thanks in advance.
    • By tukangusil7
      When the type of a registry value given by RegQueryValueEx() is REG_RESOURCE_LIST constant (i.e. 8), the data received in the lpData (out) parameter is a pointer to a variable of type CM_RESOURCE_LIST struct.
      According to MSDN, CM_RESOURCE_LIST struct is defined as follows:
      typedef struct _CM_RESOURCE_LIST { ULONG Count; CM_FULL_RESOURCE_DESCRIPTOR List[1]; } *PCM_RESOURCE_LIST, CM_RESOURCE_LIST; Additionally, CM_FULL_RESOURCE_DESCRIPTOR struct is defined as follows:
      typedef struct _CM_FULL_RESOURCE_DESCRIPTOR { INTERFACE_TYPE InterfaceType; ULONG BusNumber; CM_PARTIAL_RESOURCE_LIST PartialResourceList; } *PCM_FULL_RESOURCE_DESCRIPTOR, CM_FULL_RESOURCE_DESCRIPTOR; Furthermore, CM_PARTIAL_RESOURCE_LIST struct  is defined as follows:
      typedef struct _CM_PARTIAL_RESOURCE_LIST { USHORT Version; USHORT Revision; ULONG Count; CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]; } CM_PARTIAL_RESOURCE_LIST, *PCM_PARTIAL_RESOURCE_LIST; Finally, CM_PARTIAL_RESOURCE_DESCRIPTOR struct is defined like that (long enough to be posted here).
      I have no idea how to create these kind of structs in AutoIt.
      Please tell me how to write them in AutoIt just until the second struct (CM_FULL_RESOURCE_DESCRIPTOR).
×
×
  • Create New...