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

📄 namelookup.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 4 页
字号:
                    RtlCopyMemory( FileName->Name.Buffer,
                                   nameInfo->FileName,
                                   nameInfo->FileNameLength );
                    FileName->Name.Length = (USHORT)nameInfo->FileNameLength;
                }

                leave;

            } else if (ioStatus.Status == STATUS_BUFFER_OVERFLOW) {

                //
                //  Buffer was too small, so grow it and try again.  We need space
                //  in the buffer for the name and the FileNameLength ULONG.
                //

                nameInfoLength = (USHORT)nameInfo->FileNameLength +
                                         sizeof( ULONG );

                ExFreePoolWithTag( nameInfo, NL_POOL_TAG );

                nameInfo = ExAllocatePoolWithTag( PagedPool,
                                                  nameInfoLength,
                                                  NL_POOL_TAG );

                if (nameInfo == NULL) {

                    status = STATUS_INSUFFICIENT_RESOURCES;
                    leave;
                }

            } else {

                //
                //  The query name failed, we are done
                //

                status = ioStatus.Status;
                leave;
            }
        }

    } finally {

        if (nameInfo != NULL) {

            ExFreePoolWithTag( nameInfo, NL_POOL_TAG );
        }
    }

    return status;
}


NTSTATUS
NLPQueryCompletion (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PKEVENT SynchronizingEvent
    )
/*++

Routine Description:

    This routine does the cleanup necessary once the query request completed
    by the file system.

Arguments:

    DeviceObject - This will be NULL since we originated this
        IRP.

    Irp - The IO request structure containing the information
        about the current state of our file name query.

    SynchronizingEvent - The event to signal to notify the
        originator of this request that the operation is
        complete.

Return Value:

    Returns STATUS_MORE_PROCESSING_REQUIRED so that IO Manager
    will not try to free the IRP again.

--*/
{

    UNREFERENCED_PARAMETER( DeviceObject );

    //
    //  Make sure that the IRP status is copied over to the users
    //  IO_STATUS_BLOCK so that the originator of this IRP will know
    //  the final status of this operation.
    //

    ASSERT( NULL != Irp->UserIosb );
    *Irp->UserIosb = Irp->IoStatus;

    //
    //  Signal SynchronizingEvent so that the originator of this
    //  IRP know that the operation is completed.
    //

    KeSetEvent( SynchronizingEvent, IO_NO_INCREMENT, FALSE );

    //
    //  We are now done, so clean up the IRP that we allocated.
    //

    IoFreeIrp( Irp );

    //
    //  If we return STATUS_SUCCESS here, the IO Manager will
    //  perform the cleanup work that it thinks needs to be done
    //  for this IO operation.  This cleanup work includes:
    //  * Copying data from the system buffer to the users buffer
    //    if this was a buffered IO operation.
    //  * Freeing any MDLs that are in the IRP.
    //  * Copying the Irp->IoStatus to Irp->UserIosb so that the
    //    originator of this IRP can see the final status of the
    //    operation.
    //  * If this was an asynchronous request or this was a
    //    synchronous request that got pending somewhere along the
    //    way, the IO Manager will signal the Irp->UserEvent, if one
    //    exists, otherwise it will signal the FileObject->Event.
    //    (This can have REALLY bad implications if the IRP originator
    //     did not an Irp->UserEvent and the IRP originator is not
    //     waiting on the FileObject->Event.  It would not be that
    //     farfetched to believe that someone else in the system is
    //     waiting on FileObject->Event and who knows who will be
    //     awoken as a result of the IO Manager signaling this event.
    //
    //  Since some of these operations require the originating thread's
    //  context (e.g., the IO Manager need the UserBuffer address to
    //  be valid when copy is done), the IO Manager queues this work
    //  to an APC on the IRPs originating thread.
    //
    //  We can do this cleanup work more efficiently than the IO Manager
    //  since we are handling a very specific case.  Therefore, it is better
    //  for us to perform the cleanup work here then free the IRP than passing
    //  control back to the IO Manager to do this work.
    //
    //  By returning STATUS_MORE_PROCESS_REQUIRED, we tell the IO Manager
    //  to stop processing this IRP until it is told to restart processing
    //  with a call to IoCompleteRequest.  Since the IO Manager has
    //  already performed all the work we want it to do on this
    //  IRP, we do the cleanup work, return STATUS_MORE_PROCESSING_REQUIRED,
    //  and ask the IO Manager to resume processing by calling
    //  IoCompleteRequest.
    //

    return STATUS_MORE_PROCESSING_REQUIRED;
}


