reparse point

Hello everybody,
I’m new in the driver development.
What I’m trying to do is to move a file to offline storage but leave a file stub in the main storage.
Is there any good document or code example on how the reparse point and stub file works?
Can it be done using a minifilter driver?

Thanks a lot
Payman

Payman,

This is kind of a broad question. If I were you, I would consider purchasing the book “Microsoft Windows Internals” Fourth Edition by Mark E. Russinovich and David A. Solomon. It talks briefly about how to use reparse points for HSM-type solutions, plus is generally informative and useful for understanding how the kernel and filesytem work.

I’m not sure if there is any good documentation on reparse point usage in HSM solutions, but you can pick up hints from here or there. You’ll also want to read Microsoft’s “Filter Driver Development Guide” (Google it), which has some info on using reparse points. Be sure to search through these forums for info on reparse points, as well.

I’m guessing the basic idea of what you’ll want to do is something along these lines:

  • Copy data to remote storage
  • Tag file with reparse point
  • Remove data from file & optionally mark as sparse
  • Write a minifilter which looks for STATUS_REPARSE in the post-create function for MJ_CREATE operations which would then do something to restore the file and or redirect the open to remote storage and then re-issue the IRP

Don’t be fooled, though, it’s harder than it sounds.

Here’s some C++ code that might help you (or anyone else) set reparse points (—> USER-MODE ONLY <—):

// Returned size fron DeviceIoControl
DWORD dwReturnedSize = 0;

// Should make sure this file is on an NTFS volume, otherwise this will fail
if(! this->VolumeSupportsReparsePoints(this->mwsFileName) )
return false;

// Get a handle to the file to set the reparse point
HANDLE hFile = CreateFile( this->mwsFileReadWriteName.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
NULL );

// Make sure we could create the new file
if (hFile == INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
return false;
}

// Actually tag the file with the reparse point
if ( ! DeviceIoControl( hFile,
FSCTL_SET_REPARSE_POINT,
this->mpReparseInfo,
this->mpReparseInfo->ReparseDataLength + this->mulHeaderSize,
NULL,
0,
&dwReturnedSize,
NULL ) )
{
// Signals a failure
CloseHandle(hFile);
return false;
}

// Everything seemed to work correctly!
CloseHandle(hFile);
return true;

====================

Hope that helps,

Bill

Bill,
Thank you very much for your reply. The scenario that you wrote is exactly what I intend to do. I do actually have the book that you mentioned and it helped me to understand the concept of the reparse points.

If I understand correctly the reparse point has data structure that contains information about where the actual file is located.
Could you give me a pointer how the minifilter driver uses get hold of this structure and how it would restore the file?

Thanks again
Payman

Payman,

When setting a reparse point, or upon receiving STATUS_REPARSE in a filter’s post-create you will want to use the REPARSE_GUID_DATA_BUFFER structure. This structure is defined in winnt.h for user-mode or ntifs.h in kernel-mode. I would highly suggest reading all the documentation you can find on this structure (i.e. search the forums again, check MSDN) and reviewing the ntifs.h header file.

This structure contains a few fields that will be of interest to you. First is the ReparseTag. Here’s what the WDK documetation says about it:

Reparse point tags are assigned to third parties by Microsoft. You may request more than one reparse point for use with a file system, file system filter driver, or minifilter driver. For more information about requesting a reparse point tag from Microsoft, see the Windows IFS Kit Web site.

For testing or until you contact MS, you could use a value of 0x4 or something like that for your tag. Another field you’ll need is the ReparseGuid, which you define for your filter. Use guidgen.exe or something like that to generate the GUID for you. You’ll need to send this GUID to MS when requesting your reparse tag.

The last, but certainly most important field, is the DataBuffer. This is a user-defined byte array which can contain any data you want, so long as it’s less than or equal to MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16K). You can develop some type of custom data structure for your reparse point that can contain it’s remote location, server name, etc.

So here’s a summary of what your driver would probably want to do:

  • Check for STATUS_REPARSE in post create of MJ_CREATE operation. If the ReparseTag and ReparseGuid from the pCallbackData->TagData structure match your specific tag and GUID, then it;s a file you’ll want to process

  • Read data from the DataBuffer member of the pCallbackData->TagData structure and load it into your custom structure with remote file location, server, etc.

  • Issue commands to restore the file using this data. I would suggest doing this in user-mode.

  • Pend the IRP and put the CallbackData in a cancel-safe queue

  • Return FLT_POSTOP_MORE_PROCESSING_REQUIRED from the post operation

  • Once the restore completes, remove the reparse point from the file

  • Have the minifilter remove the CallbackData from the queue, re-issue the IRP using FltReissueSynchronousIo (only works for synchronous IO, obviously) and call FltCompletePendedPostOperation() on the CallbackData

So that would be the basic structure of an HSM type driver. I would review more information on reparse points, cancel-safe queues and kernel worker items that can help you along the way. Hopefully this thread can server as a basic guide for anyone undertaking such endeavors.

Enjoy,
Bill

Bill,
Thanks again. Those were great pointers.
Payman