📄 namelookup.c
字号:
returnValue = STATUS_UNSUCCESSFUL;
}
//
// CASE 3: We are opening a file that has a RelatedFileObject.
//
else if (FlagOn( LookupFlags, NLFL_IN_CREATE ) &&
(NULL != FileObject->RelatedFileObject)) {
//
// Must be a relative open. We cannot use ObQueryNameString to get
// the name of the RelatedFileObject because it may result in
// deadlock.
//
PNAME_CONTROL relativeName;
ULONG returnLength;
status = NLAllocateNameControl( &relativeName, LookasideList );
if (!NT_SUCCESS( status )) {
goto NoResources;
}
status = NLPQueryFileSystemForFileName( FileObject->RelatedFileObject,
NLExtHeader->AttachedToDeviceObject,
relativeName );
if (NT_SUCCESS( status ))
{
//
// We were able to get the relative FileoBject's name.
// Build up the file name in the following format:
// [volumeName]\[relativeFileObjectName]\[FileObjectName]
// The VolumeName is already in FileNameControl if we've got one.
//
status = NLCheckAndGrowNameControl( FileNameControl,
FileNameControl->Name.Length +
relativeName->Name.Length );
if (!NT_SUCCESS( status )) {
goto NoResources;
}
RtlAppendUnicodeStringToString( &FileNameControl->Name,
&relativeName->Name );
} else {
//
// The query for the relative FileObject name was
// unsuccessful. Build up the file name in the following format:
// [volumeName]\...\[FileObjectName]
// The volumeName is already in FileNameControl if we've got one.
# define RFOPlaceholder L"...\\"
status = NLCheckAndGrowNameControl( FileNameControl,
FileNameControl->Name.Length +
sizeof( RFOPlaceholder ) );
if (!NT_SUCCESS( status )) {
goto NoResources;
}
RtlAppendUnicodeToString( &FileNameControl->Name,
RFOPlaceholder );
cacheName = FALSE;
}
//
// If there is not a slash and the end of the related file object
// string and there is not a slash at the front of the file object
// string, then add one.
//
if (((FileNameControl->Name.Length < sizeof(WCHAR) ||
(FileNameControl->Name.Buffer[(FileNameControl->Name.Length/sizeof(WCHAR))-1] != L'\\')))
&& ((FileObject->FileName.Length < sizeof(WCHAR)) ||
(FileObject->FileName.Buffer[0] != L'\\')))
{
status = NLCheckAndGrowNameControl( FileNameControl,
FileNameControl->Name.Length +
sizeof(WCHAR) );
if (!NT_SUCCESS( status )) {
goto NoResources;
}
RtlAppendUnicodeToString( &FileNameControl->Name, L"\\" );
}
NLFreeNameControl( relativeName, LookasideList );
//
// At this time, copy over the FileObject->FileName to FileNameControl.
//
status = NLCheckAndGrowNameControl( FileNameControl,
FileNameControl->Name.Length +
FileObject->FileName.Length );
if (!NT_SUCCESS( status )) {
goto NoResources;
}
RtlAppendUnicodeStringToString( &FileNameControl->Name,
&FileObject->FileName );
//
// Continue on to the end of the routine and return
// STATUS_UNSUCCESSFUL since we are not able to return a "usable"
// file name (caller cannot use the file name we return in other
// calls because it is not "valid").
//
returnValue = STATUS_UNSUCCESSFUL;
}
//
// CASE 4: We have a open on a file with an absolute path.
//
else if (FlagOn( LookupFlags, NLFL_IN_CREATE ) &&
(FileObject->RelatedFileObject == NULL) ) {
//
// We have an absolute path, so try to copy that into FileNameControl.
//
status = NLCheckAndGrowNameControl( FileNameControl,
FileNameControl->Name.Length +
FileObject->FileName.Length );
if (!NT_SUCCESS( status )) {
goto NoResources;
}
RtlAppendUnicodeStringToString( &FileNameControl->Name,
&FileObject->FileName );
}
//
// CASE 5: We are retrieving the file name sometime after the
// CREATE operation.
//
else if (!FlagOn( LookupFlags, NLFL_IN_CREATE )) {
PNAME_CONTROL nameInfo;
ULONG returnLength;
status = NLAllocateNameControl( &nameInfo, LookasideList );
if (!NT_SUCCESS( status )) {
goto NoResources;
}
status = NLPQueryFileSystemForFileName( FileObject,
NLExtHeader->AttachedToDeviceObject,
nameInfo );
if (NT_SUCCESS( status )) {
status = NLCheckAndGrowNameControl( FileNameControl,
FileNameControl->Name.Length +
nameInfo->Name.Length );
if (!NT_SUCCESS( status )) {
goto NoResources;
}
RtlAppendUnicodeStringToString( &FileNameControl->Name,
&nameInfo->Name );
} else {
//
// Got an error trying to get the file name from the base file
// system, so fail.
//
count = _snwprintf( nameInfo->Name.Buffer,
nameInfo->BufferSize,
L"[-=Error 0x%x Getting Name=-]",
status );
nameInfo->Name.Length = (USHORT)max( 0, count );
status = NLCheckAndGrowNameControl( FileNameControl,
FileNameControl->Name.Length +
nameInfo->Name.Length );
if (!NT_SUCCESS( status )) {
goto NoResources;
}
RtlAppendUnicodeStringToString( &FileNameControl->Name,
&nameInfo->Name );
cacheName = FALSE;
return STATUS_UNSUCCESSFUL;
}
NLFreeNameControl( nameInfo, LookasideList );
}
//
// When we get here we have a valid name.
// Sometimes when we query a name it has a trailing slash, other times
// it doesn't. To make sure the contexts are correct we are going to
// remove a trailing slash if there is not a ":" just before it.
//
if ((FileNameControl->Name.Length >= (2*sizeof(WCHAR))) &&
(FileNameControl->Name.Buffer[(FileNameControl->Name.Length/sizeof(WCHAR))-1] == L'\\') &&
(FileNameControl->Name.Buffer[(FileNameControl->Name.Length/sizeof(WCHAR))-2] != L':'))
{
FileNameControl->Name.Length -= sizeof(WCHAR);
}
//
// See if we are actually opening the target directory. If so then
// remove the trailing name and slash. Note that we won't remove
// the initial slash (just after the colon).
//
if (FlagOn( LookupFlags, NLFL_OPEN_TARGET_DIR ) &&
(FileNameControl->Name.Length > 0))
{
i = (FileNameControl->Name.Length / sizeof(WCHAR)) - 1;
//
// See if the path ends in a backslash, if so skip over it
// (since the file system did).
//
if ((i > 0) &&
(FileNameControl->Name.Buffer[i] == L'\\') &&
(FileNameControl->Name.Buffer[i-1] != L':')) {
i--;
}
//
// Scan backwards over the last component
//
for ( ; i > 0; i-- ) {
if (FileNameControl->Name.Buffer[i] == L'\\') {
if ((i > 0) && (FileNameControl->Name.Buffer[i-1] == L':')) {
i++;
}
FileNameControl->Name.Length = (USHORT)(i * sizeof(WCHAR));
break;
}
}
}
*CacheName = cacheName;
return returnValue;
NoResources:
*CacheName = FALSE;
FileNameControl->Name.Length = 0;
return status;
}
NTSTATUS
NLPQueryFileSystemForFileName (
IN PFILE_OBJECT FileObject,
IN PDEVICE_OBJECT NextDeviceObject,
OUT PNAME_CONTROL FileName
)
/*++
Routine Description:
This routine rolls an IRP to query the name of the
FileObject parameter from the base file system.
Note: ObQueryNameString CANNOT be used here because it
would cause recursive lookup of the file name for FileObject.
Arguments:
FileObject - the file object for which we want the name.
NextDeviceObject - the device object for the next driver in the
stack. This is where we want to start our request
for the name of FileObject.
FileName - Receives the name. This must be memory that safe to write
to from kernel space.
Return Value:
Returns the status of the operation.
--*/
{
PIRP irp;
PIO_STACK_LOCATION irpSp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;
PFILE_NAME_INFORMATION nameInfo = NULL;
ULONG nameInfoLength;
PAGED_CODE();
try {
//
// We'll start with a small buffer and grow it if needed.
//
nameInfoLength = 256;
nameInfo = ExAllocatePoolWithTag( PagedPool,
nameInfoLength,
NL_POOL_TAG );
if (nameInfo == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
leave;
}
//
// Try getting the name. If the IRP fails, then our buffer is too small.
// We'll grow it and try again (hence the loop). We can get the needed
// buffer size from the FileNameLength field of FILE_NAME_INFORMATION.
//
while (TRUE) {
irp = IoAllocateIrp( NextDeviceObject->StackSize, FALSE );
if (irp == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
leave;
}
//
// Set our current thread as the thread for this
// IRP so that the IO Manager always knows which
// thread to return to if it needs to get back into
// the context of the thread that originated this
// IRP.
//
irp->Tail.Overlay.Thread = PsGetCurrentThread();
//
// Set that this IRP originated from the kernel so that
// the IOManager knows that the buffers do not
// need to be probed.
//
irp->RequestorMode = KernelMode;
//
// Initialize the UserIosb and UserEvent in the
//
ioStatus.Status = STATUS_SUCCESS;
ioStatus.Information = 0;
irp->UserIosb = &ioStatus;
irp->UserEvent = NULL; //already zeroed
//
// Set the IRP_SYNCHRONOUS_API to denote that this
// is a synchronous IO request.
//
irp->Flags = IRP_SYNCHRONOUS_API;
irpSp = IoGetNextIrpStackLocation( irp );
irpSp->MajorFunction = IRP_MJ_QUERY_INFORMATION;
irpSp->FileObject = FileObject;
//
// Setup the parameters for IRP_MJ_QUERY_INFORMATION.
// The buffer we want to be filled in should be placed in
// the system buffer.
//
irp->AssociatedIrp.SystemBuffer = nameInfo;
irpSp->Parameters.QueryFile.Length = nameInfoLength;
irpSp->Parameters.QueryFile.FileInformationClass = FileNameInformation;
//
// Set up the completion routine so that we know when our
// request for the file name is completed. At that time,
// we can free the IRP.
//
KeInitializeEvent( &event, NotificationEvent, FALSE );
IoSetCompletionRoutine( irp,
NLPQueryCompletion,
&event,
TRUE,
TRUE,
TRUE );
status = IoCallDriver( NextDeviceObject, irp );
if (STATUS_PENDING == status) {
(VOID) KeWaitForSingleObject( &event,
Executive,
KernelMode,
FALSE,
NULL );
}
//
// Verify that our completion routine has been called.
//
ASSERT(KeReadStateEvent(&event) ||
!NT_SUCCESS(irp->IoStatus.Status));
//
// If the IRP succeeded, go ahead and copy the name and return.
//
if (NT_SUCCESS( ioStatus.Status )) {
//
// We retrieved a valid name, set into buffer
// Make sure the buffer is big enough to hold the given name
//
status = NLCheckAndGrowNameControl( FileName,
(USHORT)nameInfo->FileNameLength );
if (NT_SUCCESS( status )) {
//
// Copy the name from nameInfo buffer into name control
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -