Jump to content

Recommended Posts

A simple function to print a DllStruct on AutoIt.

 

#include <StringConstants.au3>
#include <Array.au3>

Func DllStructPrint($str, $tag)
    Local $ret = ""
    If IsDllStruct($str) Then
        $tag = StringLower($tag)
        Local $arr1, $arr2
        $arr1 = StringSplit($tag, ";", $STR_NOCOUNT)
        Local $aLabel[1]
        For $ii = 0 To UBound($arr1, 1) - 1
            If Not ($arr1[$ii] = "struct") And Not ($arr1[$ii] = "endstruct") Then
                $arr2 = StringSplit($arr1[$ii], " ", $STR_NOCOUNT)
                If IsArray($arr2) Then _ArrayAdd($aLabel, $arr2[1])
            EndIf
        Next
        For $ii = 1 To UBound($aLabel, 1) - 1
            $ret &= $aLabel[$ii] & "=" & DllStructGetData($str, $aLabel[$ii])
        Next
    ElseIf IsArray($str) Then
        $ret &= "[" & @LF
        Local $iSize = UBound($str, 1) - 1
        For $ii = 0 To $iSize
            $ret &= "  " & DllStructPrint($str[$ii], $tag) & ($ii = $iSize ? "" : ",") & @LF
        Next
        $ret &= "]" & @LF
    EndIf
    Return $ret
EndFunc   ;==>DllStructPrint

Local $tag = "Struct;byte key;EndStruct"

Local $str1 = DllStructCreate($tag)
$str1.key = Random(100, 999)
Local $str2 = DllStructCreate($tag)
$str2.key = Random(100, 999)
Local $str3 = DllStructCreate($tag)
$str3.key = Random(100, 999)

Local $arr[2]
$arr[0] = $str2
$arr[1] = $str3

Local $var1 = DllStructPrint($str1, $tag)
ConsoleWrite($var1 & @LF)

Local $var2 = DllStructPrint($arr, $tag)
ConsoleWrite($var2 & @LF)

 

OUTPUT:

key=189
[
  key=155,
  key=62
]

 

Edited by Luigi

Visit my repository

Link to post
Share on other sites
  • 2 weeks later...

Hi Luigi,

This is a good idea. I recently had the same need here for a debugging function and ended up just modifying _WinAPI_DisplayStruct to get around all the leg work that's needed for a function like this. There are a lot of different situations to think about. I actually spent more time perfecting/making a decision on the table formatting. I still go back and forth on which one I like better. Anyway here's example from help file and what the output would look like. Cheers

Local $sStruct = 'dword Length;short State;uint Flags;handle hBitmap;hwnd hDC;long Rect[4];byte[14];int Reserved[10];wchar Text[80]'
Local $tStruct = DllStructCreate($sStruct)

DllStructSetData($tStruct, 1, 80)
DllStructSetData($tStruct, 2, 6)
DllStructSetData($tStruct, 3, 1)
DllStructSetData($tStruct, 4, 0x00010014)
DllStructSetData($tStruct, 5, 0x01010057)
DllStructSetData($tStruct, 6, 20, 1)
DllStructSetData($tStruct, 6, 20, 2)
DllStructSetData($tStruct, 6, 60, 3)
DllStructSetData($tStruct, 6, 80, 4)
DllStructSetData($tStruct, 7, Binary('0x656A6D633835206C6A6764206200'))
DllStructSetData($tStruct, 8, 0)
DllStructSetData($tStruct, 9, 'Simple Text')

Local $aStruct = _Winapi_PrintStruct($tStruct, $sStruct)

Output:

