Jump to content
tukangusil7

How to interpret raw bytes as SID_AND_ATTRIBUTES struct?

Recommended Posts

tukangusil7
Posted (edited)

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.

  1. Have I got a correct value of Attributes member of SID_AND_ATTRIBUTES struct?
  2. 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.

Edited by tukangusil7

Share this post


Link to post
Share on other sites
Bilgus

maybe have a look at 

_Security__GetTokenInformation in security.au3 it's already getting the length of the struct when its created

also since the struct already exists you could get the byte length with DllStructGetSize ( Struct )

Share this post


Link to post
Share on other sites
tukangusil7
Posted (edited)

My comments below based on my way of thinking in AutoIt world, which can be wrong, because I'm still a newbie in AutoIt.

I think knowing the size of SID_AND_ATTRIBUTES struct won't help in interpreting bytes as SID_AND_ATTRIBUTES struct because the struct has the SID member that has an arbitrary length of bytes.

Even if I can make use the size of SID_AND_ATTRIBUTES struct to interpret the bytes as follows:

Local Const $SIZE_OF_PTR = DllStructGetSize(DllStructCreate("PTR"))  ; The size of a pointer
Local $iSidBytesLen = DllStructGetSize($tRawTokenInfo) - $SIZE_OF_PTR - 4  ; 4 is size of "ULONG Attributes"
Local $tagSID_AND_ATTRIBUTES = "align 4; PTR Sid; BYTE[" & $iSidBytesLen & "]; ULONG Attributes"
Local $tSID_AND_ATTRIBUTES = DllStructCreate($tagSID_AND_ATTRIBUTES, $pRawTokenInfo)

that way will make my life harder when I want to (for example) interpret the bytes returned by _Security__GetTokenInformation() as TOKEN_ACCESS_INFORMATION struct, which is a more complex struct.

OK, to make it simpler, I just need a confirmation whether the following portion of my GetTokenInfoUser() above will return a correct result:

; 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

I need a confirmation whether it is a right way to interpret a struct whose one of its members has an arbitrary bytes length.

Thanks in advanced.

Edited by tukangusil7

Share this post


Link to post
Share on other sites
Danyfirex

Hello You need to declare _SID_AND_ATTRIBUTES like this:

 

"ptr psid;dword Attributes"

 

The you can the correct Windows API to manage the SID

So then you can do this:

#include <SecurityConstants.au3>
#include <WinAPI.au3>

Example_TokInfo()

Func Example_TokInfo()
    Local $hProcess = _WinAPI_GetCurrentProcess()
    If @error Then Return ; check for possible errors

    Local $hToken = _Security__OpenProcessToken($hProcess, $TOKEN_ALL_ACCESS)
    ; If token is get...
    If $hToken Then

        Local Const $sTag_SID_AND_ATTRIBUTES = "ptr psid;dword Attributes"
        ; Get information about the type of this token:
        Local $tInfo = _Security__GetTokenInformation($hToken, $TOKENUSER)

        Local $tsa = DllStructCreate($sTag_SID_AND_ATTRIBUTES, DllStructGetPtr($tInfo))
        Local $pSID = $tsa.psid

        Local $aCall = DllCall("Advapi32.dll", "dword", "GetLengthSid", "ptr", $pSID)
        Local $iSidLength = $aCall[0]

        $aCall = DllCall("Advapi32.dll", "bool", "IsValidSid", "ptr", $pSID)
        Local $IsValidSid = $aCall[0]

        If $IsValidSid Then
            Local $tBytes = DllStructCreate("byte[" & $iSidLength & "]", $pSID)
            ConsoleWrite("Sid Hex: " & DllStructGetData($tBytes, 1) & @CRLF)
        EndIf

        ; Close the token handle
        _WinAPI_CloseHandle($hToken)
    EndIf
EndFunc   ;==>Example_TokInfo

Saludos

 

  • Thanks 1

Share this post


Link to post
Share on other sites
Bilgus

sorry I missed the second pointer 

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)

I believe he has pretty much what you have there danyfirex

also I'm guessing (.) dot access of structs is here to stay its been there over 4 years since you asked??

Thats wonderful news!

#include <SecurityConstants.au3>
#include <WinAPI.au3>

Example_TokInfo()

Func Example_TokInfo()
    Local $hProcess = _WinAPI_GetCurrentProcess()
    If @error Then Return ; check for possible errors

    Local $hToken = _Security__OpenProcessToken($hProcess, $TOKEN_ALL_ACCESS)
    ; If token is get...
    If $hToken Then

        Local Const $sTag_SID_AND_ATTRIBUTES = "ptr psid;dword Attributes"
        ; Get information about the type of this token:
        Local $tInfo = _Security__GetTokenInformation($hToken, $TOKENUSER)

        Local $tsa = DllStructCreate($sTag_SID_AND_ATTRIBUTES, DllStructGetPtr($tInfo))
        Local $pSid = $tsa.psid

        Local $IsValidSid = _Security__IsValidSid($pSid)
        Local $tBytes, $iSidLength
        If $IsValidSid Then
            $iSidLength = _Security__GetLengthSid($pSid)
            $tBytes = DllStructCreate("ALIGN 4;byte[" & $iSidLength & "]", $pSid)
            ConsoleWrite("Sid Hex: " & DllStructGetData($tBytes, 1) & @CRLF)
            ConsoleWrite("Sid: " & _Security__SidToStringSid ($pSid) & @CRLF)
        EndIf

        ; Close the token handle
        _WinAPI_CloseHandle($hToken)
    EndIf
    Return
