Jump to content
Sign in to follow this  
tukangusil7

How to interpret raw bytes as SID_AND_ATTRIBUTES struct?

Recommended Posts

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

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

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

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

 

Share this post


Link to post
Share on other sites

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

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

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

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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Luigi
      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 ]  
    • 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
      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...