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;
51 PsInitializeQuotaSystem(VOID
);
53 ULONG ObpInitializationPhase
;
55 /* PRIVATE FUNCTIONS *********************************************************/
61 ObpCreateKernelObjectsSD(OUT PSECURITY_DESCRIPTOR
*SecurityDescriptor
)
63 PSECURITY_DESCRIPTOR Sd
= NULL
;
65 ULONG AclSize
, SdSize
;
68 AclSize
= sizeof(ACL
) +
69 sizeof(ACE
) + RtlLengthSid(SeWorldSid
) +
70 sizeof(ACE
) + RtlLengthSid(SeAliasAdminsSid
) +
71 sizeof(ACE
) + RtlLengthSid(SeLocalSystemSid
);
73 SdSize
= sizeof(SECURITY_DESCRIPTOR
) + AclSize
;
75 /* Allocate the SD and ACL */
76 Sd
= ExAllocatePoolWithTag(PagedPool
, SdSize
, TAG_SD
);
79 return STATUS_INSUFFICIENT_RESOURCES
;
82 /* Initialize the SD */
83 Status
= RtlCreateSecurityDescriptor(Sd
,
84 SECURITY_DESCRIPTOR_REVISION
);
85 if (!NT_SUCCESS(Status
))
88 Dacl
= (PACL
)((INT_PTR
)Sd
+ sizeof(SECURITY_DESCRIPTOR
));
90 /* Initialize the DACL */
91 RtlCreateAcl(Dacl
, AclSize
, ACL_REVISION
);
94 RtlAddAccessAllowedAce(Dacl
,
99 RtlAddAccessAllowedAce(Dacl
,
104 RtlAddAccessAllowedAce(Dacl
,
109 /* Attach the DACL to the SD */
110 Status
= RtlSetDaclSecurityDescriptor(Sd
,
114 if (!NT_SUCCESS(Status
))
117 *SecurityDescriptor
= Sd
;
120 if (!NT_SUCCESS(Status
))
123 ExFreePoolWithTag(Sd
, TAG_SD
);
136 PGENERAL_LOOKASIDE CurrentList
= NULL
;
138 /* Now allocate the per-processor lists */
139 for (i
= 0; i
< KeNumberProcessors
; i
++)
141 /* Get the PRCB for this CPU */
142 Prcb
= KiProcessorBlock
[(int)i
];
144 /* Set the OBJECT_CREATE_INFORMATION List */
145 Prcb
->PPLookasideList
[LookasideCreateInfoList
].L
= &ObpCreateInfoLookasideList
;
146 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
147 sizeof(GENERAL_LOOKASIDE
),
152 ExInitializeSystemLookasideList(CurrentList
,
154 sizeof(OBJECT_CREATE_INFORMATION
),
157 &ExSystemLookasideListHead
);
161 /* No list, use the static buffer */
162 CurrentList
= &ObpCreateInfoLookasideList
;
166 Prcb
->PPLookasideList
[LookasideCreateInfoList
].P
= CurrentList
;
168 /* Set the captured UNICODE_STRING Object Name List */
169 Prcb
->PPLookasideList
[LookasideNameBufferList
].L
= &ObpNameBufferLookasideList
;
170 CurrentList
= ExAllocatePoolWithTag(NonPagedPool
,
171 sizeof(GENERAL_LOOKASIDE
),
176 ExInitializeSystemLookasideList(CurrentList
,
181 &ExSystemLookasideListHead
);
185 /* No list, use the static buffer */
186 CurrentList
= &ObpNameBufferLookasideList
;
190 Prcb
->PPLookasideList
[LookasideNameBufferList
].P
= CurrentList
;
201 OBJECT_ATTRIBUTES ObjectAttributes
;
203 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
204 OBP_LOOKUP_CONTEXT Context
;
206 PKPRCB Prcb
= KeGetCurrentPrcb();
207 PLIST_ENTRY ListHead
, NextEntry
;
208 POBJECT_HEADER Header
;
209 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
210 POBJECT_HEADER_NAME_INFO NameInfo
;
211 PSECURITY_DESCRIPTOR KernelObjectsSD
= NULL
;
214 /* Check if this is actually Phase 1 initialization */
215 if (ObpInitializationPhase
!= 0) goto ObPostPhase0
;
217 /* Initialize the OBJECT_CREATE_INFORMATION List */
218 ExInitializeSystemLookasideList(&ObpCreateInfoLookasideList
,
220 sizeof(OBJECT_CREATE_INFORMATION
),
223 &ExSystemLookasideListHead
);
225 /* Set the captured UNICODE_STRING Object Name List */
226 ExInitializeSystemLookasideList(&ObpNameBufferLookasideList
,
231 &ExSystemLookasideListHead
);
233 /* Temporarily setup both pointers to the shared list */
234 Prcb
->PPLookasideList
[LookasideCreateInfoList
].L
= &ObpCreateInfoLookasideList
;
235 Prcb
->PPLookasideList
[LookasideCreateInfoList
].P
= &ObpCreateInfoLookasideList
;
236 Prcb
->PPLookasideList
[LookasideNameBufferList
].L
= &ObpNameBufferLookasideList
;
237 Prcb
->PPLookasideList
[LookasideNameBufferList
].P
= &ObpNameBufferLookasideList
;
239 /* Initialize the security descriptor cache */
242 /* Initialize the Default Event */
243 KeInitializeEvent(&ObpDefaultObject
, NotificationEvent
, TRUE
);
245 /* Initialize the Dos Device Map mutex */
246 KeInitializeGuardedMutex(&ObpDeviceMapLock
);
248 /* Setup default access for the system process */
249 PsGetCurrentProcess()->GrantedAccess
= PROCESS_ALL_ACCESS
;
250 PsGetCurrentThread()->GrantedAccess
= THREAD_ALL_ACCESS
;
252 /* Setup the Object Reaper */
253 ExInitializeWorkItem(&ObpReaperWorkItem
, ObpReapObject
, NULL
);
255 /* Initialize default Quota block */
256 PsInitializeQuotaSystem();
258 /* Create kernel handle table */
259 PsGetCurrentProcess()->ObjectTable
= ExCreateHandleTable(NULL
);
260 ObpKernelHandleTable
= PsGetCurrentProcess()->ObjectTable
;
262 /* Create the Type Type */
263 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
264 RtlInitUnicodeString(&Name
, L
"Type");
265 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
266 ObjectTypeInitializer
.ValidAccessMask
= OBJECT_TYPE_ALL_ACCESS
;
267 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
268 ObjectTypeInitializer
.MaintainTypeList
= TRUE
;
269 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
270 ObjectTypeInitializer
.GenericMapping
= ObpTypeMapping
;
271 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(OBJECT_TYPE
);
272 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
273 ObjectTypeInitializer
.DeleteProcedure
= ObpDeleteObjectType
;
274 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ObpTypeObjectType
);
276 /* Create the Directory Type */
277 RtlInitUnicodeString(&Name
, L
"Directory");
278 ObjectTypeInitializer
.PoolType
= PagedPool
;
279 ObjectTypeInitializer
.ValidAccessMask
= DIRECTORY_ALL_ACCESS
;
280 ObjectTypeInitializer
.CaseInsensitive
= TRUE
;
281 ObjectTypeInitializer
.MaintainTypeList
= FALSE
;
282 ObjectTypeInitializer
.GenericMapping
= ObpDirectoryMapping
;
283 ObjectTypeInitializer
.DeleteProcedure
= NULL
;
284 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(OBJECT_DIRECTORY
);
285 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ObpDirectoryObjectType
);
286 ObpDirectoryObjectType
->TypeInfo
.ValidAccessMask
&= ~SYNCHRONIZE
;
288 /* Create 'symbolic link' object type */
289 RtlInitUnicodeString(&Name
, L
"SymbolicLink");
290 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(OBJECT_SYMBOLIC_LINK
);
291 ObjectTypeInitializer
.GenericMapping
= ObpSymbolicLinkMapping
;
292 ObjectTypeInitializer
.ValidAccessMask
= SYMBOLIC_LINK_ALL_ACCESS
;
293 ObjectTypeInitializer
.ParseProcedure
= ObpParseSymbolicLink
;
294 ObjectTypeInitializer
.DeleteProcedure
= ObpDeleteSymbolicLink
;
295 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ObpSymbolicLinkObjectType
);
296 ObpSymbolicLinkObjectType
->TypeInfo
.ValidAccessMask
&= ~SYNCHRONIZE
;
298 /* Phase 0 initialization complete */
299 ObpInitializationPhase
++;
304 /* Re-initialize lookaside lists */
307 /* Initialize Object Types directory attributes */
308 RtlInitUnicodeString(&Name
, L
"\\");
309 InitializeObjectAttributes(&ObjectAttributes
,
311 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
313 SePublicDefaultUnrestrictedSd
);
315 /* Create the directory */
316 Status
= NtCreateDirectoryObject(&Handle
,
317 DIRECTORY_ALL_ACCESS
,
319 if (!NT_SUCCESS(Status
)) return FALSE
;
321 /* Get a handle to it */
322 Status
= ObReferenceObjectByHandle(Handle
,
324 ObpDirectoryObjectType
,
326 (PVOID
*)&ObpRootDirectoryObject
,
328 if (!NT_SUCCESS(Status
)) return FALSE
;
330 /* Close the extra handle */
331 Status
= NtClose(Handle
);
332 if (!NT_SUCCESS(Status
)) return FALSE
;
334 /* Create a custom security descriptor for the KernelObjects directory */
335 Status
= ObpCreateKernelObjectsSD(&KernelObjectsSD
);
336 if (!NT_SUCCESS(Status
))
339 /* Initialize the KernelObjects directory attributes */
340 RtlInitUnicodeString(&Name
, L
"\\KernelObjects");
341 InitializeObjectAttributes(&ObjectAttributes
,
343 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
347 /* Create the directory */
348 Status
= NtCreateDirectoryObject(&Handle
,
349 DIRECTORY_ALL_ACCESS
,
351 ExFreePoolWithTag(KernelObjectsSD
, TAG_SD
);
352 if (!NT_SUCCESS(Status
)) return FALSE
;
354 /* Close the extra handle */
355 Status
= NtClose(Handle
);
356 if (!NT_SUCCESS(Status
)) return FALSE
;
358 /* Initialize ObjectTypes directory attributes */
359 RtlInitUnicodeString(&Name
, L
"\\ObjectTypes");
360 InitializeObjectAttributes(&ObjectAttributes
,
362 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
366 /* Create the directory */
367 Status
= NtCreateDirectoryObject(&Handle
,
368 DIRECTORY_ALL_ACCESS
,
370 if (!NT_SUCCESS(Status
)) return FALSE
;
372 /* Get a handle to it */
373 Status
= ObReferenceObjectByHandle(Handle
,
375 ObpDirectoryObjectType
,
377 (PVOID
*)&ObpTypeDirectoryObject
,
379 if (!NT_SUCCESS(Status
)) return FALSE
;
381 /* Close the extra handle */
382 Status
= NtClose(Handle
);
383 if (!NT_SUCCESS(Status
)) return FALSE
;
385 /* Initialize lookup context */
386 ObpInitializeLookupContext(&Context
);
389 ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject
, &Context
);
391 /* Loop the object types */
392 ListHead
= &ObpTypeObjectType
->TypeList
;
393 NextEntry
= ListHead
->Flink
;
394 while (ListHead
!= NextEntry
)
396 /* Get the creator info from the list */
397 CreatorInfo
= CONTAINING_RECORD(NextEntry
,
398 OBJECT_HEADER_CREATOR_INFO
,
401 /* Recover the header and the name header from the creator info */
402 Header
= (POBJECT_HEADER
)(CreatorInfo
+ 1);
403 NameInfo
= OBJECT_HEADER_TO_NAME_INFO(Header
);
405 /* Make sure we have a name, and aren't inserted yet */
406 if ((NameInfo
) && !(NameInfo
->Directory
))
408 /* Do the initial lookup to setup the context */
409 if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject
,
411 OBJ_CASE_INSENSITIVE
,
415 /* Insert this object type */
416 ObpInsertEntryDirectory(ObpTypeDirectoryObject
,
422 /* Move to the next entry */
423 NextEntry
= NextEntry
->Flink
;
426 /* Cleanup after lookup */
427 ObpReleaseLookupContext(&Context
);
429 /* Initialize DOS Devices Directory and related Symbolic Links */
430 Status
= ObpCreateDosDevicesDirectory();
431 if (!NT_SUCCESS(Status
)) return FALSE
;