1 /* $Id: object.c,v 1.1 2001/06/12 17:51:51 chorns Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: User object manager
6 * FILE: subsys/win32k/misc/object.c
7 * PROGRAMMERS: David Welch (welch@cwcom.net)
8 * Casper S. Hornstrup (chorns@users.sourceforge.net)
10 * 06-06-2001 CSH Ported kernel object manager
12 #include <ddk/ntddk.h>
13 #include <include/object.h>
20 PUSER_OBJECT_HEADER ObjectHeader
)
22 return (((PUSER_OBJECT_HEADER
)ObjectHeader
) + 1);
25 PUSER_OBJECT_HEADER
BODY_TO_HEADER(
28 return (((PUSER_OBJECT_HEADER
)ObjectBody
) - 1);
33 PUSER_HANDLE_TABLE HandleTable
)
35 // ExAcquireFastMutex(HandleTable->ListLock);
39 ObmpUnlockHandleTable(
40 PUSER_HANDLE_TABLE HandleTable
)
42 // ExReleaseFastMutex(AtomTable->ListLock);
46 ObmpPerformRetentionChecks(
47 PUSER_OBJECT_HEADER ObjectHeader
)
49 if (ObjectHeader
->RefCount
< 0)
51 DbgPrint("ObjectHeader 0x%X has invalid reference count (%d)\n",
52 ObjectHeader
, ObjectHeader
->RefCount
);
55 if (ObjectHeader
->HandleCount
< 0)
57 DbgPrint("Object 0x%X has invalid handle count (%d)\n",
58 ObjectHeader
, ObjectHeader
->HandleCount
);
61 if ((ObjectHeader
->RefCount
== 0) && (ObjectHeader
->HandleCount
== 0))
63 ExFreePool(ObjectHeader
);
68 ObmpGetObjectByHandle(
69 PUSER_HANDLE_TABLE HandleTable
,
72 * FUNCTION: Get the data structure for a handle
74 * HandleTable = Table to search
75 * Handle = Handle to get data structure for
77 * Pointer to the data structure identified by the handle on success,
81 ULONG Count
= ((ULONG
)Handle
/ HANDLE_BLOCK_ENTRIES
);
82 ULONG Index
= (((ULONG
)Handle
) - 1) >> 2;
83 PUSER_HANDLE_BLOCK Block
= NULL
;
87 Current
= HandleTable
->ListHead
.Flink
;
89 for (i
= 0; i
< Count
; i
++)
91 Current
= Current
->Flink
;
92 if (Current
== &(HandleTable
->ListHead
))
98 Block
= CONTAINING_RECORD(Current
, USER_HANDLE_BLOCK
, ListEntry
);
99 return &(Block
->Handles
[Index
% HANDLE_BLOCK_ENTRIES
]);
104 PUSER_HANDLE_TABLE HandleTable
)
106 PLIST_ENTRY CurrentEntry
;
107 PUSER_HANDLE_BLOCK Current
;
111 ObmpLockHandleTable(HandleTable
);
113 CurrentEntry
= HandleTable
->ListHead
.Flink
;
115 while (CurrentEntry
!= &HandleTable
->ListHead
)
117 Current
= CONTAINING_RECORD(CurrentEntry
, USER_HANDLE_BLOCK
, ListEntry
);
119 for (i
= 0; i
< HANDLE_BLOCK_ENTRIES
; i
++)
121 ObjectBody
= Current
->Handles
[i
].ObjectBody
;
123 if (ObjectBody
!= NULL
)
125 PUSER_OBJECT_HEADER ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
127 ObmReferenceObjectByPointer(ObjectBody
, otUnknown
);
128 ObjectHeader
->HandleCount
--;
129 Current
->Handles
[i
].ObjectBody
= NULL
;
131 ObmpUnlockHandleTable(HandleTable
);
133 ObmDereferenceObject(ObjectBody
);
135 ObmpLockHandleTable(HandleTable
);
136 CurrentEntry
= &HandleTable
->ListHead
;
141 CurrentEntry
= CurrentEntry
->Flink
;
144 ObmpUnlockHandleTable(HandleTable
);
148 ObmpDeleteHandleTable(
149 PUSER_HANDLE_TABLE HandleTable
)
151 PUSER_HANDLE_BLOCK Current
;
152 PLIST_ENTRY CurrentEntry
;
154 ObmpCloseAllHandles(HandleTable
);
156 CurrentEntry
= RemoveHeadList(&HandleTable
->ListHead
);
158 while (CurrentEntry
!= &HandleTable
->ListHead
)
160 Current
= CONTAINING_RECORD(CurrentEntry
,
166 CurrentEntry
= RemoveHeadList(&HandleTable
->ListHead
);
172 PUSER_HANDLE_TABLE HandleTable
,
175 PUSER_OBJECT_HEADER ObjectHeader
;
179 ObmpLockHandleTable(HandleTable
);
181 Entry
= ObmpGetObjectByHandle(HandleTable
, Handle
);
184 ObmpUnlockHandleTable(HandleTable
);
188 ObjectBody
= Entry
->ObjectBody
;
190 if (ObjectBody
!= NULL
)
192 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
193 ObjectHeader
->HandleCount
--;
194 ObmReferenceObjectByPointer(ObjectBody
, otUnknown
);
195 Entry
->ObjectBody
= NULL
;
198 ObmpUnlockHandleTable(HandleTable
);
204 ObmpInitializeObject(
205 PUSER_HANDLE_TABLE HandleTable
,
206 PUSER_OBJECT_HEADER ObjectHeader
,
208 USER_OBJECT_TYPE ObjectType
,
211 DWORD Status
= STATUS_SUCCESS
;
213 ObjectHeader
->Type
= ObjectType
;
214 ObjectHeader
->HandleCount
= 0;
215 ObjectHeader
->RefCount
= 1;
216 ObjectHeader
->Size
= ObjectSize
;
220 Status
= ObmCreateHandle(
222 HEADER_TO_BODY(ObjectHeader
),
231 ObmGetReferenceCount(
234 PUSER_OBJECT_HEADER ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
236 return ObjectHeader
->RefCount
;
243 PUSER_OBJECT_HEADER ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
245 return ObjectHeader
->HandleCount
;
252 * FUNCTION: Increments a given object's reference count and performs
255 * ObjectBody = Body of the object
258 PUSER_OBJECT_HEADER ObjectHeader
;
265 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
267 ObjectHeader
->RefCount
++;
269 ObmpPerformRetentionChecks(ObjectHeader
);
273 ObmDereferenceObject(
276 * FUNCTION: Decrements a given object's reference count and performs
279 * ObjectBody = Body of the object
282 PUSER_OBJECT_HEADER ObjectHeader
;
289 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
291 ObjectHeader
->RefCount
--;
293 ObmpPerformRetentionChecks(ObjectHeader
);
297 ObmReferenceObjectByPointer(
299 USER_OBJECT_TYPE ObjectType
)
301 * FUNCTION: Increments the pointer reference count for a given object
303 * ObjectBody = Object's body
304 * ObjectType = Object type
308 PUSER_OBJECT_HEADER ObjectHeader
;
310 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
312 if ((ObjectType
!= otUnknown
) && (ObjectHeader
->Type
!= ObjectType
))
314 return STATUS_INVALID_PARAMETER
;
317 ObjectHeader
->RefCount
++;
319 return STATUS_SUCCESS
;
324 PUSER_HANDLE_TABLE HandleTable
,
326 USER_OBJECT_TYPE ObjectType
,
329 PUSER_OBJECT_HEADER ObjectHeader
;
333 ObjectHeader
= (PUSER_OBJECT_HEADER
)ExAllocatePool(
334 NonPagedPool
, ObjectSize
+ sizeof(USER_OBJECT_HEADER
));
340 ObjectBody
= HEADER_TO_BODY(ObjectHeader
);
342 RtlZeroMemory(ObjectBody
, ObjectSize
);
344 Status
= ObmpInitializeObject(
351 if (!NT_SUCCESS(Status
))
353 ExFreePool(ObjectHeader
);
362 PUSER_HANDLE_TABLE HandleTable
,
364 PHANDLE HandleReturn
)
366 * FUNCTION: Add a handle referencing an object
368 * HandleTable = Table to put handle in
369 * ObjectBody = Object body that the handle should refer to
370 * RETURNS: The created handle
373 PUSER_HANDLE_BLOCK NewBlock
;
378 if (ObjectBody
!= NULL
) {
379 BODY_TO_HEADER(ObjectBody
)->HandleCount
++;
382 ObmpLockHandleTable(HandleTable
);
384 Current
= HandleTable
->ListHead
.Flink
;
386 * Scan through the currently allocated Handle blocks looking for a free
389 while (Current
!= &(HandleTable
->ListHead
))
391 PUSER_HANDLE_BLOCK Block
= CONTAINING_RECORD(
392 Current
, USER_HANDLE_BLOCK
, ListEntry
);
395 for (i
= 0; i
< HANDLE_BLOCK_ENTRIES
; i
++)
397 if (!Block
->Handles
[i
].ObjectBody
)
399 Block
->Handles
[i
].ObjectBody
= ObjectBody
;
400 ObmpUnlockHandleTable(HandleTable
);
401 *HandleReturn
= (HANDLE
)((Handle
+ i
) << 2);
402 return ERROR_SUCCESS
;
406 Handle
= Handle
+ HANDLE_BLOCK_ENTRIES
;
407 Current
= Current
->Flink
;
411 * Add a new Handle block to the end of the list
413 NewBlock
= (PUSER_HANDLE_BLOCK
)ExAllocatePool(
414 NonPagedPool
, sizeof(USER_HANDLE_BLOCK
));
417 *HandleReturn
= (PHANDLE
)NULL
;
418 return STATUS_INSUFFICIENT_RESOURCES
;
421 RtlZeroMemory(NewBlock
, sizeof(USER_HANDLE_BLOCK
));
422 NewBlock
->Handles
[0].ObjectBody
= ObjectBody
;
423 InsertTailList(&HandleTable
->ListHead
, &NewBlock
->ListEntry
);
424 ObmpUnlockHandleTable(HandleTable
);
425 *HandleReturn
= (HANDLE
)(Handle
<< 2);
427 return STATUS_SUCCESS
;
431 ObmReferenceObjectByHandle(
432 PUSER_HANDLE_TABLE HandleTable
,
434 USER_OBJECT_TYPE ObjectType
,
437 * FUNCTION: Increments the reference count for an object and returns a
438 * pointer to its body
440 * HandleTable = Table to search
441 * Handle = Handle for the object
442 * ObjectType = Type of object
443 * Object (OUT) = Points to the object body on return
447 PUSER_OBJECT_HEADER ObjectHeader
;
448 PUSER_HANDLE UserHandle
;
451 ObmpLockHandleTable(HandleTable
);
453 UserHandle
= ObmpGetObjectByHandle(HandleTable
, Handle
);
455 if ((UserHandle
== NULL
) || (UserHandle
->ObjectBody
== NULL
))
457 ObmpUnlockHandleTable(HandleTable
);
458 return STATUS_UNSUCCESSFUL
;
461 ObjectBody
= UserHandle
->ObjectBody
;
462 ObmReferenceObjectByPointer(ObjectBody
, ObjectType
);
464 ObmpUnlockHandleTable(HandleTable
);
466 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
468 if ((ObjectType
!= otUnknown
) && (ObjectHeader
->Type
!= ObjectType
))
470 return STATUS_UNSUCCESSFUL
;
473 *Object
= ObjectBody
;
475 return STATUS_SUCCESS
;
480 PUSER_HANDLE_TABLE HandleTable
,
485 ObjectBody
= ObmpDeleteHandle(HandleTable
, Handle
);
486 if (ObjectBody
== NULL
)
488 return STATUS_UNSUCCESSFUL
;
491 ObmDereferenceObject(ObjectBody
);
493 return STATUS_SUCCESS
;
498 ObmInitializeHandleTable(
499 PUSER_HANDLE_TABLE HandleTable
)
501 InitializeListHead(&HandleTable
->ListHead
);
502 //ExInitializeFastMutex(HandleTable->ListLock);
507 PUSER_HANDLE_TABLE HandleTable
)
509 ObmpDeleteHandleTable(HandleTable
);
513 ObmCreateHandleTable(VOID
)
515 PUSER_HANDLE_TABLE HandleTable
;
517 HandleTable
= (PUSER_HANDLE_TABLE
)ExAllocatePool(
518 NonPagedPool
, sizeof(USER_HANDLE_TABLE
));
524 ObmInitializeHandleTable(HandleTable
);
530 ObmDestroyHandleTable(
531 PUSER_HANDLE_TABLE HandleTable
)
533 ObmFreeHandleTable(HandleTable
);
534 ExFreePool(HandleTable
);