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..