Young87

当前位置:首页 >个人收藏

ObpLookupEntryDirectory(Windows内核学习笔记)

PVOID
NTAPI
ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
                        IN PUNICODE_STRING Name,
                        IN ULONG Attributes,
                        IN UCHAR SearchShadow,
                        IN POBP_LOOKUP_CONTEXT Context)
{
    BOOLEAN CaseInsensitive = FALSE;
    POBJECT_HEADER_NAME_INFO HeaderNameInfo;
    POBJECT_HEADER ObjectHeader;
    ULONG HashValue;
    ULONG HashIndex;
    LONG TotalChars;
    WCHAR CurrentChar;
    POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
    POBJECT_DIRECTORY_ENTRY *LookupBucket;
    POBJECT_DIRECTORY_ENTRY CurrentEntry;
    PVOID FoundObject = NULL;
    PWSTR Buffer;
    PAGED_CODE();

    if (!ObpLUIDDeviceMapsEnabled) 
    	SearchShadow = FALSE;

    /*检查输入的两个关键指针是否有效*/
    if (!(Directory) || !(Name)) 
    	goto Quickie;

    /* Get name information */
    TotalChars = Name->Length / sizeof(WCHAR);//按照双字大小,计算对象名的字节数
    Buffer = Name->Buffer;//得Name名称

    /* Set up case-sensitivity */
    if (Attributes & OBJ_CASE_INSENSITIVE)
    	 CaseInsensitive = TRUE;//大小写不敏感

    /*不是一个命名的对象*/
    if (!(Buffer) || !(TotalChars)) 
    	goto Quickie;

    /*计算hash值*/
    for (HashValue = 0; TotalChars; TotalChars--)
    {
        /* Go to the next Character */
        CurrentChar = *Buffer++;

        /* Prepare the Hash */
        HashValue += (HashValue << 1) + (HashValue >> 1);

        /* Create the rest based on the name */
        if (CurrentChar < 'a') HashValue += CurrentChar;
        else if (CurrentChar > 'z') HashValue += RtlUpcaseUnicodeChar(CurrentChar);
        else HashValue += (CurrentChar - ('a'-'A'));
    }

    /*计算hash索引*/
    HashIndex = HashValue % 37;//Hash数组的大小为37

    /*保存Hash值和Hash索引在Context中*/
    Context->HashValue = HashValue;
    Context->HashIndex = (USHORT)HashIndex;

    /*得到当前HashIndex对应在Hash列表中的首地址*/
    AllocatedEntry = &Directory->HashBuckets[HashIndex];
    LookupBucket = AllocatedEntry;

    /* Check if the directory is already locked */
    if (!Context->DirectoryLocked)
    {
        /*申请共享锁*/
        ObpAcquireDirectoryLockShared(Directory, Context);
    }

    /* Start looping */
    while ((CurrentEntry = *AllocatedEntry))
    {
        /*Hash匹配*/
        if (CurrentEntry->HashValue == HashValue)
        {
            /*对象体向对象头的转换*/
            ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentEntry->Object);

            /* Get the name information */
            ASSERT(ObjectHeader->NameInfoOffset != 0);
            HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);

            /*如果名字相同,长度相同*/
            if ((Name->Length == HeaderNameInfo->Name.Length) &&
                (RtlEqualUnicodeString(Name, &HeaderNameInfo->Name, CaseInsensitive)))
            {
                break;//发现目标,对象名相同
            }
        }

        /*否则继续向下遍历*/
        AllocatedEntry = &CurrentEntry->ChainLink;
    }

    /*若CurrentEntry非空,则说明找到了目标对象所在的节点 */
    if (CurrentEntry)
    {
        /*设置当前节点到队列的最前面,为了下次查找效率的提高*/
        if (AllocatedEntry != LookupBucket)
        {
            /* Check if the directory was locked or convert the lock */
            if ((Context->DirectoryLocked) ||
                (ExConvertPushLockSharedToExclusive(&Directory->Lock)))
            {
                /*当前目录项的值修改为当前目录项的下一个,因为当前目录项的内容要被放到最前面去*/
                *AllocatedEntry = CurrentEntry->ChainLink;

                /*连接之前的Hash表 */
                CurrentEntry->ChainLink = *LookupBucket;

                /*构建新的HashEntry*/
                *LookupBucket = CurrentEntry;
            }
        }

        /* 找到目标对象 */
        FoundObject = CurrentEntry->Object;
        goto Quickie;
    }
    else
    {
        /* Check if the directory was locked */
        if (!Context->DirectoryLocked)
        {
            /* Release the lock */
            ObpReleaseDirectoryLock(Directory, Context);
        }

        /* Check if we should scan the shadow directory */
        if ((SearchShadow) && (Directory->DeviceMap))
        {
            /* FIXME: We don't support this yet */
            ASSERT(FALSE);
        }
    }

Quickie:
    /* Check if we inserted an object */
    if (FoundObject)
    {
        /* Get the object name information */
        ObjectHeader = OBJECT_TO_OBJECT_HEADER(FoundObject);
        ObpReferenceNameInfo(ObjectHeader);

        /* Reference the object being looked up */
        ObReferenceObject(FoundObject);

        /* Check if the directory was locked */
        if (!Context->DirectoryLocked)
        {
            /* Release the lock */
            ObpReleaseDirectoryLock(Directory, Context);
        }
    }

    /* Check if we found an object already */
    if (Context->Object)
    {
        /* We already did a lookup, so remove this object's query reference */
        ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object);
        HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
        ObpDereferenceNameInfo(HeaderNameInfo);

        /* Also dereference the object itself */
        ObDereferenceObject(Context->Object);
    }

    /* Return the object we found */
    Context->Object = FoundObject;
    return FoundObject;
}

“You’re never really done for, as long as you’ve got a good story and someone to tell it to.”
参考资料:
《Windows内核情景分析》
《Reactos》

除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog

上一篇: 计算机网络知识框架总结(复习)

下一篇: @程序员,一文让你掌握Python爬虫!

精华推荐