2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ob/obinit.c
5 * PURPOSE: Handles Object Manager Initialization and Shutdown
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Thomas Weidenmueller (w3seek@reactos.org)
11 /* INCLUDES ******************************************************************/
17 /* GLOBALS *******************************************************************/
19 GENERIC_MAPPING ObpTypeMapping
=
22 STANDARD_RIGHTS_WRITE
,
23 STANDARD_RIGHTS_EXECUTE
,
27 GENERIC_MAPPING ObpDirectoryMapping
=
29 STANDARD_RIGHTS_READ
| DIRECTORY_QUERY
|
31 STANDARD_RIGHTS_WRITE
| DIRECTORY_CREATE_SUBDIRECTORY
|
32 DIRECTORY_CREATE_OBJECT
,
33 STANDARD_RIGHTS_EXECUTE
| DIRECTORY_QUERY
|
38 GENERIC_MAPPING ObpSymbolicLinkMapping
=
40 STANDARD_RIGHTS_READ
| SYMBOLIC_LINK_QUERY
,
41 STANDARD_RIGHTS_WRITE
,
42 STANDARD_RIGHTS_EXECUTE
| SYMBOLIC_LINK_QUERY
,
43 SYMBOLIC_LINK_ALL_ACCESS
46 PDEVICE_MAP ObSystemDeviceMap
= NULL
;
47 ULONG ObpTraceLevel
= 0;
52 PsInitializeQuotaSystem(VOID
);
54 ULONG ObpInitializationPhase
;
56 ULONG ObpObjectSecurityMode
= 0;
57 ULONG ObpProtectionMode
= 0;
59 /* PRIVATE FUNCTIONS *********************************************************/
65 ObpCreateKernelObjectsSD(OUT PSECURITY_DESCRIPTOR
*SecurityDescriptor
)
67 PSECURITY_DESCRIPTOR Sd
= NULL
;
69 ULONG AclSize
, SdSize
;
72 AclSize
= sizeof(ACL
) +
73 sizeof(ACE
) + RtlLengthSid(SeWorldSid
) +
74 sizeof(ACE
) + RtlLengthSid(SeAliasAdminsSid
) +
75 sizeof(ACE
) + RtlLengthSid(SeLocalSystemSid
);
77 SdSize
= sizeof(SECURITY_DESCRIPTOR
) + AclSize
;
79 /* Allocate the SD and ACL */
80 Sd
= ExAllocatePoolWithTag(PagedPool
, SdSize
, TAG_SD
);
83 return STATUS_INSUFFICIENT_RESOURCES
;
86 /* Initialize the SD */
87 Status
= RtlCreateSecurityDescriptor(Sd
,
88 SECURITY_DESCRIPTOR_REVISION
);
89 if (!NT_SUCCESS(Status
))
92 Dacl
= (PACL
)((INT_PTR
)Sd
+ sizeof(SECURITY_DESCRIPTOR
));
94 /* Initialize the DACL */
95 RtlCreateAcl(Dacl
, AclSize
, ACL_REVISION
);
98 RtlAddAccessAllowedAce(Dacl
,
103 RtlAddAccessAllowedAce(Dacl
,
108 RtlAddAccessAllowedAce(Dacl
,
113 /* Attach the DACL to the SD */
114 Status
= RtlSetDaclSecurityDescriptor(Sd
,
118 if (!NT_SUCCESS(Status
))
121 *SecurityDescriptor
= Sd
;
124 if (!NT_SUCCESS(Status
))
127 ExFreePoolWithTag(Sd
, TAG_SD
);
140 PGENERAL_LOOKASIDE CurrentList
= NULL
;
142 /* Now allocate the per-processor lists */
143 for (i
= 0; i
< KeNumberProcessors
; i
++)
145 /* Get the PRCB for this CPU */
146 Prcb
= KiProcessorBlock
[(int)i
];
148 /* Set the OBJECT_CREATE_INFORMATION List */
149 Prcb
->PPLookasideList
[LookasideCreateInfoList
].L
= &ObpCreateInfoLookasideList
;
150 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
151 sizeof(GENERAL_LOOKASIDE
),
156 ExInitializeSystemLookasideList(CurrentList
,
158 sizeof(OBJECT_CREATE_INFORMATION
),
161 &ExSystemLookasideListHead
);
165 /* No list, use the static buffer */
166 CurrentList
= &ObpCreateInfoLookasideList
;
170 Prcb
->PPLookasideList
[LookasideCreateInfoList
].P
= CurrentList
;
172 /* Set the captured UNICODE_STRING Object Name List */
173 Prcb
->PPLookasideList
[LookasideNameBufferList
].L
= &ObpNameBufferLookasideList
;
174 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
175 sizeof(GENERAL_LOOKASIDE
),
180 ExInitializeSystemLookasideList(CurrentList
,
185 &ExSystemLookasideListHead
);
189 /* No list, use the static buffer */
190 CurrentList
= &ObpNameBufferLookasideList
;
194 Prcb
->PPLookasideList
[LookasideNameBufferList
].P
= CurrentList
;
205 OBJECT_ATTRIBUTES ObjectAttributes
;
207 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
208 OBP_LOOKUP_CONTEXT Context
;
210 PKPRCB Prcb
= KeGetCurrentPrcb();
211 PLIST_ENTRY ListHead
, NextEntry
;
212 POBJECT_HEADER Header
;
213 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
214 POBJECT_HEADER_NAME_INFO NameInfo
;
215 PSECURITY_DESCRIPTOR KernelObjectsSD
= NULL
;
218 /* Check if this is actually Phase 1 initialization */
219 if (ObpInitializationPhase
!= 0) goto ObPostPhase0
;
221 /* Initialize the OBJECT_CREATE_INFORMATION List */
222 ExInitializeSystemLookasideList(&ObpCreateInfoLookasideList
,
224 sizeof(OBJECT_CREATE_INFORMATION
),
227 &ExSystemLookasideListHead
);
229 /* Set the captured UNICODE_STRING Object Name List */
230 ExInitializeSystemLookasideList(&ObpNameBufferLookasideList
,
235 &ExSystemLookasideListHead
);
237 /* Temporarily setup both pointers to the shared list */
238 Prcb
->PPLookasideList
[LookasideCreateInfoList
].L
= &ObpCreateInfoLookasideList
;
239 Prcb
->PPLookasideList
[LookasideCreateInfoList
].P
= &ObpCreateInfoLookasideList
;
240 Prcb
->PPLookasideList
[LookasideNameBufferList
].L
= &ObpNameBufferLookasideList
;
241 Prcb
->PPLookasideList
[LookasideNameBufferList
].P
= &ObpNameBufferLookasideList
;
243 /* Initialize the security descriptor cache */
246 /* Initialize the Default Event */
247 KeInitializeEvent(&ObpDefaultObject
, NotificationEvent
, TRUE
);
249 /* Initialize the Dos Device Map mutex */
250 KeInitializeGuardedMutex(&ObpDeviceMapLock
);
252 /* Setup default access for the system process */
253 PsGetCurrentProcess()->GrantedAccess
= PROCESS_ALL_ACCESS
;
254 PsGetCurrentThread()->GrantedAccess
= THREAD_ALL_ACCESS
;
256 /* Setup the Object Reaper */
257 ExInitializeWorkItem(&ObpReaperWorkItem
, ObpReapObject
, NULL
);
259 /* Initialize default Quota block */
260 PsInitializeQuotaSystem();
262 /* Create kernel handle table */
263 PsGetCurrentProcess()->ObjectTable
= ExCreateHandleTable(NULL
);
264 ObpKernelHandleTable
= PsGetCurrentProcess()->ObjectTable
;
266 /* Create the Type Type */
267 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
268 RtlInitUnicodeString(&Name
, L
"Type");
269 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
270 ObjectTypeInitializer
.ValidAccessMask
= OBJECT_TYPE_ALL_ACCESS
;
271 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
272 ObjectTypeInitializer
.MaintainTypeList
= TRUE
;
273 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
274 ObjectTypeInitializer
.GenericMapping
= ObpTypeMapping
;
275 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(OBJECT_TYPE
);
276 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
277 ObjectTypeInitializer
.DeleteProcedure
= ObpDeleteObjectType
;
278 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ObpTypeObjectType
);
280 /* Create the Directory Type */
281 RtlInitUnicodeString(&Name
, L
"Directory");
282 ObjectTypeInitializer
.PoolType
= PagedPool
;
283 ObjectTypeInitializer
.ValidAccessMask
= DIRECTORY_ALL_ACCESS
;
284 ObjectTypeInitializer
.CaseInsensitive
= TRUE
;
285 ObjectTypeInitializer
.MaintainTypeList
= FALSE
;
286 ObjectTypeInitializer
.GenericMapping
= ObpDirectoryMapping
;
287 ObjectTypeInitializer
.DeleteProcedure
= NULL
;
288 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(OBJECT_DIRECTORY
);
289 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ObpDirectoryObjectType
);
290 ObpDirectoryObjectType
->TypeInfo
.ValidAccessMask
&= ~SYNCHRONIZE
;
292 /* Create 'symbolic link' object type */
293 RtlInitUnicodeString(&Name
, L
"SymbolicLink");
294 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(OBJECT_SYMBOLIC_LINK
);
295 ObjectTypeInitializer
.GenericMapping
= ObpSymbolicLinkMapping
;
296 ObjectTypeInitializer
.ValidAccessMask
= SYMBOLIC_LINK_ALL_ACCESS
;
297 ObjectTypeInitializer
.ParseProcedure
= ObpParseSymbolicLink
;
298 ObjectTypeInitializer
.DeleteProcedure
= ObpDeleteSymbolicLink
;
299 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ObpSymbolicLinkObjectType
);
300 ObpSymbolicLinkObjectType
->TypeInfo
.ValidAccessMask
&= ~SYNCHRONIZE
;
302 /* Phase 0 initialization complete */
303 ObpInitializationPhase
++;
308 /* Re-initialize lookaside lists */
311 /* Initialize Object Types directory attributes */
312 RtlInitUnicodeString(&Name
, L
"\\");
313 InitializeObjectAttributes(&ObjectAttributes
,
315 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
317 SePublicDefaultUnrestrictedSd
);
319 /* Create the directory */
320 Status
= NtCreateDirectoryObject(&Handle
,
321 DIRECTORY_ALL_ACCESS
,
323 if (!NT_SUCCESS(Status
)) return FALSE
;
325 /* Get a handle to it */
326 Status
= ObReferenceObjectByHandle(Handle
,
328 ObpDirectoryObjectType
,
330 (PVOID
*)&ObpRootDirectoryObject
,
332 if (!NT_SUCCESS(Status
)) return FALSE
;
334 /* Close the extra handle */
335 Status
= NtClose(Handle
);
336 if (!NT_SUCCESS(Status
)) return FALSE
;
338 /* Create a custom security descriptor for the KernelObjects directory */
339 Status
= ObpCreateKernelObjectsSD(&KernelObjectsSD
);
340 if (!NT_SUCCESS(Status
))
343 /* Initialize the KernelObjects directory attributes */
344 RtlInitUnicodeString(&Name
, L
"\\KernelObjects");
345 InitializeObjectAttributes(&ObjectAttributes
,
347 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
351 /* Create the directory */
352 Status
= NtCreateDirectoryObject(&Handle
,
353 DIRECTORY_ALL_ACCESS
,
355 ExFreePoolWithTag(KernelObjectsSD
, TAG_SD
);
356 if (!NT_SUCCESS(Status
)) return FALSE
;
358 /* Close the extra handle */
359 Status
= NtClose(Handle
);
360 if (!NT_SUCCESS(Status
)) return FALSE
;
362 /* Initialize ObjectTypes directory attributes */
363 RtlInitUnicodeString(&Name
, L
"\\ObjectTypes");
364 InitializeObjectAttributes(&ObjectAttributes
,
366 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
370 /* Create the directory */
371 Status
= NtCreateDirectoryObject(&Handle
,
372 DIRECTORY_ALL_ACCESS
,
374 if (!NT_SUCCESS(Status
)) return FALSE
;
376 /* Get a handle to it */
377 Status
= ObReferenceObjectByHandle(Handle
,
379 ObpDirectoryObjectType
,
381 (PVOID
*)&ObpTypeDirectoryObject
,
383 if (!NT_SUCCESS(Status
)) return FALSE
;
385 /* Close the extra handle */
386 Status
= NtClose(Handle
);
387 if (!NT_SUCCESS(Status
)) return FALSE
;
389 /* Initialize lookup context */
390 ObpInitializeLookupContext(&Context
);
393 ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject
, &Context
);
395 /* Loop the object types */
396 ListHead
= &ObpTypeObjectType
->TypeList
;
397 NextEntry
= ListHead
->Flink
;
398 while (ListHead
!= NextEntry
)
400 /* Get the creator info from the list */
401 CreatorInfo
= CONTAINING_RECORD(NextEntry
,
402 OBJECT_HEADER_CREATOR_INFO
,
405 /* Recover the header and the name header from the creator info */
406 Header
= (POBJECT_HEADER
)(CreatorInfo
+ 1);
407 NameInfo
= OBJECT_HEADER_TO_NAME_INFO(Header
);
409 /* Make sure we have a name, and aren't inserted yet */
410 if ((NameInfo
) && !(NameInfo
->Directory
))
412 /* Do the initial lookup to setup the context */
413 if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject
,
415 OBJ_CASE_INSENSITIVE
,
419 /* Insert this object type */
420 ObpInsertEntryDirectory(ObpTypeDirectoryObject
,
426 /* Move to the next entry */
427 NextEntry
= NextEntry
->Flink
;
430 /* Cleanup after lookup */
431 ObpReleaseLookupContext(&Context
);
433 /* Initialize DOS Devices Directory and related Symbolic Links */
434 Status
= ObpCreateDosDevicesDirectory();
435 if (!NT_SUCCESS(Status
)) return FALSE
;