EndFunc   ;==>Example_TokInfo

I'm still not sure what having the raw struct does for you I was under the impression that you were to pass the pointer directly or convert the sid to a string first and use that form in other functions

@tukangusil7 I think you will have to supply more information as far as what you want to do with this data

 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
tukangusil7
Posted (edited)

Thanks to you both, Bilgus and Danyfirex :). I will investigate the inputs from both of you later because I'm having a toothache right now :'(.

What I can say right now is that I'm creating a wrapper for GetTokenInformation(), something similar to _Security__GetTokenInformation(), but my UDF will return the requested token information in form of an array that represents information from the requested struct, instead of just returning raw bytes that need to be interpreted later. The goal is to let the complicated works done in the UDF instead of troubling the caller.

Edited by tukangusil7
  • Like 1

Share this post


Link to post
Share on other sites
tukangusil7
Posted (edited)

If you both do not mind, for completeness, will you also include the value of Attributes member of SID_AND_ATTRIBUTES struct in both answers to be compared to my code, please? I learn a lot from both answers, especially the use of dot operator, among other things.

Thank you for your attention.

Edited by tukangusil7

Share this post


Link to post
Share on other sites
tukangusil7
Posted (edited)

Bilgus, I see, how could I missed the sentence, "There are currently no attributes defined for user security identifiers (SIDs)."

It turns out that I had provided an improper example. Thanks anyway.

Edited by tukangusil7
  • Thanks 1

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

    • tukangusil7
      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).
    • tukangusil7
      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.
    • c.haslam
      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)?
       
    • InunoTaishou
      By InunoTaishou
      Struggling a bit to get this GDI+ function converted to AutoIt.
      #include <GDIPlus.au3> _GDIPlus_Startup() Global $hImage = _GDIPlus_ImageLoadFromFile("F:\DCIM\Camera\20170515_111804.jpg") Global $tBufferSize = DllStructCreate("uint") Global $tProperties = DllStructCreate("uint") _GDIPlus_GetPropertySize($hImage, $tBufferSize, $tProperties) Global $tAllItems = DllStructCreate("struct;char[" & DllStructGetData($tBufferSize, 1) & "];endstruct") _GDIPlus_GetAllPropertyItems($hImage, $tBufferSize, $tProperties, $tPropertyItem) _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() Func _GDIPlus_GetAllPropertyItems(ByRef $hImage, Const $tTotalBufferSize, Const $tNumProperties, ByRef $tAllItems) If (Not IsDllStruct($tPropertyItem)) Then Return SetError(-1, 0, "") Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipGetAllPropertyItems", "hwnd", $hImage, "unit", DllStructGetData($tTotalBufferSize, 1), "uint", DllStructGetData($tNumProperties, 1), "ptr", DllStructGetPtr($tAllItems)) If (@error) Then Return SetError(@error, @extended, ConsoleWrite("@Error = " & @error & @LF)) If ($aResult[0]) Then Return SetError($aResult[0], @extended, "") Return $aResult[0] EndFunc ;==>_GDIPlus_GetAllPropertyItems Func _GDIPlus_GetPropertySize(Const ByRef $hImage, ByRef $tTotalBufferSize, ByRef $tNumProperties) If (Not IsDllStruct($tTotalBufferSize)) Then Return SetError(-1, 0, "") If (Not IsDllStruct($tNumProperties)) Then Return SetError(-2, 0, "") Local $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetPropertySize", "hwnd", $hImage, "uint_ptr", DllStructGetPtr($tTotalBufferSize), "uint_ptr", DllStructGetPtr($tNumProperties)) If (@error) Then Return SetError(@error, @extended, "") If ($aResult[0]) Then Return SetError($aResult[0], 0, "") Return $aResult[0] EndFunc ;==>_GDIPlus_GetPropertySize Got the GetPropertySize function to work, gives me the correct buffer size and the property count, but I cannot figure out how to get the struct for the all items.
      Function on MSDN:
      https://msdn.microsoft.com/en-us/library/windows/desktop/ms535372(v=vs.85).aspx
      Struct needed:
      PropertyItem class:
      https://msdn.microsoft.com/en-us/library/windows/desktop/ms534493(v=vs.85).aspx
      Found other topics about this function in other languages where they used a blank string as the buffer, so I tried using a char array, which doesn't work. Just cannot figure out how to create the struct buffer to hold the data.
    • InunoTaishou
      By InunoTaishou
      I know you can store functions in variables but I'm interested in storing functions in structs.
      Global $tWindow = DllStructCreate("hwnd hwnd;ptr delete") $tWindow.hwnd = GUICreate("") ; works Global $pDelete = GUIDelete ; doesn't work $tWindow.delete = GUIDelete ConsoleWrite("Delete using $tWindow.delete: " & $tWindow.delete() & @LF) ConsoleWrite("Delete using $pDelete: " & $pDelete() & @LF) Maybe I'm using the wrong data type for my delete member, I've tried int, dword, ptr, handle, hwnd.
×