WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Files and Directories

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Alternate Data Stream UDFs

 Keywords: Alternate Data Stream ADS udfFileDeleteStream udfFileGetStream udfFileItemizeStream xEnumStreams FileItemize ZoneIdentifer Blocked File Find Itemize Enumerate List Array ReportView Get Delete lads

The NTFS file system provides applications the ability to create alternate data streams of information. By default, all data is stored in a file's main unnamed data stream, but by using the syntax 'file:stream', you are able to read and write to alternates.

Windows apparently does not come with any tools that let you see which files have streams, so I've attempted to create some User Defined Functions that should help with the following:

;***************************************************************************
;**
;**             Alternate Data Stream (ADS) UDF Library
;**
;** Purpose:  Handle Alternate Data Streams in Files
;**
;** Requirements: WILX and FileAndFolder Extenders
;**
;**
;** udfFileDeleteStream  ( sFullFileName, sStreamName )
;**    Delete a specific files Alternate Data Stream (ADS)
;**
;** udfFileGetStream ( sFullFileName )
;**    Gets a specific files Alternate Data Stream (ADS)
;**
;** udfFileItemizeStream ( sRootDir, sFileMask, nRecurse )
;**    Enumerate all files with an Alternate Data Stream (ADS)
;**
;**
;**
;** Revisions:
;**
;** 1.0 2012.11.16.Deana.Falk
;**    Initial release.
;**    udfFileDeleteStream
;**    udfFileGetStream
;**    udfFileItemizeStream
;**
;** 1.1 2012.11.19.Deana.Falk
;**    udfFileDeleteStream - Added code to check for blank stream name.
;**    udfFileGetStream/udfFileDeleteStream added code to check the file wasn't open in read deny
;***************************************************************************


;///////////////////////////////////////////////////////////////////////////////
#DefineFunction udfFileDeleteStream ( sFullFileName, sStreamName )

   ;***************************************************************************
   ;**                    udfFileDeleteStream
   ;**  Delete a specific files Alternate Data Stream (ADS)
   ;**
   ;**  Parameters
   ;**  [sFullFileName]
   ;**
   ;**  [sStreamName]
   ;**
   ;**  Returns 1 on success. 0 on failure.
   ;**
   ;***************************************************************************
   If FileExist( sFullFileName ) != 1
      Pause('ADS Error','Unable to locate or open the specified file' )
      Exit
   EndIf

   ; Check for blank stream name?
   If StrTrim(sStreamName) == ""
      Pause('ADS Error','Blank stream name specified.' )
      Exit
   EndIf

   FileDelete( sFullFileName : sStreamName )

   Return 1

#EndFunction
;///////////////////////////////////////////////////////////////////////////////


;///////////////////////////////////////////////////////////////////////////////
#DefineFunction udfFileGetStream ( sFullFileName )

   ;***************************************************************************
   ;**                    udfFileGetStream
   ;**  Gets a specific files Alternate Data Stream (ADS)
   ;**
   ;**  Parameters
   ;**  [sFullFileName]
   ;**
   ;**  Returns sStreamName or blank string for if not ADS exists
   ;**
   ;***************************************************************************

   ;Load Appropriate Extenders: WILX
   If WinMetrics(-2) == 3 Then AddExtender("WILX64I.DLL") ; 64-bit
   Else AddExtender("WILX44I.DLL") ; 32-bit

   If FileExist( sFullFileName ) != 1
      Pause('ADS Error','Unable to locate or open the specified file' )
      Exit
   EndIf

   arrStream = xEnumStreams( sFullFileName, 0 )

   If ArrInfo(arrStream, 1 ) > 0
      sStreamName = arrStream[0,0]
   Else
      sStreamName = ""
   EndIf

   Return sStreamName

#EndFunction
;///////////////////////////////////////////////////////////////////////////////

