zoukankan      html  css  js  c++  java
  • 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..

  • 相关阅读:
    HTML/网站一键打包APK工具(html网页打包安卓APP应用)
    四款最好用的html转苹果APP免上架免签名打包在线生成工具
    ios11,弹出层内的input框光标错位
    前端进阶小知识
    html数据交互小知识
    H5特殊情况解决方案
    H5个人不常用但感觉很重要的东西
    H5小知识
    Java SE 8 Programmer复习小结
    JSP页面中onSubmit方法不执行
  • 原文地址:https://www.cnblogs.com/herso/p/1522881.html
Copyright © 2011-2022 走看看