PNAME_CONTROL
NLGetAndAllocateObjectName (
    IN PVOID Object,
    IN PPAGED_LOOKASIDE_LIST LookasideList
    )
/*++

Routine description:

    This routine will allocate the name control and retrieve the name of
    the device object or driver object.  If we can not get either a NULL
    entry is returned.

Arguments:

    DeviceObject - The object to get the name for

    ObjectName - The lookaside list to allocate from

Return Value:

    Returns: NAME_CONTROL if we got the name.  The caller must free the
             name control when they are done.
             Else NULL if no name could be retrieved.

--*/
{
    NTSTATUS status;
    PNAME_CONTROL objName;

    //
    //  Allocate name control
    //

    status = NLAllocateNameControl( &objName, LookasideList );

    if (NT_SUCCESS( status )) {

        //
        //  Retrieve the name.  Note that we don't test for an error because
        //  we want to use whatever name is returned.
        //

        status = NLGetObjectName( Object, objName );

    } else {

        //
        //  On a failure NLAllocateNameControl returns the buffer NULL'd,
        //  verify this
        //

        ASSERT(objName == NULL);
    }

    return objName;
}


NTSTATUS
NLGetObjectName (
    IN PVOID Object,
    IN OUT PNAME_CONTROL ObjectName
    )
/*++

Routine description:

    This routine reads the name from Object and copies it into the
    given name control structure.  The memory for ObjectName's buffer should
    be allocated by the caller.  We can use ObQueryNameString here because
    Object is a device object or a driver object.

Arguments:

    Object - Supplies the object being queried

    ObjectName - The name control structure to store Object's name.  Will
        grow if needed to hold the object name.

Return Value:

    Returns STATUS_SUCCESS if the name could be retrieved and successfully
        copied into ObjectName.

     Returns STATUS_INSUFFICIENT_RESOURCES if memory cannot be allocated to
        store the name.

--*/
{
    NTSTATUS status;
    POBJECT_NAME_INFORMATION nameInfo;
    ULONG lengthReturned = 0;

    PAGED_CODE();

    ASSERT( ARGUMENT_PRESENT( ObjectName ) );

    //
    //  We just use the buffer in the name control to hold the
    //  OBJECT_NAME_INFORMATION structure plus name buffer.  That
    //  way we don't have to do a separate allocation.
    //

    nameInfo = (POBJECT_NAME_INFORMATION) ObjectName->Name.Buffer;

    //
    //  Query the object manager to get the name
    //

    status = ObQueryNameString( Object,
                                nameInfo,
                                ObjectName->Name.MaximumLength,
                                &lengthReturned );

    //
    //  If we get back a status saying the buffer is too small,
    //  we can try to reallocate a node with the number of bytes needed
    //

    if (status == STATUS_INFO_LENGTH_MISMATCH) {

        status = NLReallocNameControl( ObjectName,
                                       lengthReturned,
                                       NULL );

        if (!NT_SUCCESS( status )) {

            //
            //  If we cannot successfully reallocate a node, we are probably
            //  out of memory. In this case we will just set the string to NULL
            //  and return the error
            //

            ObjectName->Name.Length = 0;
            return status;
        }

        nameInfo = (POBJECT_NAME_INFORMATION) ObjectName->Name.Buffer;

        status = ObQueryNameString( Object,
                                    nameInfo,
                                    ObjectName->Name.MaximumLength,
                                    &lengthReturned );

    }

    //
    //  At this point we should only be getting back errors other than
    //  buffer not large enough (that should have been handled above)
    //

    if (!NT_SUCCESS( status )) {

        int count = _snwprintf( ObjectName->Name.Buffer,
                                           ObjectName->Name.MaximumLength,
                                           L"[-=Error 0x%x Getting Name=-]",
                                           status );
        //
        //  We should never really get a negative count back because
        //  Name Control structures allocate a buffer of size 254 or greater
        //  Our error status should never cause us to have string > 254...
        //

        ObjectName->Name.Length = (USHORT)max( 0, count );

        return status;
    }

    //
    //  We got the name, so now just need to shuffle everything into place.
    //

    ObjectName->Name.Length = nameInfo->Name.Length;

    RtlMoveMemory( ObjectName->Name.Buffer,
                   nameInfo->Name.Buffer,
                   ObjectName->Name.Length );

    return status;
}


