Jump to content

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
Link to comment
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

Link to comment
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
Link to comment
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

Link to comment
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

 

Link to comment
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
 Share

×
×
  • Create New...