Re: Alternate Data Stream Gibberish
Posted: 24 Jun 2018, 11:10
I have updated the code above, try again.
Let's help each other out
https://www.autohotkey.com/boards/
https://www.autohotkey.com/boards/viewtopic.php?f=76&t=50460
---------------------------
proptest.ahk
---------------------------
Error: Memory limit reached (see #MaxMem in the help file).
Line#
040: NumPut(1, &PROPSPEC, "UInt")
041: NumPut(propid, &PROPSPEC+A_PtrSize, "UInt")
043: VarSetCapacity(PROPVARIANT, A_PtrSize == 4 ? 16 : 24)
046: DllCall(NumGet(NumGet(IPropertyStorage+0)+3*A_PtrSize), "UPtr", IPropertyStorage, "UInt", 1, "UPtr", &PROPSPEC, "UPtr", &PROPVARIANT, "UInt")
047: if (NumGet(&PROPVARIANT+0, "UShort") == 31)
048: List .= StrGet(NumGet(&PROPVARIANT + 8, "UPtr"), "UTF-16") . "
--------------------
"
049: Else
---> 050: List .= "PROPVARIANT.vt=" . NumGet(&PROPVARIANT+0, "UShort") . "
--------------------
"
051: DllCall("Ole32.dll\PropVariantClear", "UPtr", &PROPVARIANT)
052: }
054: MsgBox,Str . "
" . List
055: }
056: Exit
057: Exit
057: Exit
The current thread will exit.
---------------------------
OK
---------------------------
PROPVARIANT is not difficult to understand, in fact, my only problem is to try to understand the correct steps to follow to recover the OLE Streams.zcooler wrote:Propvariant seems difficult
Code: Select all
fileselectfile File
VarSetCapacity(GUID, 16)
DllCall("Ole32.dll\CLSIDFromString", "Str", "{0000013A-0000-0000-C000-000000000046}", "UPtr", &GUID)
IPropertySetStorage := 0
DllCall("Ole32.dll\StgOpenStorageEx", "UPtr", &File, "UInt", 0x10, "Int", 4, "UInt", 0, "UPtr", 0, "UPtr", 0, "UPtr", &GUID, "UPtrP", IPropertySetStorage, "UInt")
IEnumSTATPROPSETSTG := 0
DllCall(NumGet(NumGet(IPropertySetStorage+0)+6*A_PtrSize), "UPtr", IPropertySetStorage, "UPtrP", IEnumSTATPROPSETSTG, "UInt")
Buffer := 0
VarSetCapacity(STATPROPSETSTG, 64)
Fetched := 0
While !DllCall(NumGet(NumGet(IEnumSTATPROPSETSTG+0)+3*A_PtrSize), "UPtr", IEnumSTATPROPSETSTG, "UInt", 1, "UPtr", &STATPROPSETSTG, "UIntP", Fetched, "UInt") ;enum
{
; Predefined Property Set Format Identifiers : https://msdn.microsoft.com/en-us/library/windows/desktop/aa380060(v=vs.85).aspx
; FMTID_SummaryInformation = {F29F85E0-4FF9-1068-AB91-08002B27B3D9}
; FMTID_DocSummaryInformation = {D5CDD502-2E9C-101B-9397-08002B2CF9AE}
; FMTID_UserDefinedProperties = {D5CDD505-2E9C-101B-9397-08002B2CF9AE}
DllCall("Ole32.dll\StringFromCLSID", "UPtr", &STATPROPSETSTG, "UPtrP", Buffer)
Str := StrGet(Buffer, "UTF-16"), DllCall("Ole32.dll\CoTaskMemFree", "UPtr", Buffer) ; stream name
IPropertyStorage := 0
DllCall(NumGet(NumGet(IPropertySetStorage+0)+4*A_PtrSize), "UPtr", IPropertySetStorage, "UPtr", &STATPROPSETSTG, "UInt", 0x10, "UPtrP", IPropertyStorage, "UInt")
IEnumSTATPROPSTG := 0
; IPropertyStorage::Enum method
; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379973(v=vs.85).aspx
DllCall(NumGet(NumGet(IPropertyStorage+0)+11*A_PtrSize), "UPtr", IPropertyStorage, "UPtrP", IEnumSTATPROPSTG, "UInt")
List := ""
VarSetCapacity(STATPROPSTG, A_PtrSize + 4 + 4)
While !DllCall(NumGet(NumGet(IEnumSTATPROPSTG+0)+3*A_PtrSize), "UPtr", IEnumSTATPROPSTG, "UInt", 1, "UPtr", &STATPROPSTG, "UIntP", Fetched, "UInt") ;enum
{
propid := NumGet(&STATPROPSTG + A_PtrSize, "UInt")
VarSetCapacity(PROPSPEC, 2*A_PtrSize)
NumPut(1, &PROPSPEC, "UInt")
NumPut(propid, &PROPSPEC+A_PtrSize, "UInt")
VarSetCapacity(PROPVARIANT, A_PtrSize == 4 ? 16 : 24)
; IPropertyStorage::ReadMultiple method
; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379975(v=vs.85).aspx
DllCall(NumGet(NumGet(IPropertyStorage+0)+3*A_PtrSize), "UPtr", IPropertyStorage, "UInt", 1, "UPtr", &PROPSPEC, "UPtr", &PROPVARIANT, "UInt")
If (NumGet(&PROPVARIANT+0, "UShort") == 31) ; VT_LPWSTR
List .= StrGet(NumGet(&PROPVARIANT + 8, "UPtr"), 1000, "UTF-16") . "`n--------------------`n"
Else
List .= "PROPVARIANT.vt=" . NumGet(&PROPVARIANT+0, "UShort") . "`n--------------------`n"
DllCall("Ole32.dll\PropVariantClear", "UPtr", &PROPVARIANT)
}
MsgBox % Str . "`n`n" . List
}
;ObjRelease * ...
I always recommend using UTF-8 with BOM.Had to use UTF-8-BOM encoding and then it works
Read Predefined Property Set Format Identifiers. That's the least of it, just use If.I wonder if it might be possible to convert the GUIDs to display the actual stream names?
Yes, I know, I have no idea where it get those names, maybe ADS Manager do some conversion and are not the real names, you should try another program. is weird, maybe it's a BOM. Several unknownszcooler wrote:I mean these names:
Stream : DocumentSummaryInformation
Stream : SebiesnrMkudrfcoIaamtykdDa
Stream : SummaryInformation
Code: Select all
fileselectfile file
List := ""
For Each, Stream in EnumStreams(File)
List .= "[" . Stream.Size . "] " . Stream.Name . "`n"
MsgBox % List
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: RTrim(StrGet(&WIN32_FIND_STREAM_DATA + 8, "UTF-16"), ":$DATA")})
While (DllCall("Kernel32.dll\FindNextStreamW", "Ptr", Handle, "UPtr", &WIN32_FIND_STREAM_DATA, "Ptr"))
ObjPush(Streams, {Size: NumGet(&WIN32_FIND_STREAM_DATA, "Int64"), Name: RTrim(StrGet(&WIN32_FIND_STREAM_DATA + 8, "UTF-16"), ":$DATA")})
Return Streams
} ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa365741(v=vs.85).aspx
Oh wow, that would be amazingFlipeador wrote:I will continue investigating, I am not sure what kind of data the PROPVARIANT structure is recovering (if it's about the Stream data or what). Then we'll have to turn all this ugly code into a nice function .
Heck yes, this is so far above my head...you are impressing thoughFlipeador wrote:Yes, I know, I have no idea where it get those names, maybe ADS Manager do some conversion and are not the real names, you should try another program. is weird, maybe it's a BOM. Several unknownszcooler wrote:I mean these names:
Stream : DocumentSummaryInformation
Stream : SebiesnrMkudrfcoIaamtykdDa
Stream : SummaryInformation
That is correctly observed...it's my experience with aDSmanager as well in text preview. The hex preview works better.Flipeador wrote:Edit: This is very rare, if I try to modify the Stream data with ADS Manager (load data from a file), PROPVARIANT.vt is set to zero (VT_EMPTY). It seems that ADS Manager uses only FindFirstStream (does not use any interface, so it breaks the OLE Streams, and converts it into normal Streams, or maybe what I'm saying does not make any sense).
Does FindFirstStream work for you too?.That is correctly observed...it's my experience with aDSmanager as well in text preview.
That's because it's probably binary data, and not a string. Or who knows what strange things do ADS Manager.The hex preview works better
Hmm..that is strange. Your code doesnt seem to find the content of DocumentSummaryInformation, while the other two SebiesnrMkudrfcoIaamtykdDa and SummaryInformation seem to be no problem.Flipeador wrote:Does FindFirstStream work for you too?.
Code: Select all
; put the file path here
File := "F:\Ny mapp\20180116_20-59-02_Discovery Channel_Gold Rush Alaska - S08E03 - “Busted And Bushfixed”.ts"
;File := "F:\Ny mapp\20180102_02-19-01_Sjuan_Clueless - ★★★★★★★☆☆☆.ts"
VarSetCapacity(GUID, 16)
DllCall("Ole32.dll\CLSIDFromString", "Str", "{0000013A-0000-0000-C000-000000000046}", "UPtr", &GUID)
IPropertySetStorage := 0
DllCall("Ole32.dll\StgOpenStorageEx", "UPtr", &File, "UInt", 0x10, "Int", 4, "UInt", 0, "UPtr", 0, "UPtr", 0, "UPtr", &GUID, "UPtrP", IPropertySetStorage, "UInt")
IEnumSTATPROPSETSTG := 0
DllCall(NumGet(NumGet(IPropertySetStorage+0)+6*A_PtrSize), "UPtr", IPropertySetStorage, "UPtrP", IEnumSTATPROPSETSTG, "UInt")
Buffer := 0
VarSetCapacity(STATPROPSETSTG, 64)
Fetched := 0
While !DllCall(NumGet(NumGet(IEnumSTATPROPSETSTG+0)+3*A_PtrSize), "UPtr", IEnumSTATPROPSETSTG, "UInt", 1, "UPtr", &STATPROPSETSTG, "UIntP", Fetched, "UInt") ;enum
{
; Predefined Property Set Format Identifiers : https://msdn.microsoft.com/en-us/library/windows/desktop/aa380060(v=vs.85).aspx
; FMTID_SummaryInformation = {F29F85E0-4FF9-1068-AB91-08002B27B3D9}
; FMTID_DocSummaryInformation = {D5CDD502-2E9C-101B-9397-08002B2CF9AE}
; FMTID_UserDefinedProperties = {D5CDD505-2E9C-101B-9397-08002B2CF9AE}
DllCall("Ole32.dll\StringFromCLSID", "UPtr", &STATPROPSETSTG, "UPtrP", Buffer)
Str := StrGet(Buffer, "UTF-16"), DllCall("Ole32.dll\CoTaskMemFree", "UPtr", Buffer) ; stream name
IPropertyStorage := 0
DllCall(NumGet(NumGet(IPropertySetStorage+0)+4*A_PtrSize), "UPtr", IPropertySetStorage, "UPtr", &STATPROPSETSTG, "UInt", 0x10, "UPtrP", IPropertyStorage, "UInt")
IEnumSTATPROPSTG := 0
; IPropertyStorage::Enum method
; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379973(v=vs.85).aspx
DllCall(NumGet(NumGet(IPropertyStorage+0)+11*A_PtrSize), "UPtr", IPropertyStorage, "UPtrP", IEnumSTATPROPSTG, "UInt")
List := ""
VarSetCapacity(STATPROPSTG, A_PtrSize + 4 + 4)
While !DllCall(NumGet(NumGet(IEnumSTATPROPSTG+0)+3*A_PtrSize), "UPtr", IEnumSTATPROPSTG, "UInt", 1, "UPtr", &STATPROPSTG, "UIntP", Fetched, "UInt") ;enum
{
propid := NumGet(&STATPROPSTG + A_PtrSize, "UInt")
VarSetCapacity(PROPSPEC, 2*A_PtrSize)
NumPut(1, &PROPSPEC, "UInt")
NumPut(propid, &PROPSPEC+A_PtrSize, "UInt")
VarSetCapacity(PROPVARIANT, A_PtrSize == 4 ? 16 : 24)
; IPropertyStorage::ReadMultiple method
; https://msdn.microsoft.com/en-us/library/windows/desktop/aa379975(v=vs.85).aspx
DllCall(NumGet(NumGet(IPropertyStorage+0)+3*A_PtrSize), "UPtr", IPropertyStorage, "UInt", 1, "UPtr", &PROPSPEC, "UPtr", &PROPVARIANT, "UInt")
If (NumGet(&PROPVARIANT+0, "UShort") == 31) ; VT_LPWSTR
List .= StrGet(NumGet(&PROPVARIANT + 8, "UPtr"), 1000, "UTF-16") . "`n--------------------`n"
Else
List .= "PROPVARIANT.vt=" . NumGet(&PROPVARIANT+0, "UShort") . "`n--------------------`n"
DllCall("Ole32.dll\PropVariantClear", "UPtr", &PROPVARIANT)
}
MsgBox % Str . "`n`n" . List
}
;ObjRelease * ...
Code: Select all
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) . "`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)+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)
}
It might not retrieve it cuz it seem to be a control stream and no iproperty stream.Flipeador wrote:Also i do not know why it does not retrieve {4c8cc155-6c1e-11d1-8e41-00c04fb9386d}.
Yes but no.zcooler wrote:It might not retrieve it cuz it seem to be a control stream and no iproperty stream.
This Stream complies with the name, but not with the content, since it is zero bytes sized, and this is not correct. We could say that it is an "incomplete" or "erroneous" Control Stream.2.24.3 Control Stream wrote:A file that has one or more property sets associated with it through the alternate stream binding MUST have a control stream, which is an alternate stream with the name "{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}". This stream MUST contain the following packet. [...]
https://msdn.microsoft.com/en-us/library/dd942541.aspx
Example of how to create a Control Stream in AHK:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Code: Select all
FileOpen(A_Desktop . "\~tmp.txt", "w", "UTF-8-RAW").Write("I have a Control Stream inside of me")
cs := FileOpen(A_Desktop . "\~tmp.txt:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}", "w")
cs.Length := 2 + 2 + 4 + 16
cs.Seek(0)
; Reserved1 (2 bytes): MUST be set to zero, and nonzero values MUST be rejected.
cs.WriteUShort(0x0000)
; Reserved2 (2 bytes): MUST be set to zero, and MUST be ignored.
cs.WriteUShort(0x0000)
; ApplicationState (4 bytes): An application-provided value that MUST NOT be interpreted by the OLEPS implementation. If the application did not provide a value, it SHOULD be set to zero.
cs.WriteUInt(0x00000000)
; CLSID (16 bytes): An application-provided value that MUST NOT be interpreted by the OLEPS implementation. If the application did not provide a value, it SHOULD be absent.
CLSID := ""
VarSetCapacity(CLSID, 16)
DllCall("Ole32.dll\CLSIDFromString", "Str", "{00000000-0000-0000-0000-000000000000}", "UPtr", &CLSID, "UInt")
cs.RawWrite(&CLSID+0, 16)
cs.Close()
ExitApp
Edit2: 5.6.3 Document Properties Stream Name. That strange character at the beginning of the Streams names is for distinguish "IProperty Streams" from other Streams (note that we always refer to the content of the Stream and not the Stream itself).C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\shared\guiddef.h wrote:typedef struct _GUID {
⠀⠀unsigned long Data1;⠀⠀⠀⠀⠀⠀// 4 bytes | 4⠀| 00000000
⠀⠀unsigned short Data2;⠀⠀⠀⠀ ⠀// 2 bytes | 6⠀| 0000
⠀⠀unsigned short Data3;⠀⠀⠀⠀ ⠀// 2 bytes | 8⠀| 0000
⠀⠀unsigned char Data4[ 8 ];⠀⠀⠀// 8 bytes | 16 | 0000-000000000000
} GUID;
Code: Select all
Global Gui, Tab, Txt, Hex, Btn, LV, File
Gui := GuiCreate("-DPIScale", "Alternate Streams Viewer")
Gui.SetFont("s10", "Segoe UI")
Tab := Gui.AddTab3("x0 y0 w512 h310", "String view|Hexadecimal view")
Tab.UseTab(1)
Txt := Gui.AddEdit("x5 y30 w500 h272 +ReadOnly -Wrap")
Tab.UseTab(2)
Hex := Gui.AddEdit("x5 y30 w500 h272 +ReadOnly -Wrap")
Hex.SetFont("s9", "Monospac821 BT")
Tab.UseTab()
LV := Gui.AddListView("x0 y310 w510 h200 -Multi", "Name|Size|Stream Object")
LV.OnEvent("ItemSelect", "LVEvent")
Btn := Gui.AddButton("x0 y510 w510 h25", "Select file")
Btn.OnEvent("Click", "SelectFile")
Gui.Show("w510 h535")
Gui.OnEvent("Close", () => ExitApp())
Return
LVEvent(GuiCtrlObj, Item, Selected)
{
Txt.Text := "", Hex.Text := ""
Sleep(50)
Local Stream := LV.GetText(Item)
, f := FileOpen(File . (Stream == "<unnamed>" ? "" : ":" . Stream), "r")
If (!f)
{
MsgBox "The file couldn't be opened"
Return
}
Txt.Text := f.Read(10000)
f.Seek(0)
Local HexTxt := "0001 ", Arr := [], i := 0
While (!f.AtEOF)
{
HexTxt .= Format("{:02X} ", Arr[ObjPush(Arr, f.ReadUChar())])
If (!Mod(i:=A_Index, 16))
{
HexTxt .= " "
For k, v in Arr
HexTxt .= !v || v == 10 || v == 13 ? "." : 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.Text := HexTxt
}
SelectFile()
{
File := FileSelect(3)
If (ErrorLevel)
Return
Txt.Text := "", Hex.Text := ""
LV.Delete()
Local Each := "", Stream := ""
For Each, Stream in EnumStreams(File)
LV.Add(, Stream.Name == "" ? "<unnamed>" : Stream.Name, StrFormatByteSize(Stream.Size), Stream.Name ~= "^\x5" ? "TRUE" : "FALSE")
LV.ModifyCol(1, "AutoHdr")
LV.ModifyCol(2, "AutoHdr")
}
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