File Name

In sfilter sample code I find this function SfGetFileName which gives
the file names as
\Device\HarddiskVolume1\Filename.Ext from FileObject

1>IS there any DDK routine or any function by using which I can get the
name like
C:\Filename.Ext ?
2> Or how can I manupulate function SfGetFileName to give me name like
C:\Filename.Ext ?

I think manupulating SfGetFileName would not be a good idea as it has
been designed to give the pathname in optimal manner.

Any Ideas will be very helpfull.
regards,
Anurag

SfGetFileName function for your reference



PUNICODE_STRING
SfGetFileName(
IN PFILE_OBJECT FileObject,
IN NTSTATUS CreateStatus,
IN OUT PGET_NAME_CONTROL NameControl
)
/*++
Routine Description:
This routine will try and get the name of the given file object.
This
is guaranteed to always return a printable string (though it may be
NULL).
This will allocate a buffer if it needs to.
Arguments:
FileObject - the file object we want the name for
CreateStatus - status of the create operation
NameControl - control structure used for retrieving the name. It
keeps
track if a buffer was allocated or if we are using the internal
buffer.
Return Value:
Pointer to the unicode string with the name
Code:
GF
Modified date: Functions added by Anurag July 30 2004
–*/
{
POBJECT_NAME_INFORMATION nameInfo;
NTSTATUS status;
ULONG size;
ULONG bufferSize;

DbgPrint(“\nGF:Entered with sfGetFileName:”);

//
// Mark we have not allocated the buffer
//
NameControl->allocatedBuffer = NULL;
//
// Use the small buffer in the structure (that will handle most
cases)
// for the name
//
nameInfo = (POBJECT_NAME_INFORMATION)NameControl->smallBuffer;
bufferSize = sizeof(NameControl->smallBuffer);
//
// If the open succeeded, get the name of the file, if it
// failed, get the name of the device.
//

status = ObQueryNameString(
(NT_SUCCESS( CreateStatus ) ?
(PVOID)FileObject :
(PVOID)FileObject->DeviceObject),
nameInfo,
bufferSize,
&size );
//
// See if the buffer was to small
//
if (status == STATUS_BUFFER_OVERFLOW)
{
//
// The buffer was too small, allocate one big enough
//

DbgPrint(“\nGF:STATUS_BUFFER_OVERFLOW is true”);

bufferSize = size + sizeof(WCHAR);
NameControl->allocatedBuffer = ExAllocatePoolWithTag(
NonPagedPool,
bufferSize,
SFLT_POOL_TAG );
if (NULL == NameControl->allocatedBuffer)
{
//
// Failed allocating a buffer, return an empty string for
the name
//
DbgPrint(“\nGF:Failed allocating a buffer”);

RtlInitEmptyUnicodeString(
(PUNICODE_STRING)&NameControl->smallBuffer,
(PWCHAR)(NameControl->smallBuffer +
sizeof(UNICODE_STRING)),
(USHORT)(sizeof(NameControl->smallBuffer) -
sizeof(UNICODE_STRING)) );

DbgPrint(“\nGF:Done with sfGetFileName: Returning Filename”);

return (PUNICODE_STRING)&NameControl->smallBuffer;
}
//
// Set the allocated buffer and get the name again
//
nameInfo =
(POBJECT_NAME_INFORMATION)NameControl->allocatedBuffer;

status = ObQueryNameString(
FileObject,
nameInfo,
bufferSize,
&size );
}
//
// If we got a name and an error opening the file then we
// just received the device name. Grab the rest of the name
// from the FileObject (note that this can only be done if being
called
// from Create). This only happens if we got an error back from
the
// create.
//

