四。目录对象结构(ObpLookupDirectoryEntry、ObpLookupObjectName) (一)
2010年05月11日 星期二 14:31
第一篇在分析ObCreateObjectType函数中出现了ObpLookupDirectoryEntry。 这个函数的作用是查询指定的目录对象中是否包含某对象。 目录对象的数据结构是OBJECT_DIRECTORY typedef struct _OBJECT_DIRECTORY { struct _OBJECT_DIRECTORY_ENTRY *HashBuckets[ NUMBER_HASH_BUCKETS ]; EX_PUSH_LOCK Lock; struct _DEVICE_MAP *DeviceMap; ULONG SessionId; } OBJECT_DIRECTORY, *POBJECT_DIRECTORY; HashBuckets是一个根据哈希数组 哈希值是根据对象的名字计算出来的 typedef struct _OBJECT_DIRECTORY_ENTRY { struct _OBJECT_DIRECTORY_ENTRY *ChainLink; PVOID Object; ULONG HashValue; } OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY; _OBJECT_DIRECTORY_ENTRY.ChainLink 把有相同哈希值的对象串联在一起 +-----------------------+ | OBJECT_DIRECTORY | | HashBuckets[37]+--+ (37个指针, 分别指向37个_OBJECT_DIRECTORY_ENTRY结构) | Lock | | (HashValue相同的_OBJECT_DIRECTORY_ENTRY结构使用ChainLink串联起来) +-----------------------+ | (这里只画出了一个指针) +--------------------------+ V +-----------------------+ +->+-----------------------+ |_OBJECT_DIRECTORY_ENTRY| | |_OBJECT_DIRECTORY_ENTRY| | ChainLink+--+ | ChainLink+->..... | Object| | Object| | HashValue| | HashValue| +-----------------------+ +-----------------------+ 下面开始分析ObpLookupDirectoryEntry函数 PVOID ObpLookupDirectoryEntry ( IN POBJECT_DIRECTORY Directory, //目录对象 IN PUNICODE_STRING Name, //搜索的名字 IN ULONG Attributes, //指定是否区分大小写 IN BOOLEAN SearchShadow, //是否搜索shadow directory OUT POBP_LOOKUP_CONTEXT LookupContext //查询详细信息通过这个结构返回 ) { ...... // 一些参数检测 ...... // 根据名字计算一个哈希值, WcharLength是名字长度, Buffer指向Name->Buffer HashIndex = 0; while (WcharLength--) { Wchar = *Buffer++; HashIndex += (HashIndex << 1) + (HashIndex >> 1); if (Wchar < 'a') { HashIndex += Wchar; } else if (Wchar > 'z') { HashIndex += RtlUpcaseUnicodeChar( ( WCHAR )Wchar ); } else { HashIndex += (Wchar - ('a'-'A')); } } HashValue = HashIndex; HashIndex %= NUMBER_HASH_BUCKETS; LookupContext->HashIndex = ( USHORT )HashIndex; LookupContext->HashValue = HashValue; while (1) { // 获取对应的哈希表项 HeadDirectoryEntry = (POBJECT_DIRECTORY_ENTRY *)&Directory->HashBuckets[ HashIndex ]; LookupBucket = HeadDirectoryEntry; // 这个函数给目录上共享锁, _OBJECT_DIRECTORY.Lock 是共享锁数据结构 if (!LookupContext->DirectoryLocked) { ObpLockDirectoryShared( Directory, LookupContext); } // 遍历 _OBJECT_DIRECTORY_ENTRY.ChainLink 链表 while ((DirectoryEntry = *HeadDirectoryEntry) != NULL ) { if (DirectoryEntry->HashValue == HashValue) { // 比较对象名称 ObjectHeader = OBJECT_TO_OBJECT_HEADER( DirectoryEntry->Object ); NameInfo = OBJECT_HEADER_TO_NAME_INFO_EXISTS( ObjectHeader ); if (RtlEqualUnicodeString( Name, &NameInfo->Name, CaseInSensitive )) { break ; } } HeadDirectoryEntry = &DirectoryEntry->ChainLink; } if (DirectoryEntry) { // 找到了对象所在的DirectoryEntry, 返回对应的OBJECT if (HeadDirectoryEntry != LookupBucket) { if ( LookupContext->DirectoryLocked || ExTryConvertPushLockSharedToExclusive(&Directory->Lock)) { *HeadDirectoryEntry = DirectoryEntry->ChainLink; DirectoryEntry->ChainLink = *LookupBucket; *LookupBucket = DirectoryEntry; } } Object = DirectoryEntry->Object; goto UPDATECONTEXT; } else { // 没有找到对象的DirectoryEntry if (!LookupContext->DirectoryLocked) { ObpUnlockDirectory( Directory, LookupContext ); } if (SearchShadow && Directory->DeviceMap != NULL ) { POBJECT_DIRECTORY NewDirectory; NewDirectory = ObpGetShadowDirectory (Directory); if (NewDirectory != NULL ) { Directory = NewDirectory; continue ; } } goto UPDATECONTEXT; } } UPDATECONTEXT: ..... return Object; } 看过了查找指定目录下是否有指定名称的对象的函数后 再来看看一个功能更强大的函数ObpLookupObjectName 它可以根据路径来查找对象, 路径里还可以包含符号链接等。。。总之很复杂很强大。。。 |