;///////////////////////////////////////////////////////////////////////////////
#DefineFunction udfFileItemizeStream (sRootDir, sFileMask, nRecurse)

   ;***************************************************************************
   ;**                     udfFileItemizeStream
   ;**  Enumerate all files with an Alternate Data Stream (ADS)
   ;**
   ;** Parameters
   ;**  [sRootDir]
   ;**
   ;**  [sFileMask]
   ;**
   ;**  [nRecurse] bit mask of search options.
   ;**   Flag   Meaning
   ;**   0      Use extender defaults. (same as not specifying a value for the parameter)
   ;**   1      Include 'hidden' file and folders in search results.
   ;**   2      Include 'system' files and folders in the search results.
   ;**   16     Search the sub-directories of root-path.
   ;**
   ;**
   ;** Returns Blank string if no matching files found or a 2 dimensional array in the format
   ;**  Col     Data
   ;**   0      Filename
   ;**   1      StreamName
   ;**
   ;***************************************************************************

   ;Load Appropriate Extenders: WILX and FileAndFolder
   If WinMetrics(-2) == 3 Then AddExtender("WILX64I.DLL") ; 64-bit
   Else AddExtender("WILX44I.DLL") ; 32-bit
   If WinMetrics(-2) == 3 Then AddExtender("WWFAF64I.DLL") ; 64-bit
   Else AddExtender("WWFAF44I.DLL") ; 32-bit

   If !DirExist( sRootDir )
      Pause('ADS Error','Unable to locate specified directory' )
      Exit
   EndIf

   ; Initialize an Array
   nSize = 1024
   arrADS = ArrDimension(nSize,2)
   ArrInitialize(arrADS, "")

   ; Open a search handle
   fsHandle = fafOpen( sRootDir, sFileMask, nRecurse )
   ; Search for a specific file
   nCount = 0
   While 1
      sFileName= fafFind( fsHandle )
      If sFileName == "" Then Break
      arrStream = xEnumStreams( sFileName, 0 )
      If nCount>=nSize
           ;Resize array
           nNewSize = nSize*2
           ArrayRedim( arrADS, nNewSize ,2 )
           nSize = nNewSize
      EndIf
      If ArrInfo(arrStream, 1 ) > 0
         arrADS[nCount,0] = sFileName
         arrADS[nCount,1] = arrStream[0,0]
         nCount = nCount + 1
      EndIf
   EndWhile
   fafClose(fsHandle)

   ; Clean up array by removing undefined elements.
   ArrayRedim( arrADS, nCount ,2 )

   ; Handle Empty Array
   If ArrInfo( arrADS, 1 ) == 0
      arrADS = ArrDimension(1,2)
      ArrInitialize(arrADS, "")
   EndIf

   Return arrADS

#EndFunction
;///////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////


;***************************************************************************
;**
;**            MAIN
;**
;***************************************************************************

RootDir = DirScript()   ; Tested
;RootDir = 'c:\temp\'   ; Tested
;RootDir = ''           ; Tested

FileMask = '*'     ; Tested
;FileMask = ''     ; Tested
;FileMask = '*.*'  ; Tested
;FileMask = 'xxx'  ; Tested

Flag = 1|2|16 ; All Flags          ; Tested
;Flag = 0      ; No Recurse        ; Tested
;Flag = 1      ; Include 'hidden'  ; Tested
;Flag = 2      ; Include 'system'  ; Tested
;Flag = 16     ; Recurse           ; Tested

; Enumerate all files with an Alternate Data Stream (ADS)
arrADS = udfFileItemizeStream ( RootDir, FileMask, Flag )


; Display all files with an Alternate Data Stream (ADS)
title =  'File - Alternate Data Streams: ' : ArrInfo( arrADS, 1 )
; title =  'File - Alternate Data Streams: '

MyDialogFormat=`WWWDLGED,6.2`

MyDialogCaption=title
MyDialogX=002
MyDialogY=059
MyDialogWidth=766
MyDialogHeight=353
MyDialogNumControls=004
MyDialogProcedure=`DEFAULT`
MyDialogFont=`DEFAULT`
MyDialogTextColor=`DEFAULT`
MyDialogBackground=`DEFAULT,DEFAULT`
MyDialogConfig=0

MyDialog001=`231,333,036,012,PUSHBUTTON,"PushButton_OK",DEFAULT,"OK",1,10,32,DEFAULT,DEFAULT,DEFAULT`
MyDialog002=`499,333,036,012,PUSHBUTTON,"PushButton_Cancel",DEFAULT,"Cancel",0,20,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog003=`005,037,742,278,REPORTVIEW,"ReportView_1",arrADS,DEFAULT,DEFAULT,30,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog004=`009,015,218,012,STATICTEXT,"StaticText_1",DEFAULT,"Choose a File to Delete the Alternate Data Stream",DEFAULT,40,DEFAULT,"Microsoft Sans Serif|6656|70|34",DEFAULT,DEFAULT`

ButtonPushed=Dialog("MyDialog")

; Check that the user selected an item
If ArrInfo( arrADS, 1 ) == 0
   Pause( 'ADS Notice', 'No file selected to delete ADS.' )
   Exit
EndIf

FullFileName = arrADS[0,0]
StreamName = arrADS[0,1]

; Delete alternate data stream
udfFileDeleteStream ( FullFileName, StreamName )

; Confirm stream name is delete
streamname = udfFileGetStream ( FullFileName )
If streamname != ''
   Pause( 'ADS Notice', 'Uh oh! ADS still exists on selected file.' )
   Exit
EndIf

Pause( 'ADS Delete Sucessfull', 'Deleted stream name: ' : StreamName : ' from the file: ': FullFileName )
Exit







Article ID:   W18360
Filename:   Alternate Data Stream UDFs.txt
File Created: 2012:11:19:16:05:30
Last Updated: 2012:11:19:16:05:30