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

📄 namelookup.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 4 页
字号:
/*++

Copyright (c) 1989-1999  Microsoft Corporation

Module Name:

    namelookup.c

Abstract:
    Header file which contains the definitions that may be
    shared with the file spy kernel debugger extensions


Environment:

    Kernel mode

--*/

//
//  Fixes Win2K compatibility regarding lookaside lists.
//

#ifndef _WIN2K_COMPAT_SLIST_USAGE
#define _WIN2K_COMPAT_SLIST_USAGE
#endif

#include <stdio.h>
#include "ntifs.h"
#include "ntdddisk.h"
#include "namelookup.h"

#define NL_POOL_TAG 'tPlN'

#if WINVER == 0x0500

#define RtlInitEmptyUnicodeString(_ucStr,_buf,_bufSize) \
    ((_ucStr)->Buffer = (_buf), \
     (_ucStr)->Length = 0, \
     (_ucStr)->MaximumLength = (USHORT)(_bufSize))


#define ExFreePoolWithTag( a, b ) ExFreePool( (a) )

#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif

#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif

#endif

//
//  The context used to send the task of getting the DOS device name off to
//  a worker thread.
//

typedef struct _NL_DOS_NAME_COMPLETION_CONTEXT {

    WORK_QUEUE_ITEM WorkItem;

    //
    //  The DeviceObject whose name is being retrieved.  We need this in addition
    //  to the other fields so we can make sure it doesn't disappear while
    //  we're retrieving the name.
    //

    PDEVICE_OBJECT DeviceObject;

    //
    //  The name library device extension header of the device object to get
    //  the DOS name of.
    //

    PNL_DEVICE_EXTENSION_HEADER NLExtHeader;

} NL_DOS_NAME_COMPLETION_CONTEXT, *PNL_DOS_NAME_COMPLETION_CONTEXT;


//
//  Function prototypes
//


NTSTATUS
NLPQueryFileSystemForFileName (
    IN PFILE_OBJECT FileObject,
    IN PDEVICE_OBJECT NextDeviceObject,
    OUT PNAME_CONTROL FileName
    );

NTSTATUS
NLPQueryCompletion (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PKEVENT SynchronizingEvent
    );

VOID
NLPGetDosDeviceNameWorker (
    IN PNL_DOS_NAME_COMPLETION_CONTEXT Context
    );

#pragma alloc_text(PAGE, NLPQueryFileSystemForFileName)
#pragma alloc_text(PAGE, NLInitNameControl)
#pragma alloc_text(PAGE, NLCleanupNameControl)
#pragma alloc_text(PAGE, NLGetAndAllocateObjectName)
#pragma alloc_text(PAGE, NLGetObjectName)
#pragma alloc_text(PAGE, NLGetDosDeviceName)
#pragma alloc_text(PAGE, NLPGetDosDeviceNameWorker)
#pragma alloc_text(PAGE, NLAllocateAndCopyUnicodeString)
#pragma alloc_text(PAGE, NLAllocateNameControl)
#pragma alloc_text(PAGE, NLInitNameControl)
#pragma alloc_text(PAGE, NLCleanupNameControl)
#pragma alloc_text(PAGE, NLReallocNameControl)
#pragma alloc_text(PAGE, NLCheckAndGrowNameControl)

/////////////////////////////////////////////////////////////////////////////
//
//  Name lookup functions.
//
/////////////////////////////////////////////////////////////////////////////

NTSTATUS
NLGetFullPathName (
    IN PFILE_OBJECT FileObject,
    IN OUT PNAME_CONTROL FileNameControl,
    IN PNL_DEVICE_EXTENSION_HEADER NLExtHeader,
    IN NAME_LOOKUP_FLAGS LookupFlags,
    IN PPAGED_LOOKASIDE_LIST LookasideList,
    OUT PBOOLEAN CacheName
    )
