## demonstrates using BackupSeek to enumerate data streams for a file import win32file, win32api, win32con from win32com import storagecon import pythoncom, pywintypes import struct, traceback stream_types={ win32con.BACKUP_DATA:"Standard data", win32con.BACKUP_EA_DATA:"Extended attribute data", win32con.BACKUP_SECURITY_DATA:"Security descriptor data", win32con.BACKUP_ALTERNATE_DATA:"Alternative data streams", win32con.BACKUP_LINK:"Hard link information", win32con.BACKUP_PROPERTY_DATA:"Property data", win32con.BACKUP_OBJECT_ID:"Objects identifiers", win32con.BACKUP_REPARSE_DATA:"Reparse points", win32con.BACKUP_SPARSE_BLOCK:"Sparse file" } tempdir=win32api.GetTempPath() tempfile=win32api.GetTempFileName(tempdir,'bkr')[0] print('Filename:',tempfile) f=open(tempfile,'w') f.write('some random junk'+'x'*100) f.close() f=open(tempfile+':streamdata','w') f.write('data written to alternate stream'+'y'*100) f.close() f=open(tempfile+':anotherstream','w') f.write('z'*200) f.close() ## add Summary Information, which is stored as a separate stream m=storagecon.STGM_READWRITE | storagecon.STGM_SHARE_EXCLUSIVE |storagecon.STGM_DIRECT pss=pythoncom.StgOpenStorageEx(tempfile, m, storagecon.STGFMT_FILE, 0 , pythoncom.IID_IPropertySetStorage,None) ps=pss.Create(pythoncom.FMTID_SummaryInformation,pythoncom.IID_IPropertyStorage,0,storagecon.STGM_READWRITE|storagecon.STGM_SHARE_EXCLUSIVE) ps.WriteMultiple((storagecon.PIDSI_KEYWORDS,storagecon.PIDSI_COMMENTS),('keywords','comments')) ps=None pss=None sa=pywintypes.SECURITY_ATTRIBUTES() sa.bInheritHandle=False h=win32file.CreateFile(tempfile, win32con.GENERIC_ALL ,win32con.FILE_SHARE_READ, sa, win32con.OPEN_EXISTING, win32file.FILE_FLAG_BACKUP_SEMANTICS , None) """ stream header: typedef struct _WIN32_STREAM_ID { DWORD dwStreamId; DWORD dwStreamAttributes; LARGE_INTEGER Size; DWORD dwStreamNameSize; WCHAR cStreamName[ANYSIZE_ARRAY]; } """ win32_stream_id_format="LLQL" win32_stream_id_size=struct.calcsize(win32_stream_id_format) def parse_stream_header(h,ctxt,data): stream_type, stream_attributes, stream_size, stream_name_size=struct.unpack(win32_stream_id_format,data) print('\nType:',stream_type,stream_types[stream_type], 'Attributes:', stream_attributes, 'Size:', stream_size, 'Name len:',stream_name_size) if stream_name_size>0: ## ??? sdk says this size is in characters, but it appears to be number of bytes ??? bytes_read, stream_name_buf, ctxt=win32file.BackupRead(h, stream_name_size, None, False, True, ctxt) stream_name=pywintypes.UnicodeFromRaw(stream_name_buf[:]) else: stream_name='Unnamed' print('Name:'+stream_name) return ctxt, stream_type, stream_attributes, stream_size, stream_name_size, stream_name ctxt=0 win32_stream_id_buf=None ## gets rebound to a writable buffer on first call and reused while 1: bytes_read, win32_stream_id_buf, ctxt=win32file.BackupRead(h, win32_stream_id_size, win32_stream_id_buf, False, True, ctxt) if bytes_read==0: break ctxt, stream_type, stream_attributes, stream_size, stream_name_size, stream_name=\ parse_stream_header(h, ctxt, win32_stream_id_buf[:]) if stream_size>0: bytes_moved=win32file.BackupSeek(h, stream_size, ctxt) print('Moved: ',bytes_moved) win32file.BackupRead(h, win32_stream_id_size, win32_stream_id_buf, True, True, ctxt) win32file.CloseHandle(h)