Reading, writing and deleting alternate data streams (ADS)
- John
- 5 days ago
- 3 min read
This post is one of a series providing implementation examples of Windows API Functions, Types, Enums and Consts using VBA. The code in this post can be used as-is, however, if you regularly (or even just occasionally) work with Windows API declarations in VBA, you may want to see the posts Automatically add Windows API declaration(s) and Using 'F1' to view Windows API web pages which explain some of the functionality that can be added to the VBE by VBE_Extras.
As well as relating to the Windows API, this post is the second of three relating to alternate data streams (ADS). If you haven't already, I suggest you read the first post in the series Getting the alternate data streams (ADS) for a file or folder which covers the basic principles of streams plus how to get the names of streams for a file or folder.
So, having identified that a file or folder has one or more (alternate data) streams, how to read the stream data?
It's actually surprisingly simple: append the stream name to the file path and read just as you would normally. You can do this with the VBA ...
... but this is a post about using the Windows API ... so the below code uses the CreateFile (despite its name, it opens files as well as creates files) and ReadFile Windows API Functions to do the reading.
And what about writing a stream to a file or folder? Again, just as simple: append the stream name to the file path and read just as you would normally. You can do this with the VBA ... but (again) this is a post about using the Windows API ... so the below code uses the CreateFile and WriteFile Windows API Functions to do the writing.
And what about deleting a stream? Err, not so simple. The VBA Kill statement doesn't work with streams. In this case, you have to use the Windows API ... the DeleteFile Function in this case.
In additional to those Functions, also required is the CloseHandle Function as the CreateFile Function returns a handle which must be closed, the FlushFileBuffers Function which forces all data to be written to a file immediately and the GetFileSizeEx Function to get the size of a file before it is read. There is also various Consts, Enums and Types to support the Functions. To explore each of these further, I suggest you download VBE_Extras and use the Using 'F1' to view Windows API web pages functionality to explore the Microsoft help pages for each of these.
Here's the code. This includes all of the "UtilsStreams" code from the Getting the alternate data streams (ADS) for a file or folder post plus the new code to read, write and delete the streams so, if you were following along with that post, then you can just replace all of the "UtilsStreams" code with this.
If you weren't following along with that post then copy and paste this code into a standard Module named "UtilsStreams".
Each VBA procedure is documented so that you can understand what it is doing.
And here is an example of how you might use the above code. Put this into a standard Module.
Before running this code, create a "test" file and / or folder with which to test before using this code on "real" files and folders. Once you have created a "test" file or folder, update the value of msPATH_TO_FILE_OR_FOLDER to point to it.
The first Sub of these three is very similar to that in the Getting the alternate data streams (ADS) for a file or folder post except it now also prints the data contained in the stream (except for the default stream ... as the default stream IS the file / folder) as well as the name of the stream.
Using the second and third Subs, you can write and delete streams to the test file / folder ... which then makes the Sub to read the streams somewhat more impressive.
You can, of course, change the name of the stream that is written / delete by changing the value of the sSTREAM_NAME constants (ensure it starts with ":" and ends with ":$DATA") and you can change the value of the sStreamData variable to contain different text so that different data is written to the stream.
The next post will cover the ":Zone.Identifier:$DATA" stream and why it is important to you, the VBA developer!


Comments