if (NT_SUCCESS( status ) &&
!NT_SUCCESS( CreateStatus ))
{
ULONG newSize;
PCHAR newBuffer;
POBJECT_NAME_INFORMATION newNameInfo;
//
// Calculate the size of the buffer we will need to hold
// the combined names
//

DbgPrint(“\nGF:Calculate the size of the buffer”);

newSize = size + FileObject->FileName.Length;
//
// If there is a related file object add in the length
// of that plus space for a separator
//
if (NULL != FileObject->RelatedFileObject)
{
newSize += FileObject->RelatedFileObject->FileName.Length +
sizeof(WCHAR);
}
//
// See if it will fit in the existing buffer
//
if (newSize > bufferSize)
{
//
// It does not fit, allocate a bigger buffer
//
DbgPrint(“\nGF:It does not fit, allocate a bigger buffer”);

newBuffer = ExAllocatePoolWithTag(
NonPagedPool,
newSize,
SFLT_POOL_TAG );
if (NULL == newBuffer)
{
//
// Failed allocating a buffer, return an empty string
for the name
//
RtlInitEmptyUnicodeString(
(PUNICODE_STRING)&NameControl->smallBuffer,
(PWCHAR)(NameControl->smallBuffer +
sizeof(UNICODE_STRING)),
(USHORT)(sizeof(NameControl->smallBuffer) -
sizeof(UNICODE_STRING)) );

return (PUNICODE_STRING)&NameControl->smallBuffer;
}
//
// Now initialize the new buffer with the information
// from the old buffer.
//
newNameInfo = (POBJECT_NAME_INFORMATION)newBuffer;
RtlInitEmptyUnicodeString(
&newNameInfo->Name,
(PWCHAR)(newBuffer + sizeof(OBJECT_NAME_INFORMATION)),
(USHORT)(newSize - sizeof(OBJECT_NAME_INFORMATION)) );
DbgPrint(“\nGF:Before copy unicode”);

RtlCopyUnicodeString( &newNameInfo->Name,
&nameInfo->Name );
//
// Free the old allocated buffer (if there is one)
// and save off the new allocated buffer address. It
// would be very rare that we should have to free the
// old buffer because device names should always fit
// inside it.
//
if (NULL != NameControl->allocatedBuffer)
{
ExFreePool( NameControl->allocatedBuffer );
}
//
// Readjust our pointers
//
NameControl->allocatedBuffer = newBuffer;
bufferSize = newSize;
nameInfo = newNameInfo;
}
else
{
//
// The MaximumLength was set by ObQueryNameString to
// one char larger then the length. Set it to the
// true size of the buffer (so we can append the names)
//
DbgPrint(“\nGF:Needs Short buffer”);

nameInfo->Name.MaximumLength = (USHORT)(bufferSize -
sizeof(OBJECT_NAME_INFORMATION));
}
//
// If there is a related file object, append that name
// first onto the device object along with a separator
// character
//
if (NULL != FileObject->RelatedFileObject)
{
RtlAppendUnicodeStringToString(
&nameInfo->Name,
&FileObject->RelatedFileObject->FileName );
RtlAppendUnicodeToString( &nameInfo->Name, L"\" );
}
//
// Append the name from the file object
//
DbgPrint(“\nGF:Append the name from the file object”);
RtlAppendUnicodeStringToString(
&nameInfo->Name,
&FileObject->FileName );

ASSERT(nameInfo->Name.Length <= nameInfo->Name.MaximumLength);
}
//
// Return the name
//
DbgPrint(“\nGF:Done with sfGetFileName: Returning Filename”);
return &nameInfo->Name;

}




Hey Anurag,

If your driver is XP or higher, you can use IoVolumeDeviceToDosName to convert the device portion (\Device\DarddiskVolume1) to a drive letter. If you need to support earlier versions of windows, for those targets you would use RtlVolumeDeviceToDosName.

The trick is to know where best to use this. Many people end up BSODing when using it incorrectly at the wrong time. So to short circuit that part of the conversation, here is my recommendation, which I am sure the more experienced gurus may or may not agree with.

Personally when I catch an IRP with a major of IRP_MJ_FILE_SYSTEM_CONTROL and a minor of IRP_MN_MOUNT_VOLUME during a mount request I place the drive letter into my new stored device object extension.

I would add something like this:

#if WINVER >= 0x0501
status = IoVolumeDeviceToDosName( storageStackDeviceObject, &newDevExt->DriveLetter );
#else
status = RtlVolumeDeviceToDosName( storageStackDeviceObject, &newDevExt->DriveLetter );
#endif

You will want to make sure your filter starts up early enough to catch the mount requests for this to be effective. Other than that, this is pretty simple.

Your milage will vary of course.

Good luck.


Regards,
Dana Epp
[Blog: http://silverstr.ufies.org/blog/]

Anurag Sarin wrote:

In sfilter sample code I find this function SfGetFileName which gives
the file names as
\Device\HarddiskVolume1\Filename.Ext from FileObject

1>IS there any DDK routine or any function by using which I can get the
name like
C:\Filename.Ext ?
2> Or how can I manupulate function SfGetFileName to give me name like
C:\Filename.Ext ?

I think manupulating SfGetFileName would not be a good idea as it has
been designed to give the pathname in optimal manner.

Any Ideas will be very helpfull.
regards,
Anurag