Solved

BACKUP_REPARSE_DATA

Posted on 2006-06-13
23
563 Views
Last Modified: 2008-01-09
I need to test a scenario where a file contains a BACKUP_REPARSE_DATA stream.  We have a customer that is unable to perform a BackupWrite() to this stream; they get an ERROR_ACCESS_DENIED.  I want to try performing a normal ReadFile() when I encounter a BACKUP_REPARSE_DATA and do some in-house testing before I build a patch.  What's the easiest way to create a test file with this stream?  Thanks for any help.
0
Comment
Question by:mike2036
  • 10
  • 9
  • 4
23 Comments
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Can you check whether the ACLs on the reparse point target prohibit access (you can use e.g. http://www.sysinternals.com/Utilities/Junction.html to find that target)?
0
 

Author Comment

by:mike2036
Comment Utility
Hi jkr,

Thanks for your response.  The customer can successfully BackupRead() the BACKUP_REPARSE_DATA stream but gets the 0x5 on BackupWrite().  The customer is running with admin rights.  We BackupWrite() to a temporary file we create and then rename to the destination file name (located in a separate destination folder) when the write is completed.  If understand your question correctly, if the ACLs prohibited access on the reparse point target, would we not fail on BackupRead()?  I've used the junction utility to attempt to make files have reparse points, but it apparently only sets reparse points on directories.

-Mike
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Only directories can have BACKUP_REPARSE_DATA, it does not make sense for files at all. Strange...
0
 

Author Comment

by:mike2036
Comment Utility
According to an MSDN article, and the trace logs our app produces, it appears files can and do have BACKUP_REPARSE_DATA streams:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/reparse_points_and_file_operations.asp
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Argh, yes, I forgot that you can set a NTFS hard link on files that way. BTW, the IMO easiest way to create such a file is calling 'DeviceIoControl()' with 'FSCTL_SET_REPARSE_POINT' or as shown in the code of 'ln' for Win32 at http://ashedel.chat.ru/source/ln/ln.c - the tricky part is filling the 'REPARSE_DATA_BUFFER'.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
Hi mike2036,
> We have a customer that is unable to perform a BackupWrite() to this
> stream; they get an ERROR_ACCESS_DENIED.

FYI:
Have your customer check the antivirus program.
Antivirus programs like Symantic, can cause problems with BACKUP_REPARSE_DATA.

David Maisonave (Axter)
Cheers!
0
 

Author Comment

by:mike2036
Comment Utility
I've been tinkering with the ln.c program (thanks for the link).  Unfortunately I haven't been able to successfully create a file that contains both reparse points and actual data.  It looks like there used to be a reparse tag of type IO_REPARSE_TAG_SYMBOLIC_LINK but that no longer is supported.  The author had it commented out and has the symbolic linking to always do a mount point, which is essentially a directory and not a file.  *Sigh*.  Ideally I would symbolically link a target file to a source file, and the target file would probably contain reparse points.  I've tried all the different reparse tags with no success.  Is there a way to create a symbolic link specific to a file that's not a mount point?

-Mike
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Hm, why don't you have your customer send you the file in question?
0
 

Author Comment

by:mike2036
Comment Utility
I had thought of that, but I wasn't sure if the reparse points would be lost when they make a copy of the file.  I figured when they copied it, the reparse points would be resolved in the file system and not represented as a separate stream.  I guess it's worth a try though.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
You need a driver and a service application to create a file that is a reparse point.
It's no easy task.

>>Hm, why don't you have your customer send you the file in question?

This is not practical, unless you have a utility program from the reparse point driver author.

If you try to copy a file that has a reparse point, it will normally trigger a recall of (or redirect to) the original file, so you will not get the reparse data, and instead get what the reparse point is pointing to.

What can sometimes work is if you do a backup of the file using backup software that uses the Windows Backup API functions.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>if the reparse points would be lost when they make a copy of the file.  

Noramlly, you would not get the repase point data, and instead you would get what it's pointing to, or what it represents (the original file).
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 

Author Comment

by:mike2036
Comment Utility
Hi Axter,

Thanks for your posts.  Do you know of any backup software that's freeware (or relatively cheap) that might accomplish this?  I've tried using Microsoft's backup utlity with no luck.  It's too bad there's no effective way to simulate reparse points without having to install a backup utility.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>Do you know of any backup software that's freeware (or relatively cheap) that might accomplish this?

I've been told that Nt-Backup can do it, but I've never tried it myself.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
If you're interested in creating your own utility program, you should be able to read the raw data from the file by opening the file via following method:
template<class T>
bool OpenReparseFile(const T *fileName,HANDLE &hFile)
{
      _ASSERT(fileName);
      hFile = CreateFileT(fileName,
                                    GENERIC_READ | GENERIC_WRITE,
                                    FILE_SHARE_READ | FILE_SHARE_WRITE,
                                    NULL,
                                    OPEN_EXISTING,
                                    FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN,
                                    NULL);

      if( hFile == INVALID_HANDLE_VALUE )
      {
            return FALSE;
      }

      return TRUE;
}

Then use the handle to read the file using Backup API functions:
      for(;;)
      {
            DWORD bytesRead = 0,bytesWritten = 0;
            if(!BackupRead( srcHandle, writeBuf,writeBufSize, &bytesRead, FALSE, TRUE, &srcContext ) )
            {
                  ret = FALSE;
                  break;
            }
            
            //done if bytes read is zero
            if (bytesRead == 0)
                  break;

This will give you the RAW data that should include all the streams.
You could store the raw data in a binary file, and then when you recieve the data in the destination box, you can write to the file using BackupWrite API function.
To open that target file, you'll want to use the following method:

template<class T>
bool OpenReparseFileForRestore(const T *fileName,HANDLE &hFile)
{
      _ASSERT(fileName);
      hFile = CreateFileT(fileName,
                                    GENERIC_READ | GENERIC_WRITE | WRITE_DAC| WRITE_OWNER,
                                    FILE_SHARE_READ | FILE_SHARE_WRITE,
                                    NULL,
                                    CREATE_ALWAYS ,
                                    FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN,
                                    NULL);

      if( hFile == INVALID_HANDLE_VALUE ) {
            return FALSE;
      }

      return TRUE;
}
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
FYI:
You can replace above CreateFileT with CreateFile, or if you want to keep the function as a template, you can add the following to your code:
inline HANDLE CreateFileT( IN LPCSTR lpFileName, IN DWORD dwDesiredAccess, IN DWORD dwShareMode, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, IN DWORD dwCreationDisposition, IN DWORD dwFlagsAndAttributes, IN HANDLE hTemplateFile     ) {return CreateFileA(GetValidPath(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);}
inline HANDLE CreateFileT( IN LPCWSTR lpFileName, IN DWORD dwDesiredAccess, IN DWORD dwShareMode, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, IN DWORD dwCreationDisposition, IN DWORD dwFlagsAndAttributes, IN HANDLE hTemplateFile     ) {return CreateFileW(GetValidPath(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);}

By keeping it as a template, you can use it with both UNICODE or ANSI file names.
0
 

Author Comment

by:mike2036
Comment Utility
Thanks for the sample code Axter.  I can't get NTBackup to produce a file with reparse points.  :(  It looks to only work with tape drives, and I don't have a tape drive handy for testing.  I tried using a floppy drive (yes I'm that desperate) but the bkp file is bigger than 1.44MB!  Are there any tape drive emulators out there?  Are there any usable driver/services I could use to build reparse data streams?  Man I can't believe how hard it has been just trying to create a test file.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>I tried using a floppy drive

You don't need to use a floppy.
I know the interface would lead you to believe that, but when you try to backup the file, ask to select from the list.
It should then prompt you for a file name (c:\Backup.bkf).
You should be able to back it up to your C: drive, as long as your source is a sub folder.
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
If you want to try the backup I just created of files with reparse point, download the following file:
http://axter.com/Backup.bkf.zip

You'll want to right click the above link, and select save target as.
0
 

Author Comment

by:mike2036
Comment Utility
Axter,

Thanks for the zip file.  How does the backup.bkf file work with backupread() and backupwrite()?  Or do I just need to run the restore utility.  Forgive my ignorance.
0
 
LVL 30

Accepted Solution

by:
Axter earned 250 total points
Comment Utility
>> Or do I just need to run the restore utility.

You just need to run the utility (Ntbackup).

NtBackup uses backupread and backupwrite API functions, and that's why it's able to preserve the reparse point stream.
0
 

Author Comment

by:mike2036
Comment Utility
Thanks very much axter!  I see the reparse point in this file.
0
 

Author Comment

by:mike2036
Comment Utility
Okay, a follow-up question:

I can successfully read the reparse points and write them to a destination folder.  When I write the file to the destination, I create a temporary file that I then rename to back to the original file name.  However, when I attempt to do this (via MoveFile), I get an ERROR_CANT_ACCESS_FILE.  I was also getting this error in CreateFile until I took your advice and set the FLAG_OPEN_REPARSE_POINT attribute on.  So is there a way to rename a file with reparse points?  Thanks for your continued help.

-Mike
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
>>So is there a way to rename a file with reparse points?

You should be able to rename the  file, but probably not by using the MoveFile API function.

Try use rename function.
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now