Alternate Data Stream Gibberish Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Alternate Data Stream Gibberish

25 Jun 2018, 11:36

Flipeador...I haven't started using AHKv2. Im kind of anti against it, cuz there is no chance I could convert all my scripts to it. Maybe you could keep it v1? Since I know nothing about v2 that makes it too complex for me.
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Alternate Data Stream Gibberish

25 Jun 2018, 11:43

Sorry, but I find AHKv1 horrible to work with GUIs, whenever I have to do a GUI with AHKv1 I'm forced to look at the help file. It's really a pain for me.
If you want to try the script, you can download AHKv2 from this link, you do not have to install anything, just drag the Script to the executable.
The Script is small, I do not think it will be difficult for you to transform it. This is the AHKv2 documentation in case you don't understand something.
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Alternate Data Stream Gibberish

25 Jun 2018, 12:04

Thanks, I have v1 going alongside v2 now...coolness...you are going to kick some ADSManager a**, with that one :mrgreen:
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Alternate Data Stream Gibberish

25 Jun 2018, 12:17

Yes... ADS Manager could improve much more, adding support for Stream Objects. If this issue has not yet been resolved, tell me. :D
:wave:
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Alternate Data Stream Gibberish

25 Jun 2018, 12:42

Flipeador wrote:Yes... ADS Manager could improve much more, adding support for Stream Objects. If this issue has not yet been resolved, tell me.
Which issue do you mean?
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Alternate Data Stream Gibberish

25 Jun 2018, 12:47

I refer to your first message on this topic.
zcooler wrote:I do wonder if anyone might have any ideas on how to get readable results? Applying PS output encoding does not work. The IPropertyStorage interface cannot be scrapped before its possible to read the NTSF file property it has written on thousands of recordings.
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Alternate Data Stream Gibberish

25 Jun 2018, 13:46

Yes, it has been resolved beautifully. Impressive work, Flipeador :bravo:
If only it was possible to get the DocumentSummaryInformation :?: I tested your cleaned up v2 code and it says something about "no statistical data". Is this stream something different from the other two where the content is retrievable? Should some different flag be applied maybe?

For your ADS Viewer in "String view" it would be interesting, in the future, to get the whole string.
:wave:
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Alternate Data Stream Gibberish

25 Jun 2018, 15:34

For your ADS Viewer in "String view" it would be interesting, in the future, to get the whole string.
The Script that I put to you is just a poor example. I only take a few minutes (5-10).
I limited the length of the string to avoid loading very large files (eg 1GB) in memory. Surely you can implement an intelligent verification.
If only it was possible to get the DocumentSummaryInformation :?: I tested your cleaned up v2 code and it says something about "no statistical data". Is this stream something different from the other two where the content is retrievable? Should some different flag be applied maybe?
Yes, I saw it, and honestly I have no idea. Apparently, the object is damaged or not correct, I do not see anything wrong in my code. Until next weekend I will not be able to review anything else.
Yes, it has been resolved beautifully. Impressive work, Flipeador
:)


Edit*
zcooler wrote:For your ADS Viewer in "String view" it would be interesting, in the future, to get the whole string.
I think you were referring to when the Stream contains an Stream Object. To "decipher" this string you have to use the interfaces.
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Alternate Data Stream Gibberish

25 Jun 2018, 16:04

Flipeador wrote:
If only it was possible to get the DocumentSummaryInformation :?: I tested your cleaned up v2 code and it says something about "no statistical data". Is this stream something different from the other two where the content is retrievable? Should some different flag be applied maybe?
Yes, I saw it, and honestly I have no idea. Apparently, the object is damaged or not correct, I do not see anything wrong in my code. Until next weekend I will not be able to review anything else.
Thanks, Flipeador :) Vaccation time is coming soon, so this has to be long term. No stress. I tried 5 other recordings with the same iproperty streams and the script can't read DocumentSummaryInformation on any of them. Ultimately there is two data i need from that stream the "Series" and the "EPGID" properties.

Best regards from
zcooler
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Alternate Data Stream Gibberish

26 Jun 2018, 05:07

Hi Flipeador,

IPropertySetStorage:
Note There is an exception to the above in The DocumentSummaryInformation and UserDefined property set. This property set is unique in that it may have two property set sections in a single underlying stream. This property set is described in The DocumentSummaryInformation and UserDefined Property Sets. The first section is the DocumentSummaryInformation property set. The second section is the UserDefined property set. Each section is identified by a unique format identifier (FMTID). For example, FMTID_DocSummaryInformation and FMTID_UserDefined property set. The fact that these two property sets can exist in a single stream affects the behavior of the IPropertySetStorage interface.

When IPropertySetStorage::Create is called to create the UserDefined property set, the first section is created automatically. Once the FMTID_UserDefinedProperties is created, FMTID_DocSummaryInformation need not be created, but can be operend with a call to IPropertySetStorage::Open. Creating the first section does not automatically create the second section and it is not possible to open both sections simultaneously.

Calling IPropertySetStorage::Delete, to delete the first section, causes both sections to be deleted. In other words, calling IPropertySetStorage::Delete with FMTID_DocSummaryInformation causes both that section and the FMTID_UserDefinedProperties section to be deleted. However, deleting the second section does not automatically delete the first section.

When IPropertySetStorage::Enum is used to enumerate property sets, the UserDefined property set is not enumerated.
EnumAll Sample:

Code: Select all

        // Special-case handling for the UserDefined property set:
        // This property set actually lives inside the well-known
        // DocumentSummaryInformation property set. It is the only
        // property set which is allowed to live inside another
        // (and exists for legacy compatibility).  It does not get
        // included in a normal enumeration, so verify that it is
        // done explicitly. Look for it when the end of the
        // enumerator is reached.

        hr = pPropSetStg->Open( FMTID_UserDefinedProperties,
                                STGM_READ | STGM_SHARE_EXCLUSIVE,
                                &pPropStg );
        if( SUCCEEDED(hr) )
        {
            DisplayPropertySet( FMTID_UserDefinedProperties,
                                pwszStorageName,
                                pPropStg );
            pPropStg->Release();
                                    pPropStg = NULL;
        }
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Alternate Data Stream Gibberish

26 Jun 2018, 08:51

Greetings oh great Just me :D
Saves the day for a lot of us still you are :mrgreen:

Yes I noticed this:

Code: Select all

; FMTID_DocSummaryInformation = {D5CDD502-2E9C-101B-9397-08002B2CF9AE}
    ; FMTID_UserDefinedProperties = {D5CDD505-2E9C-101B-9397-08002B2CF9AE} 
...and thought it was strange they are sharing the same GUID, but I could not connect the dots...cuz im a hopeless moron when it comes to COM and slow learner of coding in general ;) :lol:
I think Flipeador will crack this case easily with that info you provided when he gets the time. Thank you Just me :wave:
Flipeador wrote:Edit*
zcooler wrote:For your ADS Viewer in "String view" it would be interesting, in the future, to get the whole string.
I think you were referring to when the Stream contains an Stream Object. To "decipher" this string you have to use the interfaces.
Of course but meant it would be cool if your ADS Viewer does use the interfaces and decipher Stream Objects in string view. Then it does something that no available ADS tool can do, which makes it stand out and be awesome :)
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Alternate Data Stream Gibberish

26 Jun 2018, 08:59

Thanks just me!. Now I understand perfectly what is happening. I will correct it this weekend.

Yes, it would be interesting to create my own ADS Viewer that supports Stream Objects, I'll try.
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Alternate Data Stream Gibberish