________________________________________________________________________________________________
| #   | Member      | Offset       | Type          | Size     | Value                            | 
|¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
| -   | -           | 0x011B9620   | <struct>      | 0        | -                                | 
| 1   | Length      | 0            | DWORD         | 4        | 80                               | 
| 2   | State       | 4            | short         | 2        | 6                                | 
| -   | -           | -            | <alignment>   | 2        | -                                | 
| 3   | Flags       | 8            | UINT          | 4        | 1                                | 
| 4   | hBitmap     | 12           | HANDLE        | 4        | 0x00010014                       | 
| 5   | hDC         | 16           | HWND          | 4        | 0x01010057                       | 
| 6   | Rect        | 20           | long[4]       | 16 (4)   | [1] 20                           | 
| -   | -           | 24           | -             | -        | [2] 20                           | 
| -   | -           | 28           | -             | -        | [3] 60                           | 
| -   | -           | 32           | -             | -        | [4] 80                           | 
| 7   | <unnamed>   | 36           | BYTE[14]      | 14       | 0x656A6D633835206C6A6764206200   | 
| -   | -           | -            | <alignment>   | 2        | -                                | 
| 8   | Reserved    | 52           | int[10]       | 40       | -                                | 
| 9   | Text        | 92           | WCHAR[80]     | 160      | Simple Text                      | 
| -   | -           | 0x011B971C   | <endstruct>   | 252      | -                                | 
 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

 

 

_Winapi_PrintStruct.au3

Link to post
Share on other sites

That only works when you have the struct definition text at hand.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to post
Share on other sites

Yup.. Yashied did put in a request a one point asking for function that would return the string used to define the structure if it was created with autoit but never happened. I recall Ward did some work somewhere too for discovering the types

Link to post
Share on other sites

Search for a recent post of mine based on the word _vardump.  Found it:

 

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to post
Share on other sites
Link to post
Share on other sites

You'll have to remove the map-supporting part of the code if you don't want to rely on the beta.

I plan to support scripting dictionary objects as well some day.  Not that it's hard to do given the existing code base.

Also not very hard to derive code to output some struct definition in AutoIt test format.  Only very weird pointless alignment directives might get undetected but that's very unusual.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to post
Share on other sites
  • 2 weeks later...

This was fun. I really liked these set and check statements you have for getting the element types and also poking the indexes to confirm the element array count. With knowing type size and array count we can actually confirm the alignment as we walk through by using the ptr values of the the next element. The next ptr also tells us if we are finished or not.

This below should produce same basic output as _winapi_displaystruct (minus options) without needing the definition:

#include <array.au3>
#include <WinAPIDiag.au3>

Local $sStruct = 'dword Length;short State;uint Flags;handle hBitmap;hwnd hDC;long Rect[4];byte[9];int Reserved[10];wchar Text[80];double d;float f'
Local $tStruct = DllStructCreate($sStruct)

DllStructSetData($tStruct, 1, 80)
DllStructSetData($tStruct, 2, 6)
DllStructSetData($tStruct, 3, 1)
DllStructSetData($tStruct, 4, 0x00010014)
DllStructSetData($tStruct, 5, 0x01010057)
DllStructSetData($tStruct, 6, 10, 1)
DllStructSetData($tStruct, 6, 20, 2)
DllStructSetData($tStruct, 6, 30, 3)
DllStructSetData($tStruct, 7, Binary('0xABCDEF0123456789'))
DllStructSetData($tStruct, 8, 0)
DllStructSetData($tStruct, 9, 'Simple Text')
DllStructSetData($tStruct, 10, 12567823854.1256782385411)
DllStructSetData($tStruct, 11, 11256.12567823854111)

_dlldisplay($tStruct)
_WinAPI_DisplayStruct($tStruct, $sStruct)


