Alternate Data Stream Gibberish Topic is solved
Re: Alternate Data Stream Gibberish
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.
Re: Alternate Data Stream Gibberish
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.
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.
Re: Alternate Data Stream Gibberish
Thanks, I have v1 going alongside v2 now...coolness...you are going to kick some ADSManager a**, with that one
Re: Alternate Data Stream Gibberish
Yes... ADS Manager could improve much more, adding support for Stream Objects. If this issue has not yet been resolved, tell me.
Re: Alternate Data Stream Gibberish
Which issue do you mean?Flipeador wrote:Yes... ADS Manager could improve much more, adding support for Stream Objects. If this issue has not yet been resolved, tell me.
Re: Alternate Data Stream Gibberish
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.
Re: Alternate Data Stream Gibberish
Yes, it has been resolved beautifully. Impressive work, Flipeador
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.
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.
Re: Alternate Data Stream Gibberish
The Script that I put to you is just a poor example. I only take a few minutes (5-10).For your ADS Viewer in "String view" it would be interesting, in the future, to get the whole string.
I limited the length of the string to avoid loading very large files (eg 1GB) in memory. Surely you can implement an intelligent verification.
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.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, it has been resolved beautifully. Impressive work, Flipeador
Edit*
I think you were referring to when the Stream contains an Stream Object. To "decipher" this string you have to use the interfaces.zcooler wrote:For your ADS Viewer in "String view" it would be interesting, in the future, to get the whole string.
Re: Alternate Data Stream Gibberish
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.Flipeador wrote: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.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?
Best regards from
zcooler
Re: Alternate Data Stream Gibberish
Hi Flipeador,
IPropertySetStorage:
IPropertySetStorage:
EnumAll Sample: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.
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;
}
Re: Alternate Data Stream Gibberish
Greetings oh great Just me
Saves the day for a lot of us still you are
Yes I noticed this:...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
I think Flipeador will crack this case easily with that info you provided when he gets the time. Thank you Just me
Saves the day for a lot of us still you are
Yes I noticed this:
Code: Select all
; FMTID_DocSummaryInformation = {D5CDD502-2E9C-101B-9397-08002B2CF9AE}
; FMTID_UserDefinedProperties = {D5CDD505-2E9C-101B-9397-08002B2CF9AE}
I think Flipeador will crack this case easily with that info you provided when he gets the time. Thank you Just me
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 awesomeFlipeador wrote:Edit*I think you were referring to when the Stream contains an Stream Object. To "decipher" this string you have to use the interfaces.zcooler wrote:For your ADS Viewer in "String view" it would be interesting, in the future, to get the whole string.
Re: Alternate Data Stream Gibberish
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.
Yes, it would be interesting to create my own ADS Viewer that supports Stream Objects, I'll try.
Re: Alternate Data Stream Gibberish
OH YES 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.Flipeador wrote:Yes, it would be interesting to create my own ADS Viewer that supports Stream Objects, I'll try.
Re: Alternate Data Stream Gibberish
I have already fixed it: https://autohotkey.com/boards/viewtopic ... 58#p225658.
I'll see the ADS Viewer.
I'll see the ADS Viewer.
Re: Alternate Data Stream Gibberish
ExcellenteFlipeador wrote:I have already fixed it: https://autohotkey.com/boards/viewtopic ... 58#p225658.
I'll see the ADS Viewer.
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)
}
Re: Alternate Data Stream Gibberish
AHKv1:
Sorry for the horrible code, I got bored
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)
}
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)
}
Re: Alternate Data Stream Gibberish
The stream objects are not deciphered alright, unfortunately.Flipeador wrote:AHKv1:
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 Many thanks for your awesome help Flipeador, you are definitely a rising ahk star I will go on (offline) vaccation tomorrowFlipeador wrote:Sorry for the horrible code, I got bored
Best regards
zcooler
Re: Alternate Data Stream Gibberish
I already fixed it.The stream objects are not deciphered alright, unfortunately.
You're welcome.