26 Jun 2018, 09:56

Flipeador wrote:Yes, it would be interesting to create my own ADS Viewer that supports Stream Objects, I'll try.
OH YES :D That viewer would definitely be something to include in my own tool Im going to build (mainly a batchtool for thousands of recordings to extract the stream objects and delete them and then put back native unicode ADS). This COM property system is an unbelievable overcomplicated beast and it would be a joy to get rid of it entirely.
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Alternate Data Stream Gibberish

29 Jun 2018, 23:35

I have already fixed it: https://autohotkey.com/boards/viewtopic ... 58#p225658.
I'll see the ADS Viewer.
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Alternate Data Stream Gibberish

30 Jun 2018, 02:18

Flipeador wrote:I have already fixed it: https://autohotkey.com/boards/viewtopic ... 58#p225658.
I'll see the ADS Viewer.
:bravo: Excellente :D
I had lesser luck using the code (slightly modified) for v1. aHK_H v1 fires this errormsg:
---------------------------
AutoHotkey
---------------------------
Error: CONTINUABLE EXCEPTION_ACCESS_VIOLATION

Mouse and Keyboard hooks have been disabled.

- Press yes to exit thread and continue execution.
- Press no to continue thread (debug).
- Press cancel to exit application.

Exception was caused in thread id: 14844
Line: 121
LineFile: F:\Ny mapp\proptest.ahk
---------------------------
Ja Nej Avbryt
---------------------------

I slapped on a few tweaks to make it v1 compatible, that I know of, but I get the CONTINUABLE EXCEPTION_ACCESS_VIOLATION anyway :( There is probably some v2 "trickery" left that I missed ;)

Code: Select all

fileselectfile Filename
;Filename := FileSelect()

; opens an existing root storage object in the file system
IPropertySetStorage := GetPropSetStorage(Filename)
If (!IPropertySetStorage)
{
    MsgBox "IPropertySetStorage ERROR " . Format("0x{:08X}", ErrorLevel)
    ExitApp
}

Info := ""

; retrieves the property sets stored in this property set storage
PropertySets := EnumPropSetStorage(IPropertySetStorage)
For Each, STATPROPSETSTG in PropertySets
{
    Info .= "STATPROPSETSTG.fmtid "    . StringFromCLSID(STATPROPSETSTG.fmtid) . "`n"      ; format identifier (FMTID) of the property set
    Info .= "STATPROPSETSTG.clsid "    . StringFromCLSID(STATPROPSETSTG.clsid) . "`n"
    Info .= "STATPROPSETSTG.grfFlags " . STATPROPSETSTG.grfFlags               . "`n`n"

    ; opens a property set contained in the property set storage object
    IPropertyStorage := PropSetStorage_Open(IPropertySetStorage, STATPROPSETSTG.fmtid)
    If (IPropertyStorage)
    {
        ; get statistical data in the property set
        StatisticalData := EnumPropStorage(IPropertyStorage)
        If (!ObjLength(StatisticalData))
            Info .= "> no statistical data <`n"
        For Each, STATPROPSTG in StatisticalData
        {
            Info .= "STATPROPSTG.lpwstrName " . STATPROPSTG.lpwstrName . "`n"
            Info .= "STATPROPSTG.propid "     . STATPROPSTG.propid     . "`n"
            Info .= "STATPROPSTG.vt "         . STATPROPSTG.vt         . "`n"

            ; retrieves any existing string name for the specified property ID
            Info .= "PropertyName "           . PropStorage_ReadPropertyName(IPropertyStorage, STATPROPSTG.propid) . " (" . ErrorLevel . ")`n"

            ; reads the property value
            PROPVARIANT := PropStorage_Read(IPropertyStorage, STATPROPSTG.propid)
            If (PROPVARIANT)
            {
                Info .= "PROPVARIANT.vt " . PROPVARIANT.vt . "`n"
                If (PROPVARIANT.vt == 30 || PROPVARIANT.vt == 31)    ; VT_LPSTR = 30 | VT_LPWSTR = 31
                    Info .= "`n" . StrGet(PROPVARIANT.ptr, PROPVARIANT.vt == 30 ? "UTF-8" : "UTF-16") . "`n`n"
                Else
                    Info .= "`n< no string >`n`n"
                PropVariantClear(PROPVARIANT)
            }
        }
        ObjRelease(IPropertyStorage)
    }

    Info .= "`n`n`n----------------------`n`n`n`n"
}

; special-case handling for the UserDefined property set
CLSID := ""
IPropertyStorage := PropSetStorage_Open(IPropertySetStorage, CLSIDFromString("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", CLSID))
If (IPropertyStorage)
{
    Info .= "STATPROPSETSTG.fmtid "    . StringFromCLSID(&CLSID) . " (DocumentSummaryInformation)`n`n"      ; format identifier (FMTID) of the property set

    StatisticalData := EnumPropStorage(IPropertyStorage)
    If (!ObjLength(StatisticalData))
        Info .= "> no statistical data <`n"
    For Each, STATPROPSTG in StatisticalData
    {
        Info .= "STATPROPSTG.lpwstrName " . STATPROPSTG.lpwstrName . "`n"
        Info .= "STATPROPSTG.propid "     . STATPROPSTG.propid     . "`n"
        Info .= "STATPROPSTG.vt "         . STATPROPSTG.vt         . "`n"

        Info .= "PropertyName "           . PropStorage_ReadPropertyName(IPropertyStorage, STATPROPSTG.propid) . " (" . ErrorLevel . ")`n"

        PROPVARIANT := PropStorage_Read(IPropertyStorage, STATPROPSTG.propid)
        If (PROPVARIANT)
        {
            Info .= "PROPVARIANT.vt " . PROPVARIANT.vt . "`n"
            If (PROPVARIANT.vt == 30 || PROPVARIANT.vt == 31)    ; VT_LPSTR = 30 | VT_LPWSTR = 31
                Info .= "`n" . StrGet(PROPVARIANT.ptr, PROPVARIANT.vt == 30 ? "UTF-8" : "UTF-16") . "`n`n"
            Else
                Info .= "`n< no string >`n`n"
            PropVariantClear(PROPVARIANT)
        }
    }
    ObjRelease(IPropertyStorage)
}

ObjRelease(IPropertySetStorage)
FileOpen(A_Desktop . "\~tmp.txt", "w", "UTF-16").Write(Info)
;Run(A_Desktop . "\~tmp.txt")
Run, % A_Desktop . "\~tmp.txt"
ExitApp





GetPropSetStorage(Filename, AccessMode := 0x10)
{
    Local GUID := "", IPropertySetStorage := 0
    VarSetCapacity(GUID, 16)
    DllCall("Ole32.dll\CLSIDFromString", "Str", "{0000013A-0000-0000-C000-000000000046}", "UPtr", &GUID, "UInt")

    ; StgOpenStorageEx function
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380342(v=vs.85).aspx
    ; STGFMT_ANY = 4
    ErrorLevel := DllCall("Ole32.dll\StgOpenStorageEx", "UPtr", &Filename, "UInt", AccessMode, "Int", 4, "UInt", 0, "UPtr", 0, "UPtr", 0, "UPtr", &GUID, "UPtrP", IPropertySetStorage, "UInt")
    Return IPropertySetStorage
}

