 |
|
|
 |
|
|
According the the documentation on BackupRead(), "lpContext [out] Pointer to a variable that receives a pointer to an internal data structure used by BackupRead to maintain context information during a backup operation.
You must set the variable pointed to by lpContext to NULL before the first call to BackupRead for the specified file or directory. The function allocates memory for the data structure, and then sets the variable to point to that structure. You must not change lpContext or the variable that it points to between calls to BackupRead.
To release the memory used by the data structure, call BackupRead with the bAbort parameter set to TRUE when the backup operation is complete."
Also, "bAbort [in] Indicates whether you have finished using BackupRead on the handle. While you are backing up the file, specify this parameter as FALSE. Once you are done using BackupRead, you must call BackupRead one more time specifying TRUE for this parameter and passing the appropriate lpContext. lpContext must be passed when bAbort is TRUE; all other parameters are ignored."
Note the last statement in te first quote of the documentation: "To release the memory...". You need to call BackupRead with bAbort set to true when you are finished with the context to free the memory allocated for the context data structure.
I use alternate streams on millions of files and when I'm verifying that the alternate streams that are supposed to exist actaully do, and contain the correct information, I can use up a lot of memory.
This is a bug. I've fixed it in the code I use.
Here is snippet I added after the while(continue) { } statement to close down the BackupRead()
Kernel32.BackupRead(hFile, ref sid, dwStreamHeaderSize, ref lRead, true, false, ref Context);
I also had to move the definition of lRead but this argument is ignored.
There is also a small performance enhancement that could be achieved by moving the "IntPtr pName = Marshal.AllocHGlobal(sid.dwStreamNameSize);" outside the while loop and moving the
"Marshal.FreeHGlobal(pName);" to the finally block. The only requirement would be to allocate enough memory for the largest alternate stream name.
scooter_jsm
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thanks for the feedback.
I had't looked at this code for four years, until I needed to write a utility to bulk un-block downloaded files a couple of weeks ago. Needless to say, this old version looked very messy, so I re-wrote it for C# 3. I've managed to fix this bug, and hopefully make it 64-bit compatible.
The new version isn't backwards-compatible with this version, because I've significantly simplified the interface. If I get time (and if there's any interest ), I might update the article.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Just an advisory for the unwary: this code is not 64-bit compatible (e.g. use of int's instead of IntPtr's). It may run inside the IDE but will crash hard if you run it straight from the command line.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
First off nice article and sample code. Everything works great but I was wondering how you would read/write/delete ADS from folders instead of just files. Any help would be appriciated, I know you can do it using the command line method, just not sure how to accomplish this in code.
Thanks.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I never realized you could do that! 
Most of the code should work with directories as well as files. You should only need to change the FileInfo member of the FileStreams class to a FileSystemInfo, and get rid of the FileSize and Size properties.
Let me know if you manage to get it working.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I am having problem using your example. When I retrieve substream using StreamInfo.open() sometimes I get null stream. When I check StreamInfo object that I am getting stream from it shows non zero size data in it so looks like data is there. I added few millisecond delay and retry and that works for some time but eventually I have same problem. Do you have any idea why this could happen?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I haven't seen any problems on my machine (XP SP1). It sounds as if the file may be locked by another process. 
Try changing the catch block of the Open method (line 177) to display the error message, if there is one. That might give you some more information to track down the problem.
catch (Exception ex) { Console.WriteLine("Error opening stream {0}:\n{1}", _name, ex); return null; }
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Actually I found the problem. In process of iterating through sub streams I was jumping to next substream without closing it. This is why when next time I try to open it it was giving me null as result stream. Thanks for the response.
-Raj
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I needed to make one small change to the code to get it to work with multiple streams. At the bottom of initStreams(), in the code that was
//Skip the stream contents int l = 0; int h = 0; Continue = Kernel32.BackupSeek(hFile, sid.Size.Low, sid.Size.High, ref l, ref h, ref Context); I needed to remove the assignment of Continue to get it to work (by the way, all of my streams were of a zero length during my testing)
//Skip the stream contents int l = 0; int h = 0; Kernel32.BackupSeek(hFile, sid.Size.Low, sid.Size.High, ref l, ref h, ref Context);
The code then falls out of the loop at the top in the first BackupRead
//Read the next stream header int lRead = 0; Continue = Kernel32.BackupRead(hFile, ref sid, dwStreamHeaderSize, ref lRead, false, false, ref Context); if (Continue && lRead == dwStreamHeaderSize) { ... } else break;
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
from the MSDN article:
"When you copy a multi-stream file on non-NTFS volumes, only the main stream is copied. This means you lose your extra data, because they can't come up again even if you copy the file back to an NTFS disk"
That's quite the limitation!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Warren Stevens wrote: That's quite the limitation!
Only if you're moving the files to a non-NTFS drive. If you only work with NTFS, the extra streams will stay with the file until you delete them.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
What applications are you writing where this would be acceptable? (this is a question, I'm not trying to be argumentative).
1) We write desktop (MFC) applications, and a good proportion of users still use 95/98 or use 2000 but wouldn't know if they have NTFS or not.
2) There's also the issue of backup. A lot of people with NTFS hard disks still use CD for backup.
I looked at streams a while ago and I thought they were great, except for this limitation. Anyway, don't take this as a criticism of your article, just of streams.
Warren
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I was thinking more along the lines of web apps. For example, using a stream to store a thumbnail for an image, which could be recreated if it got lost. I agree that they're not much use for critical data that can't be derived from the file unless you're only using NTFS.
With the issue of backup, copying files to the CD will loose the streams, but using the NT backup program *should* preserve them.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Yes, it's a pitty that so many people still use the old crappy FAT format.
However, especially the backup problem is a serious one, because it affects a lot of nice NTFS features. And the docs for all those nice backup utilities "designed for Win95/98/Me NT/2000/XP" never mention it ! Using such backup utility you loose:
- all alternate file streams - security settings - hardlinks (files get duplicated, a tricky source for inconsistencies) - sparse files (they get really big on the backup media) - meta data (XP stores the file metadata in an alternate file stream) - ...
Especially the security thing is a serious problem. Most people are not aware, that all security settings are lost after restoring a backup 
--
Daniel Lohmann
http://www.losoft.de (Hey, this page is worth looking! You can find some free and handy NT tools there )
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
If you use the "Microsoft Windows Backup 5.0" utility that comes with Windows 2000, it should restore all of the NTFS features (permissions, etc), as long as you restore back onto a NTFS disk.
Just to make your life a little more difficult - to get your backup to restore properly, the restore cannot be on an NTFS volume used in Windows NT 4.0.
Not only is it restricted to NTFS, you have to check what version it is.
Aargh!
Warren
Note: I haven't tried this, I just read the online help for the backup utility.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The WinRar utility is able to save the security settings and the ntfs streams into to archive. I don't know how it behaves on hardlinks. But it's great for backups!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
For NTFS Volumes shared to Mac clients. Mac resource forks are probably saved in the same fashion(I am just guessing). Hence writing server based stuff and handling Mac files residing on the Mac can be impossible unless one reads and writes all streams. Just a guess. To test use a Mac font residing on NT server which will look 0 Bytes because all the data will reside in the resource fork that is not otherwise accesible. Macs you can't destroy them, and they won't go away easily.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
There are some other products that do not 'manage' all the alternate streams associated with a file. Double-Take advertises itself as "Better Backups through Replication" but does not replicate all streams of an NTFS volume. There may be others.
scooter_jsm
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Very good, does anyone know if M$ is planning to drop support for alternate streams in files?
"When the only tool you have is a hammer, a sore thumb you will have."
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Who knows what WINFS (comin in 2005) will do to filestream. WINFS is based on SQL server. It might just be an SQL layer ontop of NTFS though....
|
| Sign In·View Thread·PermaLink | 2.00/5 (3 votes) |
|
|
|
 |