二。ObpAllocateObject 生成对象
2010年05月10日 星期一 10:35
上次分析ObCreateObjectType函数中暂时略过了ObpAllocateObject函数。 这个函数的主要工作是生成一个对象实例(包括对象头和对象体) 对象实例在内存中的组织如下图 +-------------------------+ |OBJECT_HEADER_QUOTA_INFO <-----------------+ +-------------------------+ | |OBJECT_HEADER_HANDLE_INFO<---------------+ | +-------------------------+ | | |OBJECT_HEADER_NAME_INFO <-------------+ | | +-------------------------+ | | | |OBJECT_HEADER_CREATOR_INFO | | | +-------------------------+ | | | | OBJECT_HEADER | | | | | Flag | | | | | | | | | | NameInfoOffset +-------------+ | | | HandleInfoOffset +---------------+ | | QuotaInfoOffset +-----------------+ +-------------------------+ | OBJECT_BODY | +-------------------------+ OBJECT_HEADER_QUOTA_INFO、OBJECT_HEADER_HANDLE_INFO、OBJECT_HEADER_NAME_INFO、OBJECT_HEADER_CREATOR_INFO 都是可选头部。 OBJECT_HEADER中的NameInfoOffset、HandleInfoOffset、QuotaInfoOffset是相应结构距OBJECT_HEADER的偏移。 OBJECT_HEADER的地址减去相应偏移就可以找到对应结构体。 若偏移为0则说明对应结构不存在。 HEADER中并没有OBJECT_HEADER_CREATOR_INFO的偏移, 因为它如果存在一定是紧挨着OBJECT_HEADER之上的。 OBJECT->Flag域中如果OB_FLAG_CREATOR_INFO被置位, 说明存在这个结构。 NTSTATUS ObpAllocateObject ( IN POBJECT_CREATE_INFORMATION ObjectCreateInfo, //在ObCreateObjectType中它为NULL IN KPROCESSOR_MODE OwnershipMode, //对象属于UserMode还是KernelMode IN POBJECT_TYPE ObjectType OPTIONAL, //对象类型 IN PUNICODE_STRING ObjectName, //对象名 IN ULONG ObjectBodySize, //对象体大小 OUT POBJECT_HEADER *ReturnedObjectHeader //用来接收创建好的对象(头部) ) { ...... // 根据ObjectCreateInfo参数计算可选头部的大小, 挺麻烦先暂时略过 ...... ...... // 计算对象头总大小, 包括了可选头部 // QuotaInfoSize、HandleInfoSize、NameInfoSize、CreatorInfoSize都是根据ObjectCreateInfo计算出来的 HeaderSize = QuotaInfoSize + HandleInfoSize + NameInfoSize + CreatorInfoSize + FIELD_OFFSET( OBJECT_HEADER, Body ); // 根据传入的ObjectType绝对对象是否分配在分页内存中, 并分别对象体 + 对象头。 // ObjectHeader是分配的内存起点 if ((ObjectType == NULL) || (ObjectType->TypeInfo.PoolType == NonPagedPool)) { PoolType = NonPagedPool; } else { PoolType = PagedPool; } ObjectHeader = ExAllocatePoolWithTag( PoolType, HeaderSize + ObjectBodySize, (ObjectType == NULL ? 'TjbO' : ObjectType->Key) | PROTECTED_POOL ); if (ObjectHeader == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } // 从这里开始, 初始化4个可选头部 if (QuotaInfoSize != 0) { // 初始化OBJECT_HEADER_QUOTA_INFO可选头 // 这个结构和内存配额有关 // 这个域默认不存在 } if (HandleInfoSize != 0) { // 初始化OBJECT_HEADER_HANDLE_INFO可选头 // 这个域默认不存在 } // OBJECT_HEADER_NAME_INFO, 这个域是默认存在的, 对象的命名就是这里 // 注意这里直接NameInfo->Name = *ObjectName; 并没有分配名字的内存 if (NameInfoSize != 0) { NameInfo = (POBJECT_HEADER_NAME_INFO)ObjectHeader; NameInfo->Name = *ObjectName; NameInfo->Directory = NULL; NameInfo->QueryReferences = 1; if ( (OwnershipMode == KernelMode) && (ObjectCreateInfo != NULL) && (ObjectCreateInfo->Attributes & OBJ_KERNEL_EXCLUSIVE) ) { NameInfo->QueryReferences |= OBP_NAME_KERNEL_PROTECTED; } ObjectHeader = (POBJECT_HEADER)(NameInfo + 1); } // 初始化OBJECT_HEADER_CREATOR_INFO, 这个结构也是默认存在的 // 这个结构包含了创建者的进程ID、TypeList链表把所有和当前对象同类型的对象串联了起来 // 上一篇文章说过的 OBJECT_TYPE.TypeList 是链表头 if (CreatorInfoSize != 0) { CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)ObjectHeader; CreatorInfo->CreatorBackTraceIndex = 0; CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcess()->UniqueProcessId; InitializeListHead( &CreatorInfo->TypeList ); ObjectHeader = (POBJECT_HEADER)(CreatorInfo + 1); } //可选头部初始化完毕, 计算可选头部的偏移量(图上的那3个指针) if (QuotaInfoSize != 0) { ObjectHeader->QuotaInfoOffset = (UCHAR)(QuotaInfoSize + HandleInfoSize + NameInfoSize + CreatorInfoSize); } else { ObjectHeader->QuotaInfoOffset = 0; } if (HandleInfoSize != 0) { ObjectHeader->HandleInfoOffset = (UCHAR)(HandleInfoSize + NameInfoSize + CreatorInfoSize); } else { ObjectHeader->HandleInfoOffset = 0; } if (NameInfoSize != 0) { ObjectHeader->NameInfoOffset = (UCHAR)(NameInfoSize + CreatorInfoSize); } else { ObjectHeader->NameInfoOffset = 0; } // OB_FLAG_NEW_OBJECT代表新创建的对象 // OB_FLAG_CREATOR_INFO说明OBJECT_HEADER_CREATOR_INFO结构存在 // OB_FLAG_SINGLE_HANDLE_ENTRY说明OBJECT_HEADER_HANDLE_INFO (这个我们以后再说) ObjectHeader->Flags = OB_FLAG_NEW_OBJECT; if (CreatorInfoSize != 0) { ObjectHeader->Flags |= OB_FLAG_CREATOR_INFO; } if (HandleInfoSize != 0) { ObjectHeader->Flags |= OB_FLAG_SINGLE_HANDLE_ENTRY; } // 初始化指针计数和句柄计数(当这两个计数都为0的时候就会销毁对象, 以后再说), Type指向对象的类型 ObjectHeader->PointerCount = 1; ObjectHeader->HandleCount = 0; ObjectHeader->Type = ObjectType; // 现在开始初始化对象头 OBJECT_HEADER 没有什么可说的 if (OwnershipMode == KernelMode) { ObjectHeader->Flags |= OB_FLAG_KERNEL_OBJECT; } if (ObjectCreateInfo != NULL && ObjectCreateInfo->Attributes & OBJ_PERMANENT ) { ObjectHeader->Flags |= OB_FLAG_PERMANENT_OBJECT; } if ((ObjectCreateInfo != NULL) && (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) { ObjectHeader->Flags |= OB_FLAG_EXCLUSIVE_OBJECT; } ObjectHeader->ObjectCreateInfo = ObjectCreateInfo; ObjectHeader->SecurityDescriptor = NULL; if (ObjectType != NULL) { InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfObjects); if (ObjectType->TotalNumberOfObjects > ObjectType->HighWaterNumberOfObjects) { ObjectType->HighWaterNumberOfObjects = ObjectType->TotalNumberOfObjects; } } // 将OBJECT_HEADER返回 *ReturnedObjectHeader = ObjectHeader; return STATUS_SUCCESS; } 最后再看一下函数开头略过的部分 { // 根据ObjectCreateInfo参数计算可选头部的大小 // NULL也说明生成的对象是一个类型对象 if (ObjectCreateInfo == NULL) { // 如果调用者没有提供ObjectCreateInfo参数, 使用默认配置 // 默认有OBJECT_HEADER_NAME_INFO、OBJECT_HEADER_NAME_INFO可选头部 QuotaInfoSize = 0; HandleInfoSize = 0; NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO ); CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO ); } else { // 当指定的配额和类型默认的配额不同 并且 不是系统初始化进程时, 需要OBJECT_HEADER_QUOTA_INFO头部 if (((ObjectCreateInfo->PagedPoolCharge != ObjectType->TypeInfo.DefaultPagedPoolCharge || ObjectCreateInfo->NonPagedPoolCharge != ObjectType->TypeInfo.DefaultNonPagedPoolCharge || ObjectCreateInfo->SecurityDescriptorCharge > SE_DEFAULT_SECURITY_QUOTA) && PsGetCurrentProcess() != PsInitialSystemProcess) || (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) { QuotaInfoSize = sizeof( OBJECT_HEADER_QUOTA_INFO ); } else { QuotaInfoSize = 0; } // 对象的类型决定了是否需要OBJECT_HEADER_HANDLE_INFO结构 if (ObjectType->TypeInfo.MaintainHandleCount) { HandleInfoSize = sizeof( OBJECT_HEADER_HANDLE_INFO ); } else { HandleInfoSize = 0; } // 如果用户需要给对象命名, 则要有OBJECT_HEADER_NAME_INFO结构 if (ObjectName->Buffer != NULL) { NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO ); } else { NameInfoSize = 0; } // 对象类型中的 MaintainTypeList 域决定是否要维护一个对象的链表 if (ObjectType->TypeInfo.MaintainTypeList) { CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO ); } else { CreatorInfoSize = 0; } } } 有两点需要注意 1。 ObpAllocateObject具体会如何创建对象是根据ObjectCreateInfo参数控制的。 2。 函数中的一些域包含了ObjectCreateInfo和ObjectName.Buffer的指针。因此调用ObpAllocateObject后这两个结构的内存就不用我们释放了。 |