EnumPropSetStorage(IPropertySetStorage)
{
    ; IPropertySetStorage::Enum method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379960(v=vs.85).aspx
    Local IEnumSTATPROPSETSTG := 0
    If (ErrorLevel := DllCall(NumGet(NumGet(IPropertySetStorage)+6*A_PtrSize), "UPtr", IPropertySetStorage, "UPtrP", IEnumSTATPROPSETSTG, "UInt"))
        Return FALSE

    ; STATPROPSETSTG structure
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380317(v=vs.85).aspx
    Local PropertySets := [ {Buffer: ""} ], i := 1, Address := 0
    ObjSetCapacity(PropertySets[i], "Buffer", 64)    ; sizeof STATPROPSETSTG = 64 | PropertySets.Buffer = struct STATPROPSETSTG

    ; IEnumSTATPROPSETSTG::Next method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379202(v=vs.85).aspx
    While (!DllCall(NumGet(NumGet(IEnumSTATPROPSETSTG)+3*A_PtrSize), "UPtr", IEnumSTATPROPSETSTG, "UInt", 1, "UPtr", Address:=ObjGetAddress(PropertySets[i], "Buffer"), "UPtr", 0, "UInt"))
    {
        ObjRawSet(PropertySets[i], "fmtid", Address)                          ; FMTID    STATPROPSETSTG.fmtid    (FMTID of the current property set when created)
        ObjRawSet(PropertySets[i], "clsid", Address+16)                       ; CLSID    STATPROPSETSTG.clsid    (CLSID associated with this property set when created or modified)
        ObjRawSet(PropertySets[i], "grfFlags", NumGet(Address+32, "UInt"))    ; DWORD    STATPROPSETSTG.grfFlags (https://msdn.microsoft.com/en-us/library/windows/desktop/aa380069(v=vs.85).aspx)
        ObjRawSet(PropertySets[i], "mtime", Address+40)                       ; FILETIME STATPROPSETSTG.mtime    (time in Universal Coordinated Time (UTC) when the property set was last modified)
        ObjRawSet(PropertySets[i], "ctime", Address+48)                       ; FILETIME STATPROPSETSTG.ctime    (time in UTC when this property set was created)
        ObjRawSet(PropertySets[i], "atime", Address+56)                       ; FILETIME STATPROPSETSTG.atime    (Time in UTC when this property set was last accessed)
        ObjSetCapacity(PropertySets[i:=ObjPush(PropertySets, {Buffer: ""})], "Buffer", 64)    ; new struct STATPROPSETSTG
    }

    ObjPop(PropertySets)    ; remove the last STATPROPSETSTG structure
    ObjRelease(IEnumSTATPROPSETSTG)
    Return PropertySets
}

PropSetStorage_Open(IPropertySetStorage, FMTID, AccessMode := 0x10)
{
    ; IPropertySetStorage::Open method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379965(v=vs.85).aspx
    Local IPropertyStorage := 0
    ErrorLevel := DllCall(NumGet(NumGet(IPropertySetStorage)+4*A_PtrSize), "UPtr", IPropertySetStorage, "UPtr", FMTID, "UInt", AccessMode, "UPtrP", IPropertyStorage, "UInt")
    Return IPropertyStorage
}

EnumPropStorage(IPropertyStorage)
{
    ; IPropertyStorage::Enum method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379973(v=vs.85).aspx
    Local IEnumSTATPROPSTG := 0
    If (ErrorLevel := DllCall(NumGet(NumGet(IPropertyStorage)+11*A_PtrSize), "UPtr", IPropertyStorage, "UPtrP", IEnumSTATPROPSTG, "UInt"))
        Return FALSE

    ; STATPROPSTG structure
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380318(v=vs.85).aspx
    Local StatisticalData := [ {Buffer: ""} ], i := 1, Address := 0
    ObjSetCapacity(StatisticalData[i], "Buffer", A_PtrSize+8)    ; sizeof STATPROPSTG = A_PtrSize+8 | StatisticalData.Buffer = struct STATPROPSTG
    

    ; IEnumSTATPROPSTG::Next method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379213(v=vs.85).aspx
    While (!DllCall(NumGet(NumGet(IEnumSTATPROPSTG)+3*A_PtrSize), "UPtr", IEnumSTATPROPSTG, "UInt", 1, "UPtr", Address:=ObjGetAddress(StatisticalData[i], "Buffer"), "UPtr", 0, "UInt"))
    {
        If (NumGet(Address))
            ObjRawSet(StatisticalData[i], "lpwstrName", StrGet(NumGet(Address), "UTF-16"))    ; LPWSTR  STATPROPSTG.lpwstrName (optional string name associated with the property)
          , DllCall("Ole32.dll\CoTaskMemFree", "UPtr", NumGet(Address))                       ;   must be freed using CoTaskMemFree
          , NumPut(ObjGetAddress(StatisticalData[i], "lpwstrName"), Address)                  ;   update STATPROPSTG.lpwstrName with the new pointer because we released the previous one
        ObjRawSet(StatisticalData[i], "propid", NumGet(Address+A_PtrSize, "UInt"))            ; PROPID  STATPROPSTG.propid     (32-bit identifier that uniquely identifies the property)
        ObjRawSet(StatisticalData[i], "vt", NumGet(Address+A_PtrSize+4, "UShort"))            ; VARTYPE STATPROPSTG.vt         (property type)
        ObjSetCapacity(StatisticalData[i:=ObjPush(StatisticalData, {Buffer: ""})], "Buffer", A_PtrSize+8)    ; new struct STATPROPSTG
    }

    ObjPop(StatisticalData)    ; remove the last STATPROPSTG structure
    ObjRelease(IEnumSTATPROPSTG)
    Return StatisticalData
}

PropStorage_Read(IPropertyStorage, PropID)
{
    ; PROPSPEC structure
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380070(v=vs.85).aspx
    Local PROPSPEC := ""
    VarSetCapacity(PROPSPEC, 2*A_PtrSize)
    NumPut(1, &PROPSPEC, "UInt")                     ; ULONG  PROPSPEC.ulKind
    NumPut(PropID, &PROPSPEC + A_PtrSize, "UInt")    ; PROPID PROPSPEC.propid

    ; PROPVARIANT structure
    ; https://docs.microsoft.com/es-es/windows/desktop/api/propidl/ns-propidl-tagpropvariant
    Local PROPVARIANT := {Buffer: ""}
    ObjSetCapacity(PROPVARIANT, "Buffer", A_PtrSize == 4 ? 16 : 24)
    Local Address := ObjGetAddress(PROPVARIANT, "Buffer")

    ; IPropertyStorage::ReadMultiple method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379975(v=vs.85).aspx
    ; S_FALSE = 1 (valid syntax, but no properties were retrieved)
    If (ErrorLevel := DllCall(NumGet(NumGet(IPropertyStorage)+3*A_PtrSize), "UPtr", IPropertyStorage, "UInt", 1, "UPtr", &PROPSPEC, "UPtr", Address, "UInt"))
        Return FALSE

    ObjRawSet(PROPVARIANT, "vt", NumGet(Address, "UInt"))
    ObjRawSet(PROPVARIANT, "ptr", NumGet(Address+8, "UPtr"))

    Return PROPVARIANT
}

PropStorage_ReadPropertyName(IPropertyStorage, PropID)
{
    ; IPropertyStorage::ReadPropertyNames method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379976(v=vs.85).aspx
    Local Buffer := 0
    ErrorLevel := DllCall(NumGet(NumGet(IPropertyStorage)+6*A_PtrSize), "UPtr", IPropertyStorage, "UInt", 1, "UIntP", PropID, "UPtrP", Buffer, "UInt")
    Local R := ""
    If (!ErrorLevel)    ; S_OK
        R := StrGet(Buffer, "UTF-16"), DllCall("Ole32.dll\CoTaskMemFree", "UPtr", Buffer)
    Return R
}

StringFromCLSID(Address)
{
    ; StringFromGUID2 function
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms683893(v=vs.85).aspx
    Local Buffer := ""
    VarSetCapacity(Buffer, (38 + 1) * 2)
    DllCall("Ole32.dll\StringFromGUID2", "UPtr", Address, "Str", Buffer, "Int", 38 + 1)
    Return Buffer
}

CLSIDFromString(String, ByRef CLSID)
{
    ; CLSIDFromString function
    ; https://docs.microsoft.com/en-us/windows/desktop/api/combaseapi/nf-combaseapi-clsidfromstring
    VarSetCapacity(CLSID, 16)
    Return DllCall("Ole32.dll\CLSIDFromString", "Str", String, "UPtr", &CLSID, "UInt") ? 0 : &CLSID
}

PropVariantClear(Address)
{
    Return DllCall("Ole32.dll\PropVariantClear", "UPtr", IsObject(Address) ? ObjGetAddress(Address, "Buffer") : Address)
}
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Alternate Data Stream Gibberish

30 Jun 2018, 14:26

AHKv1:

Code: Select all

fileselectfile Filename,3

; opens an existing root storage object in the file system
IPropertySetStorage := GetPropSetStorage(Filename)
If (!IPropertySetStorage)
{
    MsgBox % "IPropertySetStorage ERROR " . Format("0x{:08X}", ErrorLevel)
    ExitApp
}

Info := ""

; retrieves the property sets stored in this property set storage
PropertySets := EnumPropSetStorage(IPropertySetStorage)
For Each, STATPROPSETSTG in PropertySets
{
    Info .= "STATPROPSETSTG.fmtid "    . StringFromCLSID(STATPROPSETSTG.fmtid) . "`n"      ; format identifier (FMTID) of the property set
    Info .= "STATPROPSETSTG.clsid "    . StringFromCLSID(STATPROPSETSTG.clsid) . "`n"
    Info .= "STATPROPSETSTG.grfFlags " . STATPROPSETSTG.grfFlags               . "`n`n"

    ; opens a property set contained in the property set storage object
    IPropertyStorage := PropSetStorage_Open(IPropertySetStorage, STATPROPSETSTG.fmtid)
    If (IPropertyStorage)
    {
        ; get statistical data in the property set
        StatisticalData := EnumPropStorage(IPropertyStorage)
        If (!ObjLength(StatisticalData))
            Info .= "> no statistical data <`n"
        For Each, STATPROPSTG in StatisticalData
        {
            Info .= "STATPROPSTG.lpwstrName " . STATPROPSTG.lpwstrName . "`n"
            Info .= "STATPROPSTG.propid "     . STATPROPSTG.propid     . "`n"
            Info .= "STATPROPSTG.vt "         . STATPROPSTG.vt         . "`n"

            ; retrieves any existing string name for the specified property ID
            Info .= "PropertyName "           . PropStorage_ReadPropertyName(IPropertyStorage, STATPROPSTG.propid) . " (" . ErrorLevel . ")`n"

            ; reads the property value
            PROPVARIANT := PropStorage_Read(IPropertyStorage, STATPROPSTG.propid)
            If (PROPVARIANT)
            {
                Info .= "PROPVARIANT.vt " . PROPVARIANT.vt . "`n"
                If (PROPVARIANT.vt == 30 || PROPVARIANT.vt == 31)    ; VT_LPSTR = 30 | VT_LPWSTR = 31
                    Info .= "`n" . StrGet(PROPVARIANT.ptr, PROPVARIANT.vt == 30 ? "UTF-8" : "UTF-16") . "`n`n"
                Else
                    Info .= "`n< no string >`n`n"
                PropVariantClear(PROPVARIANT)
            }
        }
        ObjRelease(IPropertyStorage)
    }

    Info .= "`n`n`n----------------------`n`n`n`n"
}

; special-case handling for the UserDefined property set
CLSID := ""
IPropertyStorage := PropSetStorage_Open(IPropertySetStorage, CLSIDFromString("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", CLSID))
If (IPropertyStorage)
{
    Info .= "STATPROPSETSTG.fmtid "    . StringFromCLSID(&CLSID) . "`n`n"      ; format identifier (FMTID) of the property set

    StatisticalData := EnumPropStorage(IPropertyStorage)
    If (!ObjLength(StatisticalData))
        Info .= "> no statistical data <`n"
    For Each, STATPROPSTG in StatisticalData
    {
        Info .= "STATPROPSTG.lpwstrName " . STATPROPSTG.lpwstrName . "`n"
        Info .= "STATPROPSTG.propid "     . STATPROPSTG.propid     . "`n"
        Info .= "STATPROPSTG.vt "         . STATPROPSTG.vt         . "`n"

        Info .= "PropertyName "           . PropStorage_ReadPropertyName(IPropertyStorage, STATPROPSTG.propid) . " (" . ErrorLevel . ")`n"

        PROPVARIANT := PropStorage_Read(IPropertyStorage, STATPROPSTG.propid)
        If (PROPVARIANT)
        {
            Info .= "PROPVARIANT.vt " . PROPVARIANT.vt . "`n"
            If (PROPVARIANT.vt == 30 || PROPVARIANT.vt == 31)    ; VT_LPSTR = 30 | VT_LPWSTR = 31
                Info .= "`n" . StrGet(PROPVARIANT.ptr, PROPVARIANT.vt == 30 ? "UTF-8" : "UTF-16") . "`n`n"
            Else
                Info .= "`n< no string >`n`n"
            PropVariantClear(PROPVARIANT)
        }
    }
    ObjRelease(IPropertyStorage)
}

ObjRelease(IPropertySetStorage)
FileOpen(A_Desktop . "\~tmp.txt", "w", "UTF-16").Write(Info)
Run % A_Desktop . "\~tmp.txt"
ExitApp





GetPropSetStorage(Filename, AccessMode := 0x10)
{
    Local GUID := "", IPropertySetStorage := 0
    VarSetCapacity(GUID, 16)
    DllCall("Ole32.dll\CLSIDFromString", "Str", "{0000013A-0000-0000-C000-000000000046}", "UPtr", &GUID, "UInt")

    ; StgOpenStorageEx function
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380342(v=vs.85).aspx
    ; STGFMT_ANY = 4
    ErrorLevel := DllCall("Ole32.dll\StgOpenStorageEx", "UPtr", &Filename, "UInt", AccessMode, "Int", 4, "UInt", 0, "UPtr", 0, "UPtr", 0, "UPtr", &GUID, "UPtrP", IPropertySetStorage, "UInt")
    Return IPropertySetStorage
}

EnumPropSetStorage(IPropertySetStorage)
{
    ; IPropertySetStorage::Enum method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379960(v=vs.85).aspx
    Local IEnumSTATPROPSETSTG := 0
    If (ErrorLevel := DllCall(NumGet(NumGet(IPropertySetStorage+0)+6*A_PtrSize), "UPtr", IPropertySetStorage, "UPtrP", IEnumSTATPROPSETSTG, "UInt"))
        Return FALSE

    ; STATPROPSETSTG structure
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380317(v=vs.85).aspx
    Local PropertySets := [ {Buffer: ""} ], i := 1, Address := 0
    ObjSetCapacity(PropertySets[i], "Buffer", 64)    ; sizeof STATPROPSETSTG = 64 | PropertySets.Buffer = struct STATPROPSETSTG

    ; IEnumSTATPROPSETSTG::Next method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379202(v=vs.85).aspx
    While (!DllCall(NumGet(NumGet(IEnumSTATPROPSETSTG+0)+3*A_PtrSize), "UPtr", IEnumSTATPROPSETSTG, "UInt", 1, "UPtr", Address:=ObjGetAddress(PropertySets[i], "Buffer"), "UPtr", 0, "UInt"))
    {
        ObjRawSet(PropertySets[i], "fmtid", Address)                          ; FMTID    STATPROPSETSTG.fmtid    (FMTID of the current property set when created)
        ObjRawSet(PropertySets[i], "clsid", Address+16)                       ; CLSID    STATPROPSETSTG.clsid    (CLSID associated with this property set when created or modified)
        ObjRawSet(PropertySets[i], "grfFlags", NumGet(Address+32, "UInt"))    ; DWORD    STATPROPSETSTG.grfFlags (https://msdn.microsoft.com/en-us/library/windows/desktop/aa380069(v=vs.85).aspx)
        ObjRawSet(PropertySets[i], "mtime", Address+40)                       ; FILETIME STATPROPSETSTG.mtime    (time in Universal Coordinated Time (UTC) when the property set was last modified)
        ObjRawSet(PropertySets[i], "ctime", Address+48)                       ; FILETIME STATPROPSETSTG.ctime    (time in UTC when this property set was created)
        ObjRawSet(PropertySets[i], "atime", Address+56)                       ; FILETIME STATPROPSETSTG.atime    (Time in UTC when this property set was last accessed)
        ObjSetCapacity(PropertySets[i:=ObjPush(PropertySets, {Buffer: ""})], "Buffer", 64)    ; new struct STATPROPSETSTG
    }

    ObjPop(PropertySets)    ; remove the last STATPROPSETSTG structure
    ObjRelease(IEnumSTATPROPSETSTG)
    Return PropertySets
}

PropSetStorage_Open(IPropertySetStorage, FMTID, AccessMode := 0x10)
{
    ; IPropertySetStorage::Open method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379965(v=vs.85).aspx
    Local IPropertyStorage := 0
    ErrorLevel := DllCall(NumGet(NumGet(IPropertySetStorage+0)+4*A_PtrSize), "UPtr", IPropertySetStorage, "UPtr", FMTID, "UInt", AccessMode, "UPtrP", IPropertyStorage, "UInt")
    Return IPropertyStorage
}

EnumPropStorage(IPropertyStorage)
{
    ; IPropertyStorage::Enum method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379973(v=vs.85).aspx
    Local IEnumSTATPROPSTG := 0
    If (ErrorLevel := DllCall(NumGet(NumGet(IPropertyStorage+0)+11*A_PtrSize), "UPtr", IPropertyStorage, "UPtrP", IEnumSTATPROPSTG, "UInt"))
        Return FALSE

    ; STATPROPSTG structure
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380318(v=vs.85).aspx
    Local StatisticalData := [ {Buffer: ""} ], i := 1, Address := 0
    ObjSetCapacity(StatisticalData[i], "Buffer", A_PtrSize+8)    ; sizeof STATPROPSTG = A_PtrSize+8 | StatisticalData.Buffer = struct STATPROPSTG
    

    ; IEnumSTATPROPSTG::Next method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379213(v=vs.85).aspx
    While (!DllCall(NumGet(NumGet(IEnumSTATPROPSTG+0)+3*A_PtrSize), "UPtr", IEnumSTATPROPSTG, "UInt", 1, "UPtr", Address:=ObjGetAddress(StatisticalData[i], "Buffer"), "UPtr", 0, "UInt"))
    {
        If (NumGet(Address+0))
            ObjRawSet(StatisticalData[i], "lpwstrName", StrGet(NumGet(Address+0), "UTF-16"))    ; LPWSTR  STATPROPSTG.lpwstrName (optional string name associated with the property)
          , DllCall("Ole32.dll\CoTaskMemFree", "UPtr", NumGet(Address+0))                       ;   must be freed using CoTaskMemFree
          , NumPut(ObjGetAddress(StatisticalData[i], "lpwstrName"), Address+0)                  ;   update STATPROPSTG.lpwstrName with the new pointer because we released the previous one
        ObjRawSet(StatisticalData[i], "propid", NumGet(Address+A_PtrSize, "UInt"))            ; PROPID  STATPROPSTG.propid     (32-bit identifier that uniquely identifies the property)
        ObjRawSet(StatisticalData[i], "vt", NumGet(Address+A_PtrSize+4, "UShort"))            ; VARTYPE STATPROPSTG.vt         (property type)
        ObjSetCapacity(StatisticalData[i:=ObjPush(StatisticalData, {Buffer: ""})], "Buffer", A_PtrSize+8)    ; new struct STATPROPSTG
    }

    ObjPop(StatisticalData)    ; remove the last STATPROPSTG structure
    ObjRelease(IEnumSTATPROPSTG)
    Return StatisticalData
}

PropStorage_Read(IPropertyStorage, PropID)
{
    ; PROPSPEC structure
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380070(v=vs.85).aspx
    Local PROPSPEC := ""
    VarSetCapacity(PROPSPEC, 2*A_PtrSize)
    NumPut(1, &PROPSPEC+0, "UInt")                     ; ULONG  PROPSPEC.ulKind
    NumPut(PropID, &PROPSPEC + A_PtrSize, "UInt")    ; PROPID PROPSPEC.propid

    ; PROPVARIANT structure
    ; https://docs.microsoft.com/es-es/windows/desktop/api/propidl/ns-propidl-tagpropvariant
    Local PROPVARIANT := {Buffer: ""}
    ObjSetCapacity(PROPVARIANT, "Buffer", A_PtrSize == 4 ? 16 : 24)
    Local Address := ObjGetAddress(PROPVARIANT, "Buffer")

    ; IPropertyStorage::ReadMultiple method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379975(v=vs.85).aspx
    ; S_FALSE = 1 (valid syntax, but no properties were retrieved)
    If (ErrorLevel := DllCall(NumGet(NumGet(IPropertyStorage+0)+3*A_PtrSize), "UPtr", IPropertyStorage, "UInt", 1, "UPtr", &PROPSPEC, "UPtr", Address, "UInt"))
        Return FALSE

    ObjRawSet(PROPVARIANT, "vt", NumGet(Address+0, "UInt"))
    ObjRawSet(PROPVARIANT, "ptr", NumGet(Address+8, "UPtr"))

    Return PROPVARIANT
}

PropStorage_ReadPropertyName(IPropertyStorage, PropID)
{
    ; IPropertyStorage::ReadPropertyNames method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379976(v=vs.85).aspx
    Local Buffer := 0
    ErrorLevel := DllCall(NumGet(NumGet(IPropertyStorage+0)+6*A_PtrSize), "UPtr", IPropertyStorage, "UInt", 1, "UIntP", PropID, "UPtrP", Buffer, "UInt")
    Local R := ""
    If (!ErrorLevel)    ; S_OK
        R := StrGet(Buffer, "UTF-16"), DllCall("Ole32.dll\CoTaskMemFree", "UPtr", Buffer)
    Return R
}

StringFromCLSID(Address)
{
    ; StringFromGUID2 function
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms683893(v=vs.85).aspx
    Local Buffer := ""
    VarSetCapacity(Buffer, (38 + 1) * 2)
    DllCall("Ole32.dll\StringFromGUID2", "UPtr", Address, "Str", Buffer, "Int", 38 + 1)
    Return Buffer
}

CLSIDFromString(String, ByRef CLSID)
{
    ; CLSIDFromString function
    ; https://docs.microsoft.com/en-us/windows/desktop/api/combaseapi/nf-combaseapi-clsidfromstring
    VarSetCapacity(CLSID, 16)
    Return DllCall("Ole32.dll\CLSIDFromString", "Str", String, "UPtr", &CLSID, "UInt") ? 0 : &CLSID
}

PropVariantClear(Address)
{
    Return DllCall("Ole32.dll\PropVariantClear", "UPtr", IsObject(Address) ? ObjGetAddress(Address, "Buffer") : Address)
}
Sorry for the horrible code, I got bored :lol:

Code: Select all

global Gui, eFile, bFile, lList, Tab, eStr, eHex
     , _hex := _sto := 0

MenuBar := MenuBarCreate()
    menu_file := MenuCreate()
        menu_file.Add("Open", "SelectFile")
        menu_file.Add("Exit", "ExitApp")
    MenuBar.Add("File", menu_file)

Gui := GuiCreate("-DPIScale -MinSize650x450 -Resize", "ADS Viewer | Flipeador")
    Gui.SetFont("s9" , "Segoe UI")
    Gui.MenuBar := MenuBar

eFile := Gui.AddEdit("x10 y10 w585 h21 c161616 +ReadOnly")
    ;SendMessage(0x1501, TRUE, &"Select the file to analyze..",, "ahk_id" . eFile.Hwnd)
bFile := Gui.AddButton("x600 y10 w40 h21", "•••")
    bFile.OnEvent("Click", "SelectFile")
lList := Gui.AddListView("x10 y40 w630 h150", "Name|Size|Storage Object")
    DllCall("UxTheme.dll\SetWindowTheme", "Ptr", lList.Hwnd, "Str", "Explorer", "UPtr", 0, "UInt")
    lList.OnEvent("ItemSelect", "LVEvents")
Tab := Gui.AddTab3("x10 y200 w630 h240", "String|Hexadecimal|Storage Object")
    Tab.OnEvent("Change", "TabEvent")

Tab.UseTab(1)
eStr := Gui.AddEdit("x20 y230 w610 h200 +ReadOnly")

Tab.UseTab(2)
eHex := Gui.AddEdit("x20 y230 w610 h200 +ReadOnly")
    eHex.SetFont(, "Monospac821 BT")

Tab.UseTab(3)
eSto := Gui.AddEdit("x20 y230 w610 h200 +ReadOnly")

Gui.Show("w650 h450")
    Gui.OnEvent("Close", () => ExitApp())
Return


SelectFile()
{
    Local File := FileSelect(3)
    If (!ErrorLevel)
    {
        lList.Delete(), Reset()
        eFile.Text := File
        Tab.Value := 1
        
        Local Each := "", Stream := ""
        For Each, Stream in EnumStreams(File)
            lList.Add(, Stream.Name == "" ? "<unnamed>" : Stream.Name, StrFormatByteSize(Stream.Size), Stream.Name ~= "^\x5" ? "TRUE" : "FALSE")
        lList.ModifyCol(1, "AutoHdr")
        lList.ModifyCol(2, "AutoHdr")
    }
}

Reset()
{
    global _hex, _sto
    eStr.Text := ""
    eHex.Text := ""
    _hex := 0
    _sto := 0
}

ConvertEOL(Str, EOL := "`r`n")
{
    Local Count := ""
    Loop
        Str := StrReplace(Str, "`r`n", "`n", Count)
    Until (!Count)
    Str := StrReplace(Str, "`r", "`n")

    Return EOL == "`n" ? Str : StrReplace(Str, "`n", EOL)
}

TabEvent()
{
    global _hex, _sto, eSto
    Gui.Opt("+Disabled")
    If (Tab.Value == 2 && !_hex)
    {
        Local Stream := lList.GetText(lList.GetNext())
            ,   File := FileOpen(eFile.Text . (Stream == "<unnamed>" ? "" : ":" . Stream), "r")
        If (!File)
        {
            MsgBox("The file couldn't be opened"), Gui.Opt("-Disabled")
            Return
        }
        File.Seek(0)
        Local HexTxt := "0001    ", Arr := [], i := 0
        While (!File.AtEOF)
        {
            HexTxt .= Format("{:02X} ", Arr[ObjPush(Arr, File.ReadUChar())])

            If (!Mod(i:=A_Index, 16))
            {
                HexTxt .= "    "
                For k, v in Arr
                    HexTxt .= v < 33 || v > 126 ? "." : Chr(v)
                HexTxt .= "`r`n" . Format("{:04X}    ", A_Index//16+1)
                Arr := []
            }
            If (A_Index//16 > 10000)
            {
                HexTxt .= "`r`n    ..."
                Break
            }
        }
        If (i:=Mod(i, 16))
        {
            HexTxt .= "    "
            Loop 16-i
                HexTxt .= "   "
            For k, v in Arr
                HexTxt .= !v || v == 10 || v == 13 ? "." : Chr(v)
        }
        _hex := 1, eHex.Text := HexTxt
    }
    If (Tab.Value == 3 && !_sto)
    {
        Local IPropertySetStorage := GetPropSetStorage(eFile.Text)
        If (!IPropertySetStorage)
        {
            MsgBox "IPropertySetStorage ERROR " . Format("0x{:08X}", ErrorLevel), Gui.Opt("-Disabled")
            Return
        }
        Local Info := ""
        local PropertySets := EnumPropSetStorage(IPropertySetStorage)
        For Each, STATPROPSETSTG in PropertySets
        {
            Info .= "STATPROPSETSTG.fmtid "    . StringFromCLSID(STATPROPSETSTG.fmtid) . "`n"      ; format identifier (FMTID) of the property set
            Info .= "STATPROPSETSTG.clsid "    . StringFromCLSID(STATPROPSETSTG.clsid) . "`n"
            Info .= "STATPROPSETSTG.grfFlags " . STATPROPSETSTG.grfFlags               . "`n`n"

            ; opens a property set contained in the property set storage object
            IPropertyStorage := PropSetStorage_Open(IPropertySetStorage, STATPROPSETSTG.fmtid)
            If (IPropertyStorage)
            {
                ; get statistical data in the property set
                StatisticalData := EnumPropStorage(IPropertyStorage)
                If (!ObjLength(StatisticalData))
                    Info .= "> no statistical data <`n"
                For Each, STATPROPSTG in StatisticalData
                {
                    Info .= "STATPROPSTG.lpwstrName " . STATPROPSTG.lpwstrName . "`n"
                    Info .= "STATPROPSTG.propid "     . STATPROPSTG.propid     . "`n"
                    Info .= "STATPROPSTG.vt "         . STATPROPSTG.vt         . "`n"

                    ; retrieves any existing string name for the specified property ID
                    Info .= "PropertyName "           . PropStorage_ReadPropertyName(IPropertyStorage, STATPROPSTG.propid) . " (" . ErrorLevel . ")`n"

                    ; reads the property value
                    PROPVARIANT := PropStorage_Read(IPropertyStorage, STATPROPSTG.propid)
                    If (PROPVARIANT)
                    {
                        Info .= "PROPVARIANT.vt " . PROPVARIANT.vt . "`n"
                        If (PROPVARIANT.vt == 30 || PROPVARIANT.vt == 31)    ; VT_LPSTR = 30 | VT_LPWSTR = 31
                            Info .= "`n" . StrGet(PROPVARIANT.ptr, PROPVARIANT.vt == 30 ? "UTF-8" : "UTF-16") . "`n`n"
                        Else
                            Info .= "`n< no string >`n`n"
                        PropVariantClear(PROPVARIANT)
                    }
                }
                ObjRelease(IPropertyStorage)
            }

            Info .= "`n`n`n----------------------`n`n`n`n"
        }

        ; special-case handling for the UserDefined property set
        CLSID := ""
        IPropertyStorage := PropSetStorage_Open(IPropertySetStorage, CLSIDFromString("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", CLSID))
        If (IPropertyStorage)
        {
            Info .= "STATPROPSETSTG.fmtid "    . StringFromCLSID(&CLSID) . "`n`n"      ; format identifier (FMTID) of the property set

            StatisticalData := EnumPropStorage(IPropertyStorage)
            If (!ObjLength(StatisticalData))
                Info .= "> no statistical data <`n"
            For Each, STATPROPSTG in StatisticalData
            {
                Info .= "STATPROPSTG.lpwstrName " . STATPROPSTG.lpwstrName . "`n"
                Info .= "STATPROPSTG.propid "     . STATPROPSTG.propid     . "`n"
                Info .= "STATPROPSTG.vt "         . STATPROPSTG.vt         . "`n"

                Info .= "PropertyName "           . PropStorage_ReadPropertyName(IPropertyStorage, STATPROPSTG.propid) . " (" . ErrorLevel . ")`n"

                PROPVARIANT := PropStorage_Read(IPropertyStorage, STATPROPSTG.propid)
                If (PROPVARIANT)
                {
                    Info .= "PROPVARIANT.vt " . PROPVARIANT.vt . "`n"
                    If (PROPVARIANT.vt == 30 || PROPVARIANT.vt == 31)    ; VT_LPSTR = 30 | VT_LPWSTR = 31
                        Info .= "`n" . StrGet(PROPVARIANT.ptr, PROPVARIANT.vt == 30 ? "UTF-8" : "UTF-16") . "`n`n"
                    Else
                        Info .= "`n< no string >`n`n"
                    PropVariantClear(PROPVARIANT)
                }
            }
            ObjRelease(IPropertyStorage)
        }
        ObjRelease(IPropertySetStorage)
        _sto := 1, eSto.Text := ConvertEOL(Info)
    }
    Gui.Opt("-Disabled")
}

LVEvents(LV, Item, Selected)
{
    Sleep(50)
    Local Stream := LV.GetText(Item)
        ,   File := FileOpen(eFile.Text . (Stream == "<unnamed>" ? "" : ":" . Stream), "r")
    If (!File)
    {
        MsgBox "The file couldn't be opened"
        Return
    }
    Gui.Opt("+Disabled")
    Tab.Value := 1
    Reset()

    Local Buffer := "", Size := 0
    eStr.Text := ConvertEOL(File.Read(10000))

    Gui.Opt("-Disabled")
}

EnumStreams(File)
{
    Local                Streams := []
        , WIN32_FIND_STREAM_DATA := ""

    VarSetCapacity(WIN32_FIND_STREAM_DATA, 8 + (260 + 36) * 2)
    Local Handle := DllCall("Kernel32.dll\FindFirstStreamW", "UPtr", &File, "UInt", 0, "UPtr", &WIN32_FIND_STREAM_DATA, "UInt", 0, "Ptr")
    If (!Handle)
        Return FALSE
    ObjPush(Streams, {Size: NumGet(&WIN32_FIND_STREAM_DATA, "Int64"), Name: SubStr(StrGet(&WIN32_FIND_STREAM_DATA + 8, "UTF-16"), 2, -6)})

    While (DllCall("Kernel32.dll\FindNextStreamW", "Ptr", Handle, "UPtr", &WIN32_FIND_STREAM_DATA, "Ptr"))
        ObjPush(Streams, {Size: NumGet(&WIN32_FIND_STREAM_DATA, "Int64"), Name: SubStr(StrGet(&WIN32_FIND_STREAM_DATA + 8, "UTF-16"), 2, -6)})

    Return Streams
} ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa365741(v=vs.85).aspx


StrFormatByteSize(Number, Flags := 1)
{
    Local Buffer := ""
    VarSetCapacity(Buffer, 30 * 2, 0)
    Local R := DllCall("Shlwapi.dll\StrFormatByteSizeEx", "Int64", Number, "UInt", Flags, "UPtr", &Buffer, "UInt", 30)
    Return R == 0 ? StrGet(&Buffer, "UTF-16") : ""
} ;https://msdn.microsoft.com/en-us/library/windows/desktop/bb892884(v=vs.85).aspx

GetPropSetStorage(Filename, AccessMode := 0x10)
{
    Local GUID := "", IPropertySetStorage := 0
    VarSetCapacity(GUID, 16)
    DllCall("Ole32.dll\CLSIDFromString", "Str", "{0000013A-0000-0000-C000-000000000046}", "UPtr", &GUID, "UInt")

    ; StgOpenStorageEx function
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380342(v=vs.85).aspx
    ; STGFMT_ANY = 4
    ErrorLevel := DllCall("Ole32.dll\StgOpenStorageEx", "UPtr", &Filename, "UInt", AccessMode, "Int", 4, "UInt", 0, "UPtr", 0, "UPtr", 0, "UPtr", &GUID, "UPtrP", IPropertySetStorage, "UInt")
    Return IPropertySetStorage
}

EnumPropSetStorage(IPropertySetStorage)
{
    ; IPropertySetStorage::Enum method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379960(v=vs.85).aspx
    Local IEnumSTATPROPSETSTG := 0
    If (ErrorLevel := DllCall(NumGet(NumGet(IPropertySetStorage)+6*A_PtrSize), "UPtr", IPropertySetStorage, "UPtrP", IEnumSTATPROPSETSTG, "UInt"))
        Return FALSE

    ; STATPROPSETSTG structure
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380317(v=vs.85).aspx
    Local PropertySets := [ {Buffer: ""} ], i := 1, Address := 0
    ObjSetCapacity(PropertySets[i], "Buffer", 64)    ; sizeof STATPROPSETSTG = 64 | PropertySets.Buffer = struct STATPROPSETSTG

    ; IEnumSTATPROPSETSTG::Next method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379202(v=vs.85).aspx
    While (!DllCall(NumGet(NumGet(IEnumSTATPROPSETSTG)+3*A_PtrSize), "UPtr", IEnumSTATPROPSETSTG, "UInt", 1, "UPtr", Address:=ObjGetAddress(PropertySets[i], "Buffer"), "UPtr", 0, "UInt"))
    {
        ObjRawSet(PropertySets[i], "fmtid", Address)                          ; FMTID    STATPROPSETSTG.fmtid    (FMTID of the current property set when created)
        ObjRawSet(PropertySets[i], "clsid", Address+16)                       ; CLSID    STATPROPSETSTG.clsid    (CLSID associated with this property set when created or modified)
        ObjRawSet(PropertySets[i], "grfFlags", NumGet(Address+32, "UInt"))    ; DWORD    STATPROPSETSTG.grfFlags (https://msdn.microsoft.com/en-us/library/windows/desktop/aa380069(v=vs.85).aspx)
        ObjRawSet(PropertySets[i], "mtime", Address+40)                       ; FILETIME STATPROPSETSTG.mtime    (time in Universal Coordinated Time (UTC) when the property set was last modified)
        ObjRawSet(PropertySets[i], "ctime", Address+48)                       ; FILETIME STATPROPSETSTG.ctime    (time in UTC when this property set was created)
        ObjRawSet(PropertySets[i], "atime", Address+56)                       ; FILETIME STATPROPSETSTG.atime    (Time in UTC when this property set was last accessed)
        ObjSetCapacity(PropertySets[i:=ObjPush(PropertySets, {Buffer: ""})], "Buffer", 64)    ; new struct STATPROPSETSTG
    }

    ObjPop(PropertySets)    ; remove the last STATPROPSETSTG structure
    ObjRelease(IEnumSTATPROPSETSTG)
    Return PropertySets
}

PropSetStorage_Open(IPropertySetStorage, FMTID, AccessMode := 0x10)
{
    ; IPropertySetStorage::Open method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379965(v=vs.85).aspx
    Local IPropertyStorage := 0
    ErrorLevel := DllCall(NumGet(NumGet(IPropertySetStorage)+4*A_PtrSize), "UPtr", IPropertySetStorage, "UPtr", FMTID, "UInt", AccessMode, "UPtrP", IPropertyStorage, "UInt")
    Return IPropertyStorage
}

EnumPropStorage(IPropertyStorage)
{
    ; IPropertyStorage::Enum method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379973(v=vs.85).aspx
    Local IEnumSTATPROPSTG := 0
    If (ErrorLevel := DllCall(NumGet(NumGet(IPropertyStorage)+11*A_PtrSize), "UPtr", IPropertyStorage, "UPtrP", IEnumSTATPROPSTG, "UInt"))
        Return FALSE

    ; STATPROPSTG structure
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380318(v=vs.85).aspx
    Local StatisticalData := [ {Buffer: ""} ], i := 1, Address := 0
    ObjSetCapacity(StatisticalData[i], "Buffer", A_PtrSize+8)    ; sizeof STATPROPSTG = A_PtrSize+8 | StatisticalData.Buffer = struct STATPROPSTG
    

    ; IEnumSTATPROPSTG::Next method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379213(v=vs.85).aspx
    While (!DllCall(NumGet(NumGet(IEnumSTATPROPSTG)+3*A_PtrSize), "UPtr", IEnumSTATPROPSTG, "UInt", 1, "UPtr", Address:=ObjGetAddress(StatisticalData[i], "Buffer"), "UPtr", 0, "UInt"))
    {
        If (NumGet(Address))
            ObjRawSet(StatisticalData[i], "lpwstrName", StrGet(NumGet(Address), "UTF-16"))    ; LPWSTR  STATPROPSTG.lpwstrName (optional string name associated with the property)
          , DllCall("Ole32.dll\CoTaskMemFree", "UPtr", NumGet(Address))                       ;   must be freed using CoTaskMemFree
          , NumPut(ObjGetAddress(StatisticalData[i], "lpwstrName"), Address)                  ;   update STATPROPSTG.lpwstrName with the new pointer because we released the previous one
        ObjRawSet(StatisticalData[i], "propid", NumGet(Address+A_PtrSize, "UInt"))            ; PROPID  STATPROPSTG.propid     (32-bit identifier that uniquely identifies the property)
        ObjRawSet(StatisticalData[i], "vt", NumGet(Address+A_PtrSize+4, "UShort"))            ; VARTYPE STATPROPSTG.vt         (property type)
        ObjSetCapacity(StatisticalData[i:=ObjPush(StatisticalData, {Buffer: ""})], "Buffer", A_PtrSize+8)    ; new struct STATPROPSTG
    }

    ObjPop(StatisticalData)    ; remove the last STATPROPSTG structure
    ObjRelease(IEnumSTATPROPSTG)
    Return StatisticalData
}

PropStorage_Read(IPropertyStorage, PropID)
{
    ; PROPSPEC structure
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380070(v=vs.85).aspx
    Local PROPSPEC := ""
    VarSetCapacity(PROPSPEC, 2*A_PtrSize)
    NumPut(1, &PROPSPEC, "UInt")                     ; ULONG  PROPSPEC.ulKind
    NumPut(PropID, &PROPSPEC + A_PtrSize, "UInt")    ; PROPID PROPSPEC.propid

    ; PROPVARIANT structure
    ; https://docs.microsoft.com/es-es/windows/desktop/api/propidl/ns-propidl-tagpropvariant
    Local PROPVARIANT := {Buffer: ""}
    ObjSetCapacity(PROPVARIANT, "Buffer", A_PtrSize == 4 ? 16 : 24)
    Local Address := ObjGetAddress(PROPVARIANT, "Buffer")

    ; IPropertyStorage::ReadMultiple method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379975(v=vs.85).aspx
    ; S_FALSE = 1 (valid syntax, but no properties were retrieved)
    If (ErrorLevel := DllCall(NumGet(NumGet(IPropertyStorage)+3*A_PtrSize), "UPtr", IPropertyStorage, "UInt", 1, "UPtr", &PROPSPEC, "UPtr", Address, "UInt"))
        Return FALSE

    ObjRawSet(PROPVARIANT, "vt", NumGet(Address, "UInt"))
    ObjRawSet(PROPVARIANT, "ptr", NumGet(Address+8, "UPtr"))

    Return PROPVARIANT
}

PropStorage_ReadPropertyName(IPropertyStorage, PropID)
{
    ; IPropertyStorage::ReadPropertyNames method
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379976(v=vs.85).aspx
    Local Buffer := 0
    ErrorLevel := DllCall(NumGet(NumGet(IPropertyStorage)+6*A_PtrSize), "UPtr", IPropertyStorage, "UInt", 1, "UIntP", PropID, "UPtrP", Buffer, "UInt")
    Local R := ""
    If (!ErrorLevel)    ; S_OK
        R := StrGet(Buffer, "UTF-16"), DllCall("Ole32.dll\CoTaskMemFree", "UPtr", Buffer)
    Return R
}

StringFromCLSID(Address)
{
    ; StringFromGUID2 function
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms683893(v=vs.85).aspx
    Local Buffer := ""
    VarSetCapacity(Buffer, (38 + 1) * 2)
    DllCall("Ole32.dll\StringFromGUID2", "UPtr", Address, "Str", Buffer, "Int", 38 + 1)
    Return Buffer
}

CLSIDFromString(String, ByRef CLSID)
{
    ; CLSIDFromString function
    ; https://docs.microsoft.com/en-us/windows/desktop/api/combaseapi/nf-combaseapi-clsidfromstring
    VarSetCapacity(CLSID, 16)
    Return DllCall("Ole32.dll\CLSIDFromString", "Str", String, "UPtr", &CLSID, "UInt") ? 0 : &CLSID
}

PropVariantClear(Address)
{
    Return DllCall("Ole32.dll\PropVariantClear", "UPtr", IsObject(Address) ? ObjGetAddress(Address, "Buffer") : Address)
}
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Alternate Data Stream Gibberish

30 Jun 2018, 15:04

Flipeador wrote:AHKv1:
The stream objects are not deciphered alright, unfortunately.
Flipeador wrote:Sorry for the horrible code, I got bored :lol:
Great stuff and it's a really nice opportunity for me to learn about the v2 GUI stuff, when I will convert this to v1 :D Many thanks for your awesome help Flipeador, you are definitely a rising ahk star :mrgreen: I will go on (offline) vaccation tomorrow :)

Best regards
zcooler
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Alternate Data Stream Gibberish

01 Jul 2018, 15:05

The stream objects are not deciphered alright, unfortunately.
I already fixed it.
You're welcome. :wave:

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Bubo_Bubo, Google [Bot], marypoppins_1, mikeyww, OrangeCat, RussF and 133 guests