Page 1 of 1

Backing up locked Windows files via streams

Posted: Wed Mar 15, 2023 5:16 pm
by RichAlgeni
This is a continuation of a program worked on by Blueznl, Zebuddi, Nico and others, that hadn't been updated to the latest versions of PB and Windows. I have it working, seemingly correctly, however I am not sure where the actual file data can be located. This is to backup a file in use. If anyone could offer some suggestions, I'd be most grateful. Please note that this originated in the Tips and Tricks section, but I thought it would attract more eyes here.

Code: Select all

; ---------------------------------------
; PureBasic 6.01
; Compile to Unicode
; Read Stream for file or directory
;----------------------------------------

EnableExplicit

Define fileHandle.l
Define filename.s
Define context.i     = 0
Define bytes_read0.i = 0
Define bytes_read1.l = 0
Define seek_low.i    = 0
Define seek_high.i   = 0
Define result.i      = 0
Define streamNdx     = 0
Define streamID.i
Define streamHigh.q
Define streamLow.q
Define streamsize.q
Define namesize.l
Define totRead.i
Define *stream.WIN32_STREAM_ID
Define *buffer
Define byteNdx

filename = "D:\dev\ascii_chart.txt"
Debug "start"

; i can read al alternative streams from an open and locked file, using

fileHandle = CreateFile_(@filename, #READ_CONTROL, 0, 0, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, 0)

If fileHandle = 0
    Debug "can't open " + filename
    End
Else
    Debug "Processing: " + filename
EndIf

Debug "=========================================="

*stream.WIN32_STREAM_ID = AllocateMemory(20)
totRead = BackupRead_(fileHandle, *stream, 20, @bytes_read0, 0, 1, @context)

While (bytes_read0 <> 0 )
    Debug "totRead = " + Str(totRead)
    streamNdx = streamNdx + 1
    Debug "stream " + Str(streamNdx)
    Debug "bytes read " + Str(bytes_read0)
    streamID = *stream\dwStreamID
    Debug "stream id " + Str(streamID)

;    For byteNdx=0 To 40 Step 2
;        Debug Str(PeekW(*stream + byteNdx))        
;    Next

    Select streamID

    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_SECURITY_DATA ;0x00000003
        Debug "Security descriptor Data."
    Case #BACKUP_ALTERNATE_DATA ;0x00000004
        Debug "Alternative Data streams. This corresponds To the NTFS $DATA stream type on a named Data stream."
    Case #BACKUP_LINK ;0x00000005
        Debug "Hard link information. This corresponds To the NTFS $FILE_NAME stream type."
    Case 6 ;#BACKUP_PROPERTY_DATA ;0x00000006
        Debug "Property Data."
    Case 7 ;#BACKUP_OBJECT_ID ;0x00000007
        Debug "Objects identifiers. This corresponds To the NTFS $OBJECT_ID stream type."
    Case 8 ;#BACKUP_REPARSE_DATA ;0x00000008
        Debug "Reparse points. This corresponds To the NTFS $REPARSE_POINT stream type."
    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."
    Default
        Debug "Stream ID: " + Str(streamID)
    EndSelect

    namesize = *stream\dwStreamNameSize
    If namesize > 0
        Debug "namesize " + Str(namesize)
        *buffer = AllocateMemory(namesize)
        BackupRead_(fileHandle, *buffer, namesize, @bytes_read1, 0, 1, @context)
        Debug PeekS(*buffer, namesize / 2, #PB_Unicode)
        FreeMemory(*buffer)
    EndIf

    streamHigh = *stream\Size\LongPart\HighPart
    streamLow  = *stream\Size\LongPart\LowPart
    streamsize =  streamHigh << 32 | streamLow
    Debug "streamsize = " + Str(streamsize)

    Debug "=========================================="

    result = BackupSeek_(fileHandle, *stream\Size\LongPart\LowPart, *stream\Size\LongPart\HighPart, @seek_low, @seek_high, @context)
    Debug "Result = " + Str(Result)

    FreeMemory(*stream)
    *stream.WIN32_STREAM_ID = AllocateMemory(20)
    bytes_read0 = 0
    totRead = BackupRead_(fileHandle, *stream, 20, @bytes_read0, 0, 1, @context)
Wend

FreeMemory(*stream)

BackupRead_(fileHandle, 0, 0, @bytes_read0, 1, 0, @context)
CloseHandle_(fileHandle)

Debug "done"

Re: Backing up locked Windows files via streams

Posted: Fri Mar 17, 2023 1:52 am
by Thunder93
Based on what you've said here and what I could remember reading elsewhere yesterday on the subject from you... You have the wrong idea of streams and its use and abilities. You want to copy locked files, best approach would be using VSS (Volume Shadow Copy Service.) There might be something available on the forums here.

Re: Backing up locked Windows files via streams

Posted: Fri Mar 17, 2023 4:19 pm
by RichAlgeni
Thunder93 wrote: Fri Mar 17, 2023 1:52 am Based on what you've said here and what I could remember reading elsewhere yesterday on the subject from you... You have the wrong idea of streams and its use and abilities. You want to copy locked files, best approach would be using VSS (Volume Shadow Copy Service.) There might be something available on the forums here.
Understood. Thank you!