Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 583
  • Last Modified:

BACKUP_REPARSE_DATA

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
mike2036
Asked:
mike2036
  • 10
  • 9
  • 4
1 Solution
 
jkrCommented:
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
 
mike2036Author Commented:
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
 
jkrCommented:
Only directories can have BACKUP_REPARSE_DATA, it does not make sense for files at all. Strange...
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
mike2036Author Commented:
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
 
jkrCommented:
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
 
AxterCommented:
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
 
mike2036Author Commented:
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
 
jkrCommented:
Hm, why don't you have your customer send you the file in question?
0
 
mike2036Author Commented:
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
 
AxterCommented:
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
 
AxterCommented:
>>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
 
mike2036Author Commented:
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
 
AxterCommented:
>>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
 
AxterCommented:
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
 
AxterCommented:
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
 
mike2036Author Commented:
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
 
AxterCommented:
>>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
 
AxterCommented:
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
 
mike2036Author Commented:
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
 
AxterCommented:
>> 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
 
mike2036Author Commented:
Thanks very much axter!  I see the reparse point in this file.
0
 
mike2036Author Commented:
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
 
AxterCommented:
>>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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 10
  • 9
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now