/*++

Routine Description:

    This routine retrieves the full pathname of the FileObject.  Note that
    the buffers containing pathname components may be stored in paged pool,
    therefore if we are at DISPATCH_LEVEL we cannot look up the name.

    The file is looked up one of the following ways based on the LookupFlags:
    1.  FlagOn( FileObject->Flags, FO_VOLUME_OPEN ) or
        (FileObject->FileName.Length == 0).  This is a volume open, so just use
        DeviceName from the NLExtHeader for the FileName, if it exists.
    2.  NAMELOOKUPFL_IN_CREATE and NAMELOOKUPFL_OPEN_BY_ID are set.
        This is an open by file id, so format the file id into the FileName
        string if there is enough room.
    3.  NAMELOOKUPFL_IN_CREATE set and FileObject->RelatedFileObject != NULL.
        This is a relative open, therefore the fullpath file name must
        be built up from the name of the FileObject->RelatedFileObject
        and FileObject->FileName.
    4.  NAMELOOKUPFL_IN_CREATE and FileObject->RelatedFileObject == NULL.
        This is an absolute open, therefore the fullpath file name is
        found in FileObject->FileName.
    5.  No LookupFlags set.
        This is a lookup sometime after CREATE.  FileObject->FileName is
        no longer guaranteed to be valid, so we call
        NLPQueryFileSystemForFileName which rolls a IRP_MJ_QUERY_INFORMATION to
        get the file name.

Arguments:

    FileObject - Pointer to the FileObject to the get name of.

    FileNameControl - A caller-allocated name control that will be filled with
        the filename.  The string will be NULL terminated.

    NLExtHeader - The portion of a device extension needed to build the file
        name.

    LookupFlags - Flags that determine how the name is generated.

    CacheName - TRUE if the returned name should be saved in the cache, FALSE
        if the returned name should NOT be saved in the cache.

Return Value:

    STATUS_INSUFFICIENT_RESOURCES if there was not enough memory to retrieve
    the full name.  If this is the case, FileNameControl->Name.Length will
    be set to 0.  Do not expect any specific value for CacheName.

    STATUS_BUFFER_OVERFLOW if the status buffer to hold the file ID or object ID
        was not large enough.  If this is the case, FileNameControl->Name.Length
        will be set to 0.  Do not expect any specific value for CacheName.

    STATUS_SUCCESS if
        1) The full name was retrieved successfully, OR
        2) At DPC level, full name could not be retrieved, OR
        3) The name was only to be looked up in the cache, OR
        4) Nested operation, full name could not be retrieved, OR

--*/
{
    NTSTATUS status = STATUS_SUCCESS;
    NTSTATUS returnValue = STATUS_SUCCESS;
    ULONG i;
    BOOLEAN cacheName = TRUE;
    LONG count;

    //
    //  Copy over the name the user gave for this device.  These names
    //  should be meaningful to the user.  Note that we do not do this for
    //  NETWORK file system because internally they already show the
    //  connection name.  If this is a direct device open of the network
    //  file system device, we will copy over the device name to be
    //  returned to the user.
    //

    if (FILE_DEVICE_NETWORK_FILE_SYSTEM != NLExtHeader->ThisDeviceObject->DeviceType &&
        FlagOn( LookupFlags, NLFL_USE_DOS_DEVICE_NAME ) &&
        NLExtHeader->DosName.Length != 0) {

        status = NLCheckAndGrowNameControl( FileNameControl,
                                            NLExtHeader->DosName.Length );

        if (!NT_SUCCESS( status )) {

            goto NoResources;
        }

        RtlCopyUnicodeString( &FileNameControl->Name, &NLExtHeader->DosName );

    } else if (FlagOn( FileObject->Flags, FO_DIRECT_DEVICE_OPEN )) {

        status = NLCheckAndGrowNameControl( FileNameControl,
                                            NLExtHeader->DeviceName.Length );

        if (!NT_SUCCESS( status )) {

            goto NoResources;
        }

        RtlCopyUnicodeString( &FileNameControl->Name,
                              &NLExtHeader->DeviceName );

        //
        //  We are now done since there will be no more to the name in this
        //  case, so return TRUE.
        //

        *CacheName = TRUE;
        return STATUS_SUCCESS;

    } else {

        status = NLCheckAndGrowNameControl( FileNameControl,
                                            NLExtHeader->DeviceName.Length );

        if (!NT_SUCCESS( status )) {

            goto NoResources;
        }

        RtlCopyUnicodeString( &FileNameControl->Name,
                              &NLExtHeader->DeviceName );
    }

    //
    //  See if we can request the name
    //

    if (FlagOn( LookupFlags, NLFL_ONLY_CHECK_CACHE )) {
#       define NotInCacheMsg L"[-=Not In Cache=-]"

        status = NLCheckAndGrowNameControl( FileNameControl,
                                            FileNameControl->Name.Length +
                                            sizeof( NotInCacheMsg ) );

        if (!NT_SUCCESS( status )) {

            goto NoResources;
        }

        RtlAppendUnicodeToString( &FileNameControl->Name,
                                  NotInCacheMsg );

        *CacheName = TRUE;
        return STATUS_UNSUCCESSFUL;
    }

    //
    //  Can not get the name at DPC level
    //

    if (KeGetCurrentIrql() > APC_LEVEL) {

#       define AtDPCMsg L"[-=At DPC Level=-]"

        status = NLCheckAndGrowNameControl( FileNameControl,
                                            FileNameControl->Name.Length +
                                            sizeof( AtDPCMsg ) );

        if (!NT_SUCCESS( status )) {

            goto NoResources;
        }

        RtlAppendUnicodeToString( &FileNameControl->Name,
                                  AtDPCMsg );

        *CacheName = FALSE;
        return STATUS_UNSUCCESSFUL;
    }

    //
    //  If there is a ToplevelIrp then this is a nested operation and
    //  there might be other locks held.  Can not get name without the
    //  potential of deadlocking.
    //

    if (IoGetTopLevelIrp() != NULL) {

#       define NestedMsg L"[-=Nested Operation=-]"

        status = NLCheckAndGrowNameControl( FileNameControl,
                                            FileNameControl->Name.Length +
                                            sizeof( NestedMsg ) );

        if (!NT_SUCCESS( status )) {

            goto NoResources;
        }

        RtlAppendUnicodeToString( &FileNameControl->Name,
                                  NestedMsg );
        *CacheName = FALSE;
        return STATUS_UNSUCCESSFUL;
    }

    //
    //  CASE 1:  This FileObject refers to a Volume open.  Either the
    //           flag is set or no filename is specified.
    //

    if (FlagOn( FileObject->Flags, FO_VOLUME_OPEN ) ||
        (FlagOn( LookupFlags, NLFL_IN_CREATE ) &&
         (FileObject->FileName.Length == 0) &&
         (FileObject->RelatedFileObject == NULL))) {

        //
        //  We've already copied the VolumeName so just return.
        //
    }

    //
    //  CASE 2:  We are opening the file by ID.
    //

    else if (FlagOn( LookupFlags, NLFL_IN_CREATE ) &&
             FlagOn( LookupFlags, NLFL_OPEN_BY_ID )) {

#       define OBJECT_ID_KEY_LENGTH 16
#       define ID_BUFFER_SIZE       40

        //
        //  Static buffer big enough for a file Id or object Id.
        //

        WCHAR idName[ID_BUFFER_SIZE];

        if (FileObject->FileName.Length == sizeof(LONGLONG)) {

            //
            //  Opening by FILE ID, generate a name.
            //
            //  To get the actual file name, you could use the file id to open
            //  the file and then get the file name.
            //

            count = _snwprintf( idName,
                                ID_BUFFER_SIZE,
                                L"<%016I64x>",
                                *((PLONGLONG)FileObject->FileName.Buffer) );

            //
            //  If the buffer wasn't big enough for the entire string, fail.
            //

            if (count < 0) {

                FileNameControl->Name.Length = 0;
                return STATUS_BUFFER_OVERFLOW;
            }

        } else if ((FileObject->FileName.Length == OBJECT_ID_KEY_LENGTH) ||
                   (FileObject->FileName.Length == OBJECT_ID_KEY_LENGTH +
                                                                sizeof(WCHAR)))
        {

            PUCHAR idBuffer;

            //
            //  Opening by Object ID, generate a name
            //
            //  To get the actual file name, you could use the file id to open
            //  the file and then get the file name.
            //

            idBuffer = (PUCHAR)&FileObject->FileName.Buffer[0];

            if (FileObject->FileName.Length != OBJECT_ID_KEY_LENGTH) {

                //
                //  Skip win32 backslash at start of buffer
                //

                idBuffer = (PUCHAR)&FileObject->FileName.Buffer[1];
            }

            count = _snwprintf( idName,
                                ID_BUFFER_SIZE,
                                L"<%08x-%04hx-%04hx-%04hx-%04hx%08x>",
                                *(PULONG)&idBuffer[0],
                                *(PUSHORT)&idBuffer[0+4],
                                *(PUSHORT)&idBuffer[0+4+2],
                                *(PUSHORT)&idBuffer[0+4+2+2],
                                *(PUSHORT)&idBuffer[0+4+2+2+2],
                                *(PULONG)&idBuffer[0+4+2+2+2+2] );

            //
            //  If the buffer wasn't big enough for the entire string, fail.
            //

            if (count < 0) {

                FileNameControl->Name.Length = 0;
                return STATUS_BUFFER_OVERFLOW;
            }

        } else {

            //
            //  Unknown ID format.
            //

            count = _snwprintf( idName,
                                ID_BUFFER_SIZE,
                                L"[-=Unknown ID (Len=%u)=-]\n",
                                FileObject->FileName.Length );
        }

        //
        //  Append the idName to FileNameControl.
        //

        status = NLCheckAndGrowNameControl( FileNameControl,
                                            FileNameControl->Name.Length +
                                            ID_BUFFER_SIZE );

        if (!NT_SUCCESS( status )) {

            goto NoResources;
        }

        RtlAppendUnicodeToString( &FileNameControl->Name,
                                  idName );

        //
        //  Don't cache the ID name
        //

        cacheName = FALSE;

        //
        //  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").
        //

⌨️ 快捷键说明

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