Func _dlldisplay($tStruct)

    Local $pNextPtr, $pCurrentPtr = DllStructGetPtr($tStruct, 1)
    Local $iOffset = 0, $iDllSize = DllStructGetSize($tStruct)
    Local $vElVal, $sType, $iTypeSize, $iElSize, $iArrCount, $iAlign

    Local $aStruct[1][5] = [['-', $pCurrentPtr, '<struct>', 0, '-']] ; #|Offset|Type|Size|Value'

    ; loop through elements
    For $iE = 1 To 2 ^ 63

        ; backup first index value, establish type and typesize of element, restore first index value
        $vElVal = DllStructGetData($tStruct, $iE, 1)
        Switch VarGetType($vElVal)
            Case "Int32", "Int64"
                DllStructSetData($tStruct, $iE, 0x7777666655554433, 1)
                Switch DllStructGetData($tStruct, $iE, 1)
                    Case 0x7777666655554433
                        $sType = "int64"
                        $iTypeSize = 8
                    Case 0x55554433
                        DllStructSetData($tStruct, $iE, 0x88887777, 1)
                        $sType = (DllStructGetData($tStruct, $iE, 1) > 0 ? "uint" : "int")
                        $iTypeSize = 4
                    Case 0x4433
                        DllStructSetData($tStruct, $iE, 0x8888, 1)
                        $sType = (DllStructGetData($tStruct, $iE, 1) > 0 ? "ushort" : "short")
                        $iTypeSize = 2
                    Case 0x33
                        $sType = 'byte'
                        $iTypeSize = 1
                EndSwitch
            Case 'Ptr'
                $sType = 'ptr'
                $iTypeSize = @AutoItX64 ? 8 : 4
            Case 'String'
                DllStructSetData($tStruct, $iE, ChrW(0x2573), 1)
                $sType = (DllStructGetData($tStruct, $iE, 1) = ChrW(0x2573) ? "wchar" : "char")
                $iTypeSize = ($sType = 'wchar') ? 2 : 1
            Case 'Double'
                DllStructSetData($tStruct, $iE, 10 ^ - 15, 1)
                $sType = (DllStructGetData($tStruct, $iE, 1) = 10 ^ - 15 ? "double" : "float")
                $iTypeSize = ($sType = 'double') ? 8 : 4
        EndSwitch
        DllStructSetData($tStruct, $iE, $vElVal, 1)

        ;calculate element total size based on distance to next element
        $pNextPtr = DllStructGetPtr($tStruct, $iE + 1)
        $iElSize = $pNextPtr ? Int($pNextPtr - $pCurrentPtr) : $iDllSize

        ;calculate true array count. Walk index backwards till there is NOT an error
        $iArrCount = Int($iElSize / $iTypeSize)
        While $iArrCount > 1
            DllStructGetData($tStruct, $iE, $iArrCount)
            If Not @error Then ExitLoop
            $iArrCount -= 1
        WEnd

        ;alignment is whatever space is left
        $iAlign = $iElSize - ($iArrCount * $iTypeSize)
        $iElSize -= $iAlign

        ;Add/print values and alignment
        Switch $sType
            Case 'wchar', 'char', 'byte'
                _ArrayAdd($aStruct, $iE & '|' & $iOffset & '|' & $sType & '[' & $iArrCount & ']|' & $iElSize & '|' & DllStructGetData($tStruct, $iE))
            Case Else ; 'uint', 'int', 'ushort', 'short', 'double', 'float', 'ptr'
                If $iArrCount > 1 Then
                    _ArrayAdd($aStruct, $iE & '|' & $iOffset & '|' & $sType & '[' & $iArrCount & ']' & '|' & $iElSize & ' (' & $iTypeSize & ')|' & (DllStructGetData($tStruct, $iE) ? '[1] ' & $vElVal : '-'))
                    If DllStructGetData($tStruct, $iE) Then ; skip empty arrays
                        For $j = 2 To $iArrCount
                            _ArrayAdd($aStruct, '-|' & $iOffset + ($iTypeSize * ($j - 1)) & '|-|-|[' & $j & '] ' & DllStructGetData($tStruct, $iE, $j))
                        Next
                    EndIf
                Else
                    _ArrayAdd($aStruct, $iE & '|' & $iOffset & '|' & $sType & '|' & $iElSize & '|' & $vElVal)
                EndIf
        EndSwitch
        If $iAlign Then _ArrayAdd($aStruct, '-|-|<alignment>|' & ($iAlign) & '|-')

        ;if no next ptr then this was the last/only element
        If Not $pNextPtr Then ExitLoop

        ;update offset, size and next ptr
        $iOffset += $iElSize + $iAlign
        $iDllSize -= $iElSize + $iAlign
        $pCurrentPtr = $pNextPtr

    Next

    _ArrayAdd($aStruct, '-|' & DllStructGetPtr($tStruct) + DllStructGetSize($tStruct) & '|<endstruct>|' & DllStructGetSize($tStruct) & '|-')

    _ArrayDisplay($aStruct, '', '', 64, Default, '#|Offset|Type|Size|Value')

    Return $aStruct

EndFunc   ;==>_dlldisplay

 

Edited by Beege
Link to post
Share on other sites

To be honest I never find it urgent to invest time and more complexity to detect non-standard align directives.  Indeed it's quite uncommon to encounter real-world structures needing something like "align 8;byte;byte[4];align 1; byte;word; align 4;byte;..." and I don't even know how one would use it except for interfacing with weird assembly code.

I know it's possible as you show but is that necessary in daily work?

Also I didn't bother with nested struct..endstruct directives, but I confess being lazy ... and not using AutoIt at all for my own needs.

If I ever add something, that will be a dump of scripting dictionary objects (something easy to do), since the Map datatype seems to be falling in obsolescence (unfortunately).

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to post
Share on other sites

You cant imply this is a more complicated method. You just cant. I'm using simple arithmetic to establish the array count, not the alignment. The alignment/padding just happens to end up being a easy bonus since we know both space-allocated and actual space-used. Alignment is just the difference now. 

We dont need a crazy structure like that to demonstrate how standard alignment can by itself get tricky with the padding, especially when your a beginner just grasping what alignment is.  Each one of these will end up with multiple padding statements:

$tStruct = 'byte Enabled;dword Value'
_dlldisplay(DllStructCreate($tStruct))

$tStruct = 'byte Enabled;dword Value;word Idx'
_dlldisplay(DllStructCreate($tStruct))

; incorrect way of defining collection of structures
$tStruct &= ';' & $tStruct
_dlldisplay(DllStructCreate($tStruct))

; correct way - notice the alignment difference
$tStructForCollection = 'struct;byte Enabled;dword Value;word Idx;endstruct'
$tStructForCollection &= ';' & $tStructForCollection
_dlldisplay(DllStructCreate($tStructForCollection))

Outputs:

byte Enabled;dword Value
 _______________________________________________________
| #   | Offset       | Type          | Size   | Value   | 
|¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯|
| -   | 0x04840BD8   | <struct>      | 0      | -       | 
| 1   | 0            | byte[1]       | 1      | 0       | 
| -   | -            | <alignment>   | 3      | -       | <<<
| 2   | 4            | uint          | 4      | 0       | 
| -   | 0x04840BE0   | <endstruct>   | 8      | -       | 
 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

byte Enabled;dword Value;word Idx
 _______________________________________________________
| #   | Offset       | Type          | Size   | Value   | 
|¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯|
| -   | 0x0484A8C0   | <struct>      | 0      | -       | 
| 1   | 0            | byte[1]       | 1      | 0       | 
| -   | -            | <alignment>   | 3      | -       | <<<
| 2   | 4            | uint          | 4      | 0       | 
| 3   | 8            | ushort        | 2      | 0       | 
| -   | -            | <alignment>   | 2      | -       | <<<
| -   | 0x0484A8CC   | <endstruct>   | 12     | -       | 
 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

byte Enabled;dword Value;word Idx;byte Enabled;dword Value;word Idx
 _______________________________________________________
| #   | Offset       | Type          | Size   | Value   | 
|¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯|
| -   | 0x047FD050   | <struct>      | 0      | -       | 
| 1   | 0            | byte[1]       | 1      | 0       | 
| -   | -            | <alignment>   | 3      | -       | <<<
| 2   | 4            | uint          | 4      | 0       | 
| 3   | 8            | ushort        | 2      | 0       | 
| 4   | 10           | byte[1]       | 1      | 0       | 
| -   | -            | <alignment>   | 1      | -       | <<<
| 5   | 12           | uint          | 4      | 0       | 
| 6   | 16           | ushort        | 2      | 0       | 
| -   | -            | <alignment>   | 2      | -       | <<<
| -   | 0x047FD064   | <endstruct>   | 20     | -       | 
 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

struct;byte Enabled;dword Value;word Idx;endstruct;struct;byte Enabled;dword Value;word Idx;endstruct
 _______________________________________________________
| #   | Offset       | Type          | Size   | Value   | 
|¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯|
| -   | 0x047FD1D0   | <struct>      | 0      | -       | 
| 1   | 0            | byte[1]       | 1      | 0       | 
| -   | -            | <alignment>   | 3      | -       | <<<
| 2   | 4            | uint          | 4      | 0       | 
| 3   | 8            | ushort        | 2      | 0       | 
| -   | -            | <alignment>   | 2      | -       | <<<
| 4   | 12           | byte[1]       | 1      | 0       | 
| -   | -            | <alignment>   | 3      | -       | <<<
| 5   | 16           | uint          | 4      | 0       | 
| 6   | 20           | ushort        | 2      | 0       | 
| -   | -            | <alignment>   | 2      | -       | <<<
| -   | 0x047FD1E8   | <endstruct>   | 24     | -       | 
 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

 

Right here was my first introduction to what alignment/padding was and I totally thought @trancexx was fucking with me. Even after she explained it and @wraithdu gave me the fix, I still didnt completely understand what we were talking about. At the time struct/endstruct didn't exist so that didnt help things. The last two structs above showing incorrect/correct collections shows exactly the problem I was having back then and how the alignment ends up different. 

 

Edited by Beege
Link to post
Share on other sites

You're correct: it's just my lazyness

 

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

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
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • 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 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).
    • By tukangusil7
      From the documentation of DllStructCreate(), it can be called using the following syntax:
      DllStructCreate(Struct, Pointer) Struct A string representing the structure to create (See Remarks). Pointer [optional] If supplied the struct will not allocate memory but use the pointer supplied. Would somebody here explain the usage of Pointer parameter clearly with some examples?
      Thank's in advance.
    • By c.haslam
      In the code that follows, it appears that DllStructCreate() is not allocating memory in
      $tag = 'byte val['&$iLength&']' . . Static Local $tvalue = DllStructCreate($tag) Running the code below, the problem does not show, but it does show in a much longer script: there _GDIPlus_ImageSaveToFile only writes about 30K bytes when it should write about 1MB, which it does when the code is
      $tag = 'char val['&$iLength&']' . . Static Local $tvalue = DllStructCreate($tag) It should write about 1 MB.
      I suggest caution in running the code below. On my PC, it caused a second instance of SciTE to appear at the top left of the Desktop, showing only the title bar, with a width of only approximately 200 pixels! Then rebooting the PC showed this at login. Further, double-clicking on the SciTE shortcut on the Desktop showed SciTE in the same way! (After running Regedit, and searching for SciTE, the shortcut behaves normally.)
      I would appreciate help in determining whether or not there is a bug in DLLStructCreate, preferably a way which does not clobber Windows. Of course, It is possible that there is a bug in my code.
      I have made $tvalue Static in the hope that this might make the code run properly. Doing this did not help.
      My code is based on code written by Authenticity and ChrisL.
      #include <GDIPlus.au3> #include <Array.au3> Opt('MustDeclareVars',1) ; Property Item structure Global Const $tagGDIPPROPERTYITEM = _ "uint id;" & _ ; ID of this property "ulong length;" & _ ; Length of the property value, in bytes "word type;" & _ ; Type of the value, as one of TAG_TYPE_XXX constants "ptr pvalue;" ; pointer to property value ; Image property types constants ; Ref: https://www.media.mit.edu/pia/Research/deepview/exif.html Global Const $GDIP_PROPERTYTAGTYPEUBYTE = 1 Global Const $GDIP_PROPERTYTAGTYPEASCII = 2 Global Const $GDIP_PROPERTYTAGTYPEUSHORT = 3 Global Const $GDIP_PROPERTYTAGTYPEULONG = 4 Global Const $GDIP_PROPERTYTAGTYPEURATIONAL = 5 Global Const $GDIP_PROPERTYTAGTYPESBYTE = 6 Global Const $GDIP_PROPERTYTAGTYPEUNDEFINED = 7 Global Const $GDIP_PROPERTYTAGTYPESSHORT = 8 Global Const $GDIP_PROPERTYTAGTYPESLONG = 9 Global Const $GDIP_PROPERTYTAGTYPESRATIONAL = 10 Global Const $GDIP_PROPERTYTAGTYPESFLOAT = 11 Global Const $GDIP_PROPERTYTAGTYPEDFLOAT = 12 main() Func main() _GDIPlus_Startup() Local $hImage = _GDIPlus_ImageLoadFromFile('H:\temp\AP test data\DSC00824 - Copy.jpg') Local $ar = _GDIPlus_ImageGetAllPropertyItemsEx($hImage) Local $propsAr[UBound($ar,1)-1][5],$vec,$j=-1 For $i = 1 To $ar[0][0] If $ar[$i][3]<>0 Then ; pValue -- for Sony! $j += 1 $propsAr[$j][0] = $ar[$i][0] ; id $propsAr[$j][1] = $ar[$i][1] ; length $propsAr[$j][2] =$ar[$i][2]; type $vec = _GDIPlus_ImageGetPropertyItemValue($ar[$i][1],$ar[$i][2],$ar[$i][3]) $propsAr[$j][3] = $vec[0] ; val1 Switch $ar[$i][2] Case 5,10 ; $GDIP_PROPERTYTAGTYPEURATIONAL,$GDIP_PROPERTYTAGTYPESRATIONAL $propsAr[$j][4] = $vec[1] Case Else $propsAr[$j][4] = '' EndSwitch EndIf Next ReDim $propsAr[$j+1][5] For $i = 0 To UBound($propsAr,1)-1 Switch $propsAr[$i][2] ; type Case 5,10 ; $GDIP_PROPERTYTAGTYPEURATIONAL,$GDIP_PROPERTYTAGTYPESRATIONAL _GDIPlus_ImageSetPropertyItemEx($hImage,$propsAr[$i][0],$propsAr[$i][1], _ $propsAr[$i][2],$propsAr[$i][3],$propsAr[$i][4]) Case Else _GDIPlus_ImageSetPropertyItemEx($hImage,$propsAr[$i][0],$propsAr[$i][1], _ $propsAr[$i][2],$propsAr[$i][3]) EndSwitch Next _GDIPlus_ImageSaveToFile($hImage,'H:\b\1.jpg') _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() EndFunc Func _GDIPlus_ImageGetAllPropertyItemsEx($hImage) Local $iI, $iCount, $tBuffer, $pBuffer, $iBuffer, $tPropertyItem, $aSize, $aPropertyItems[1][1], $aResult $aSize = _GDIPlus_ImageGetPropertySize($hImage) If @error Then Return SetError(@error, @extended, -1) $iBuffer = $aSize[0] $tBuffer = DllStructCreate("byte[" & $iBuffer & "]") $pBuffer = DllStructGetPtr($tBuffer) $iCount = $aSize[1] $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetAllPropertyItems", "hwnd", $hImage, "uint", $iBuffer, "uint", $iCount, "ptr", $pBuffer) If @error Then Return SetError(@error, @extended, -1) If $aResult[0] Then Return SetError(10, $aResult[0], False) ReDim $aPropertyItems[$iCount + 1][4] $aPropertyItems[0][0] = $iCount For $iI = 1 To $iCount $tPropertyItem = DllStructCreate($tagGDIPPROPERTYITEM, $pBuffer) $aPropertyItems[$iI][0] = DllStructGetData($tPropertyItem, "id") $aPropertyItems[$iI][1] = DllStructGetData($tPropertyItem, "length") $aPropertyItems[$iI][2] = DllStructGetData($tPropertyItem, "type") $aPropertyItems[$iI][3] = DllStructGetData($tPropertyItem, "pvalue") $pBuffer += DllStructGetSize($tPropertyItem) Next Return $aPropertyItems EndFunc Func _GDIPlus_ImageGetPropertyItemValue($iLength, $iType, $pValue) Static Local $tvalue Switch $iType Case 1,6 ; $GDIP_PROPERTYTAGTYPEUBYTE,$GDIP_PROPERTYTAGTYPESBYTE $tvalue = DllStructCreate('byte val',$pValue) Case 2 ; $GDIP_PROPERTYTAGTYPEASCII $tvalue = DllStructCreate('char val['&$iLength&']',$pValue) Case 3 ; $GDIP_PROPERTYTAGTYPEUSHORT $tvalue = DllStructCreate('ushort val',$pValue) Case 4 ; $GDIP_PROPERTYTAGTYPEULONG $tvalue = DllStructCreate('ulong val',$pValue) Case 5 ; $GDIP_PROPERTYTAGTYPEURATIONAL $tvalue = DllStructCreate('ulong val1;ulong val2',$pValue) Case 7 ; $GDIP_PROPERTYTAGTYPEUNDEFINED ; undefined, per specification, but may be a long but is sometimes a string $tvalue = DllStructCreate('byte val['&$ilength&']',$pValue) ; see _GDIPlus_ImageSetPropertyItemEx ;~ $tvalue = DllStructCreate('char val['&$ilength&']',$pValue) Case 8 ; $GDIP_PROPERTYTAGTYPESSHORT $tvalue = DllStructCreate('short val',$pValue) Case 9 ; $GDIP_PROPERTYTAGTYPEULONG $tvalue = DllStructCreate('ulong val',$pValue) Case 10 ; $GDIP_PROPERTYTAGTYPESRATIONAL $tvalue = DllStructCreate('ulong val1;ulong val2',$pValue) Case 11 ; $GDIP_PROPERTYTAGTYPESFLOAT $tvalue = DllStructCreate('float val',$pValue) Case 12 ; $GDIP_PROPERTYTAGTYPEDFLOAT $tvalue = DllStructCreate('double val',$pValue) EndSwitch If @error Then Return SetError(@error,0,-1) Switch $iType Case 5,10 ; $GDIP_PROPERTYTAGTYPEURATIONAL,$GDIP_PROPERTYTAGTYPESRATIONAL Local $aRet[2] $aRet[0] = DllStructGetData($tvalue,'val1') $aRet[1] = DllStructGetData($tvalue,'val2') Case Else Local $aRet[1] $aRet[0] = DllStructGetData($tvalue,'val') EndSwitch Return $aRet EndFunc Func _GDIPlus_ImageGetPropertySize($hImage) Local $aSize[2], $aResult $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetPropertySize", "hwnd", $hImage, "uint*", 0, "uint*", 0) If @error Then Return SetError(@error, @extended, -1) $aSize[0] = $aResult[2] $aSize[1] = $aResult[3] Return $aSize EndFunc ;==>_GDIPlus_ImageGetPropertySize Func _GDIPlus_ImageSetPropertyItemEx($hImage,$id,$iLength,$iType,$value1,$value2=-1) Local $tProp = DllStructCreate($tagGDIPPROPERTYITEM) DllStructSetData($tProp,'id',$id) DllStructSetData($tProp,'type',$itype) DllStructSetData($tProp,'length',$ilength) Local $tag Switch $iType Case $GDIP_PROPERTYTAGTYPEUBYTE,$GDIP_PROPERTYTAGTYPESBYTE $tag = 'byte val' Case $GDIP_PROPERTYTAGTYPEASCII $tag = 'char val['&$iLength&']' Case $GDIP_PROPERTYTAGTYPEUSHORT $tag = 'ushort val' Case $GDIP_PROPERTYTAGTYPEULONG $tag = 'ulong val' Case $GDIP_PROPERTYTAGTYPEURATIONAL $tag = 'ulong val1;ulong val2' Case $GDIP_PROPERTYTAGTYPEUNDEFINED ; undefined, per specification, but may be a long but is sometimes a string $tag = 'byte val['&$iLength&']' ; causes saving to jpeg to write junk ;~ $tag = 'char val['&$iLength&']' Case $GDIP_PROPERTYTAGTYPESSHORT $tag = 'short val' Case $GDIP_PROPERTYTAGTYPEULONG $tag = 'ulong val' Case $GDIP_PROPERTYTAGTYPESRATIONAL $tag = 'long val1;long val2' Case $GDIP_PROPERTYTAGTYPESFLOAT $tag = 'float val' Case $GDIP_PROPERTYTAGTYPEDFLOAT $tag = 'double val' EndSwitch Static Local $tvalue = DllStructCreate($tag) Switch $iType Case $GDIP_PROPERTYTAGTYPEURATIONAL,$GDIP_PROPERTYTAGTYPESRATIONAL DllStructSetData($tvalue,'val1',$value1) DllStructSetData($tvalue,'val2',$value2) Case Else DllStructSetData($tvalue,1,$value1) EndSwitch DllStructSetData($tProp,'pvalue',DllStructGetPtr($tvalue)) Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipSetPropertyItem", "hwnd", $hImage, "ptr", _ DllStructGetPtr($tProp)) If @error Then Return SetError(@error, @extended, -1) If $aResult[0] Then Return SetError(10, $aResult[0], -1) Return $aResult[0] = 0 EndFunc I have seen $iLength be as much as 37 KB for $GDIP_PROPERTYTAGTYPEUNDEFINED.
      Is there is a bug, how can this be demonstrated to the developers in a few lines of code (without clobbering Windows)?
       
×
×
  • Create New...