VOID
NLGetDosDeviceName (
    IN PDEVICE_OBJECT DeviceObject,
    IN PNL_DEVICE_EXTENSION_HEADER NLExtHeader
    )
/*++

Routine Description:

    This routine gets the DOS device name of DeviceObject.  It uses a worker
    thread due to the threat of deadlock (see inline comments).

    NOTE: This routine will allocate (on success) the DosName buffer in
          NLExtHeader.  Call NLCleanupDeviceExtensionHeader when you tear down
          your device extension to make sure this is freed.

Arguments:

    DeviceObject - The object to get the DOS device name of.
    NLExtHeader - The name lookup extension header for DeviceObject.

Return Value:

    None.

--*/

{
    PNL_DOS_NAME_COMPLETION_CONTEXT completionContext;

    PAGED_CODE();

    //
    //  Mount manager could be on the call stack below us holding
    //  a lock.  NLPGetDosDeviceNameWorker will eventually query the mount
    //  manager which will cause a deadlock in this scenario.
    //  So, we need to do this work in a worker thread.
    //

    completionContext = ExAllocatePoolWithTag( NonPagedPool,
                                               sizeof( NL_DOS_NAME_COMPLETION_CONTEXT ),
                                               NL_POOL_TAG );

    if (completionContext == NULL) {

        //
        //  If we cannot allocate our completion context, we will not
        //  get the DOS name.
        //

        NLExtHeader->DosName.Length = 0;

    } else {

        //
        //  Initialize a work item.  CompletionContext keeps track
        //  of the work queue item and the data that we need
        //  to pass to NLPGetDosDeviceNameWorker in the worker thread.
        //

        ExInitializeWorkItem( &completionContext->WorkItem,
                              NLPGetDosDeviceNameWorker,
                              completionContext );

        //
        //  Don't let the DeviceObject get deleted while we get the DOS
        //  device name asynchronously.
        //

        ObReferenceObject( DeviceObject );

        //
        //  Setup the context.
        //

        completionContext->DeviceObject = DeviceObject;
        completionContext->NLExtHeader = NLExtHeader;

        //
        //  Queue the work item so that it will be run in a
        //  worker thread at some point.
        //

        ExQueueWorkItem( &completionContext->WorkItem ,
                         DelayedWorkQueue );
    }
}


VOID
NLPGetDosDeviceNameWorker (
    IN PNL_DOS_NAME_COMPLETION_CONTEXT Context
    )
/*++

Routine Description:

    This routine uses RtlVolumeDeviceToDosName to get the DOS device name of a
    device object.  Note that RtlVolumeDeviceToDosName is obsolete, but we use
    it so the code is backwards compatible with Win2K.  If the DOS name cannot
    be retrieved, we set the Length parameter of DosName to 0

Arguments:

    NLExtHeader - The name lookup extension header corresponding with the device
        object to get the name of.

Return Value:

    None

--*/

{
    NTSTATUS status;
    PNL_DEVICE_EXTENSION_HEADER nlExtHeader;

    PAGED_CODE();

    ASSERT( Context != NULL );

    nlExtHeader = Context->NLExtHeader;



    //
    //  Get DOS device name if we have a storage stack device
    //  object to ask for it. The reason we might not have a storage
    //  stack device is if this is a Remote File System.
    //

    if (nlExtHeader->StorageStackDeviceObject == NULL) {

        ObDereferenceObject( Context->DeviceObject );
        ExFreePoolWithTag( Context, NL_POOL_TAG );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -