二。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后这两个结构的内存就不用我们释放了。
转载请注明原文地址: https://ibbs.8miu.com/read-2270690.html