Page 1 of 1
streams and reading from locked files
Posted: Tue May 18, 2004 8:36 am
by blueznl
fweil, think i fixed it...
Code: Select all
; purebasic survival guide - pb3.90 sp1
; streams_1.pb - 18.05.2004 ejn (blueznl)
; http://www.xs4all.nl/~bluez/datatalk/purebasic.htm
;
; - NOT FOR BEGINNERS !!!
; - only on nt / win2k / xp using ntfs
; - backupread_()
; - open and read locked files
; - enumerate nt streams in files
; - needs double support to work on large files (> 2 gb)
;
filename.s = "c:\test.txt"
file_h = CreateFile_(@filename, #READ_CONTROL, 0, 0, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, 0)
;
Debug "start"
;
If file_h = 0
Debug "can't open"
End
EndIf
;
*buffer = AllocateMemory(4096)
*stream.WIN32_STREAM_ID = *buffer
;
context.l = 0
bytes_read.l = 0
;
Repeat
;
z = BackupRead_(file_h, *buffer, 20, @bytes_read, 0, 1, @context)
;
; dunno why, but backupread() sometimes returns 1 when it should be zero?!? so check for the nr. of bytes as well
;
If bytes_read = 0
z = 0
EndIf
;
If z <> 0
;
n+1
Debug ""
Debug "stream "+Str(n)
id = *stream\dwStreamID
Debug "stream id "+Str( id )
Select id
Case #BACKUP_DATA
Debug "data"
Case #BACKUP_EA_DATA
Debug "extended attribute"
Case #BACKUP_SECURITY_DATA
Debug "security data"
Case #BACKUP_ALTERNATE_DATA
Debug "alternate data"
Case #BACKUP_LINK
Debug "hard link information"
Default
Debug "unknown id type"
z=0
EndSelect
;
If z <> 0
;
Debug "stream attributes %"+Bin( *stream\dwStreamAttributes )
;
size.l = *stream\dwStreamSizeLow + *stream\dwStreamSizeHigh *256*256*256*256
namesize.l = *stream\dwStreamNameSize
;
Debug "stream size "+Str(size)
Debug "name size "+Str(namesize)
;
If namesize > 0
BackupRead_(file_h, *buffer, namesize, @bytes_read, 0, 1, @context)
l = WideCharToMultiByte_(#CP_OEMCP,0,*buffer,-1,0,0,0,0)
name.s = Space(l)
l = WideCharToMultiByte_(#CP_OEMCP,0,*buffer,-1,@name,l,0,0)
Debug "name... "+Str(bytes_read)+" "+name
EndIf
If size > 0
seeked_l.l = 0
seeked_h.l = 0
BackupSeek_(file_h, size, 0, @seeked_l.l, @seeked_h.l, @context)
Debug "data..."+Str(seeked_l + seeked_h *256*256*256*256)
EndIf
EndIf
EndIf
Until z = 0
;
BackupRead_(file_h, *buffer,0,@bytes_read,1,0,@context)
CloseHandle_(file_h)
;
Debug ""
Debug "done"
Posted: Thu Nov 01, 2007 10:32 pm
by blueznl
My sample above is NOT totally working. It is, sort of. Here's a little updated code, which should work better, but which does not yet handle 'locked' files well. Some more puzzling to do...
Code: Select all
; purebasic survival guide - pb4.02
; ntfs streams 1.pb - 01.11.2007 ejn (blueznl)
; http://www.xs4all.nl/~bluez/datatalk/purebasic.htm
;
; - NOT FOR BEGINNERS !!!
; - only on nt / win2k / xp using ntfs
; - bakcupread_()
; - open and read locked files (well, not yet...)
; - enumerate nt streams in files
; - obviously, you need to create a file that supports streams :-) this code does not create one...
filename.s = "c:\test.txt"
Debug "start"
;
; i can read al alternative streams from an open and locked file, using
;
; OpenFile(1,filename)
; file_h = CreateFile_(@filename, #READ_CONTROL, 0, 0, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, 0)
;
; but that won't help me reading the data from the primary (unnamed) stream!
; ... i guess i'll have to expand the above and include changing the rights of my process if i want
; to open locked files... but i don't know yet how to, any help appreciated!
;
; to open and read multiple streams from a normal file (that's not in use) use this:
;
file_h = CreateFile_(@filename, #GENERIC_READ, 0, 0, #OPEN_EXISTING, 0, 0)
;
If file_h = 0
Debug "can't open"
End
EndIf
;
context.l = 0
bytes_read.l = 0
seek_l = 0
seek_h = 0
;
Repeat
;
*buffer = AllocateMemory(SizeOf(WIN32_STREAM_ID))
*stream.WIN32_STREAM_ID = *buffer
z = BackupRead_(file_h, *buffer, 20, @bytes_read, 0, 1, @context)
;
n = n+1
Debug ""
Debug "stream "+Str(n)
Debug "bytes read "+Str(bytes_read)
id = *stream\dwStreamID
Debug "stream id "+Str(id)
Select id
Case #BACKUP_DATA
Debug "data"
Case #BACKUP_EA_DATA
Debug "extended attribute"
Case #BACKUP_SECURITY_DATA
Debug "security data"
Case #BACKUP_ALTERNATE_DATA
Debug "alternate data"
Case #BACKUP_LINK
Debug "hard link information"
Default
Debug "unknown id type"
z=0
EndSelect
Debug "stream attributes %"+Bin( *stream\dwStreamAttributes )
streamsize.l = *stream\dwStreamSizeLow + *stream\dwStreamSizeHigh *256*256*256*256
Debug "stream size "+Str(streamsize)
namesize.l = *stream\dwStreamNameSize
Debug "name size "+Str(namesize)
FreeMemory(*buffer)
;
If namesize > 0
*buffer = AllocateMemory(namesize+SizeOf(WIN32_STREAM_ID))
BackupRead_(file_h,*buffer,namesize,@bytes_read,0,1,@context)
l = WideCharToMultiByte_(#CP_OEMCP,0,*buffer,-1,0,0,0,0)
name.s = Space(l)
l = WideCharToMultiByte_(#CP_OEMCP,0,*buffer,-1,@name,l,0,0)
Debug "name "+name+" ("+Str(bytes_read)+")"
FreeMemory(*buffer)
EndIf
;
If streamsize > 0
*buffer = AllocateMemory(streamsize+SizeOf(WIN32_STREAM_ID))
Debug BackupRead_(file_h,*buffer,streamsize,@bytes_read,0,1,@context)
FreeMemory(*buffer)
Debug "read "+Str(bytes_read)
EndIf
;
; you have to use a BackupSeek_() to go to the next stream
;
; (strangely enough, you could bypass the BackupSeek_() if the streem has no data block but that's undocumented so always use BackupSeek_())
;
BackupSeek_(file_h, streamsize, 0, @seek_l, @seek_h, @context)
Debug "skipped "+Str(seek_l+seek_h*256*256*256*256)
;
Until z = 0
;
BackupRead_(file_h,0,0,@bytes_read,1,0,@context)
CloseHandle_(file_h)
;
Debug ""
Debug "done"
Posted: Thu Nov 01, 2007 10:36 pm
by Mistrel
Would you give an example of what kind of application this would be useful for?
Posted: Thu Nov 01, 2007 10:38 pm
by blueznl
Backup tools, log viewers, anti-virus, etc.
Re: streams and reading from locked files
Posted: Mon Sep 14, 2009 11:43 am
by akj
@blueznl:
Thank you for that posting, which my searching missed.
It appears to be very useful and I will analyse it.
@Mistrel:
I was intending to use ADS for storing an application's historical debug output within the same file as the working data. This way the debugging information would be transparent to the user who would [for simplicity] see just one file only, but would still be available to me for analysis.
Further, I was contemplating storing user preferences (currently held in a .ini file) here also.
To be more specific, I was thinking of doing the above for my greatly modified version of Horst Schaeffer's PB date reminder program from
http://home.mnet-online.de/horst.muc/win.htm so that a single .LST file holds all the data. I rely heavily on my modified version of this program for personal needs, and frequently 'improve' it.
Re: streams and reading from locked files
Posted: Mon Sep 13, 2010 12:37 am
by Nico
Don't work with directory, any solution?
Re: streams and reading from locked files
Posted: Mon Sep 13, 2010 9:06 am
by blueznl
That depends. Streams are not supposed to be working with directories, they are part of files...
Re: streams and reading from locked files
Posted: Mon Sep 13, 2010 2:26 pm
by jpd
Hi,
@blueznl
thanks for this nice piece code.
Have use this some time ago in a project!
@Nico
if you change the line
Code: Select all
file_h = CreateFile_(@filename, #GENERIC_READ, 0, 0, #OPEN_EXISTING, 0, 0)
with
Code: Select all
file_h = CreateFile_(@filename,#GENERIC_READ,#FILE_SHARE_READ, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, #Null)
then is possible to read stream on folder...
Best
jpd
Re: streams and reading from locked files
Posted: Mon Sep 13, 2010 5:18 pm
by blueznl
That's interesting, didn't know that
streams could be put on folders. Oh well, the miracles of Windows

Re: streams and reading from locked files
Posted: Mon Sep 13, 2010 9:02 pm
by Nico
@jpd
Ok
@blueznl
Your code contains errors, I made a new version.
Compile to Unicode!
Code: Select all
; ---------------------------------------
; PureBasic 4.51
; Compile to Unicode
; Read Stream for file or directory
;----------------------------------------
filename.s = "C:\Documents And Settings\Nico\Bureau\Test.txt"
Debug "start"
;
; i can read al alternative streams from an open and locked file, using
file_h = CreateFile_(@filename, #READ_CONTROL, 0, 0, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, 0)
If file_h = 0
Debug "can't open"
End
EndIf
;
context.l = 0
bytes_read.l = 0
bytes_read1.l = 0
seek_l = 0
seek_h = 0
result.l=0
*stream.WIN32_STREAM_ID = AllocateMemory(20)
z = BackupRead_(file_h, *stream, 20, @bytes_read, 0, 1, @context)
While (bytes_read <> 0 )
Debug ""
n = n+1
Debug "stream "+Str(n)
Debug "bytes read "+Str(bytes_read)
id = *stream\dwStreamID
Debug "stream id "+Str(id)
Select id
Case #BACKUP_ALTERNATE_DATA ;0x00000004
Debug "Alternative Data streams. This corresponds To the NTFS $DATA stream type on a named Data stream."
Case #BACKUP_DATA ;0x00000001
Debug "Standard Data. This corresponds To the NTFS $DATA stream type on the Default (unnamed) Data stream."
Case #BACKUP_EA_DATA ;0x00000002
Debug "Extended attribute Data. This corresponds To the NTFS $EA stream type."
Case #BACKUP_LINK ;0x00000005
Debug "Hard link information. This corresponds To the NTFS $FILE_NAME stream type."
Case 7 ;#BACKUP_OBJECT_ID ;0x00000007
Debug "Objects identifiers. This corresponds To the NTFS $OBJECT_ID stream type."
Case 6 ;#BACKUP_PROPERTY_DATA ;0x00000006
Debug "Property Data."
Case 8 ;#BACKUP_REPARSE_DATA ;0x00000008
Debug "Reparse points. This corresponds To the NTFS $REPARSE_POINT stream type."
Case #BACKUP_SECURITY_DATA ;0x00000003
Debug "Security descriptor Data."
Case 9 ;#BACKUP_SPARSE_BLOCK ;0x00000009
Debug "Sparse file. This corresponds To the NTFS $DATA stream type For a sparse file."
Case 10 ;#BACKUP_TXFS_DATA ;0x0000000A
Debug "Transactional NTFS (TxF) Data stream. This corresponds To the NTFS $TXF_DATA stream type."
EndSelect
;
namesize.l = *stream\dwStreamNameSize
Debug "name size "+Str(namesize)
If namesize > 0
*buffer = AllocateMemory(namesize)
BackupRead_(file_h,*buffer,namesize,@bytes_read1,0,1,@context)
Debug PeekS(*buffer,namesize/2,#PB_Unicode)
FreeMemory(*buffer)
EndIf
;
streamHight.q=*stream\dwStreamSizeHigh & $FFFFFFFF
streamLow.q=*stream\dwStreamSizeLow & $FFFFFFFF
streamsize.q = streamHight<<32 | streamLow
Debug "streamsize="+Str(streamsize)
;
result.l= BackupSeek_(file_h, *stream\dwStreamSizeLow, *stream\dwStreamSizeHigh, @seek_l, @seek_h, @context)
Debug "Result="+Str(Result)
;
FreeMemory(*stream)
*stream.WIN32_STREAM_ID = AllocateMemory(20)
bytes_read = 0
z = BackupRead_(file_h, *stream, 20, @bytes_read, 0, 1, @context)
Wend
FreeMemory(*stream)
BackupRead_(file_h,0,0,@bytes_read,1,0,@context)
CloseHandle_(file_h)
;
Debug ""
Debug "done"