ReactOS 对象的结构,创建,使用,删除

 

 

Windows 是一个对象驱动的OS。通过研究RecctOS 研究下对象的结构,创建,管理,删除操作。

1.对象的结构

其实对象就是一块内存,对象的结构有对象头和对象体两部分组成。

1.1对象头的结构:

typedef struct _OBJECT_HEADER

/*

 * PURPOSE: Header for every object managed by the object manager

*/

{

   UNICODE_STRING Name;              // 名字

   LIST_ENTRY Entry;                    // 对象链表

   LONG RefCount;                       // 对象的引用计数

   LONG HandleCount;                    //

   BOOLEAN Permanent;                  // ??

   struct _DIRECTORY_OBJECT* Parent;    

   POBJECT_TYPE ObjectType;            // 对象的类型

  

   /*

    * PURPOSE: Object type

    * NOTE: This overlaps the first member of the object body

    */

   CSHORT Type;

  

   /*

    * PURPOSE: Object size

    * NOTE: This overlaps the second member of the object body

    */

   CSHORT Size;                       对象的大小,包含了对象体

  

  

} OBJECT_HEADER, *POBJECT_HEADER;

 

对象头是通用的,也就是说,所有类型的对象的对象头结构是一致的。那么我们对对象的访问也就可以通用起来。

1.2 对象体的结构
不同的对象的对象体是不同的。

 

 

2. 对象的创建

0.17代码中,是通过ObCreateObject 系统调用实现的。

PVOID STDCALL ObCreateObject(PHANDLE Handle,

                          ACCESS_MASK DesiredAccess,

                          POBJECT_ATTRIBUTES ObjectAttributes,

                          POBJECT_TYPE Type)

{

  

   if (ObjectAttributes != NULL &&

       ObjectAttributes->ObjectName != NULL)

     {

       ObFindObject(ObjectAttributes,

                   &Parent,

                   &RemainingPath,

                   NULL);

     }

   else

     {

       RtlInitUnicodeString (&RemainingPath, NULL);

     }

 

   RtlMapGenericMask(&DesiredAccess,

                   Type->Mapping);

  /*分配对象的内存*/

   Header = (POBJECT_HEADER)ExAllocatePool(NonPagedPool,

                                      OBJECT_ALLOC_SIZE(Type));

   /*初始化对象数据*/

ObInitializeObject(Header,

                          Handle,

                          DesiredAccess,

                          Type,

                           ObjectAttributes);

   if (Header->ObjectType != NULL &&

       Header->ObjectType->Create != NULL)

     {

    /*初始化该类型的对象体*/

       Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),

                                       Parent,

                                       RemainingPath.Buffer,

                                       ObjectAttributes);

      

   RtlFreeUnicodeString( &RemainingPath );

/*返回对象体*/

   return(HEADER_TO_BODY(Header));

}

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

[ObCreateObjcet ----- > ObInitializeObject ]

VOID ObInitializeObject(POBJECT_HEADER ObjectHeader,

                     PHANDLE Handle,

                     ACCESS_MASK DesiredAccess,

                     POBJECT_TYPE Type,

                     POBJECT_ATTRIBUTES ObjectAttributes)

