⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 namelookup.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 4 页
字号:
        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 + -