二。ObpAllocateObject 生成对象

二。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后这两个结构的内存就不用我们释放了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值