{

  /*初始化对象的头*/

   ObjectHeader->HandleCount = 0;

   ObjectHeader->RefCount = 1;

   ObjectHeader->ObjectType = Type;

   if (ObjectAttributes != NULL &&

       ObjectAttributes->Attributes & OBJ_PERMANENT)

     {

       ObjectHeader->Permanent = TRUE;

     }

   else

     {

       ObjectHeader->Permanent = FALSE;

     }

   RtlInitUnicodeString(&(ObjectHeader->Name),NULL);

 

    /* 在当前进程中创建一个handle指向该对象*/

   if (Handle != NULL)

     {

       ObCreateHandle(PsGetCurrentProcess(),

                     HEADER_TO_BODY(ObjectHeader),

                     DesiredAccess,

                     FALSE,

                     Handle);

     }

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

 

 

 

3. 对象的使用

 /*
  * PURPOSE: Returns the byte offset of a field within a structure
  */

 #define FIELD_OFFSET            (long)( & ((type*)(0) -> field))

/*
 * PURPOSE: Returns the base address structure if the caller knows the
 * address of a field within the structure
 * ARGUMENTS:
 *          Address = address of the field
 *          Type = Type of the whole structure
 *          Field = Name of the field whose address is none
 */

  #define  CONTAINING_RECORD(Address, type , field )   (type*)( (long)Address - FIELE_OFFSET(type, fileld) )

上面是两个非常精致的宏。。。从注释可知:

宏1 是返回一个字段相对于结构体的偏移。。

宏2 是已知一个字段的地址,根据该地址得到结构体的地址 。。

 

NTSTATUS ObCreateHandle(PEPROCESS Process,
   PVOID ObjectBody,
   ACCESS_MASK GrantedAccess,
   BOOLEAN Inherit,
   PHANDLE HandleReturn)
/*
 * FUNCTION: Add a handle referencing an object
 * ARGUMENTS:
 *         obj = Object body that the handle should refer to
 * RETURNS: The created handle
 * NOTE: THe handle is valid only in the context of the current process
 */
{
   LIST_ENTRY* current;
   unsigned int handle=1;
   unsigned int i;
   HANDLE_BLOCK* new_blk = NULL;
   PHANDLE_TABLE HandleTable;
   KIRQL oldlvl;
  
   DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
  
   if (ObjectBody != NULL)
     {
 BODY_TO_HEADER(ObjectBody)->HandleCount++;
     }
  
   HandleTable = &Process->HandleTable;    // 得到进程的句柄表(是一个双向链表 LIST_ENTRY)
   
   KeAcquireSpinLock(&HandleTable->ListLock, &oldlvl);
   current = HandleTable->ListHead.Flink;               // 
   
   /*
    * Scan through the currently allocated handle blocks looking for a free
    * slot
    */
   while (current != (&HandleTable->ListHead))
     {
 HANDLE_BLOCK* blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);        

 DPRINT("Current %x\n",current);

 for (i=0;i<HANDLE_BLOCK_ENTRIES;i++)
   {
      DPRINT("Considering slot %d containing %x\n",i,blk->handles[i]);
      if (blk->handles[i].ObjectBody==NULL)
        {
    blk->handles[i].ObjectBody = ObjectBody;
    blk->handles[i].GrantedAccess = GrantedAccess;
    blk->handles[i].Inherit = Inherit;
    KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
    *HandleReturn = (HANDLE)((handle + i) << 2);
    return(STATUS_SUCCESS);
        }
   }
 
 handle = handle + HANDLE_BLOCK_ENTRIES;
 current = current->Flink;
     }
  
   /*
    * Add a new handle block to the end of the list
    */
   new_blk = (HANDLE_BLOCK *)ExAllocatePool(NonPagedPool,sizeof(HANDLE_BLOCK));
   memset(new_blk,0,sizeof(HANDLE_BLOCK));
   InsertTailList(&(Process->HandleTable.ListHead),
    &new_blk->entry);
   KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
   new_blk->handles[0].ObjectBody = ObjectBody;
   new_blk->handles[0].GrantedAccess = GrantedAccess;
   new_blk->handles[0].Inherit = Inherit;
   *HandleReturn = (HANDLE)(handle << 2);
   return(STATUS_SUCCESS);
}

 

从上面的代码可以看出, 进程的句柄链表是 分块的, 也就是下面的结构

 

      Block 1  --- > block 2 ---- > Block 3------> block4

         |                   |                    |                     |

     handle1           handle4           ....                  ......

     handle2           handle5

     handle3           handle6

并且一个block是一个page..

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2009-07-13 23:16  甜甜嘟嘟  阅读(398)  评论(0编辑  收藏  举报