[REACTOS] Cleanup INIT and some PAGE section allocations
[reactos.git] / ntoskrnl / ob / obinit.c
1 /*
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)
7 * Eric Kohl
8 * Thomas Weidenmueller (w3seek@reactos.org)
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16
17 /* GLOBALS *******************************************************************/
18
19 GENERIC_MAPPING ObpTypeMapping =
20 {
21 STANDARD_RIGHTS_READ,
22 STANDARD_RIGHTS_WRITE,
23 STANDARD_RIGHTS_EXECUTE,
24 0x000F0001
25 };
26
27 GENERIC_MAPPING ObpDirectoryMapping =
28 {
29 STANDARD_RIGHTS_READ | DIRECTORY_QUERY |
30 DIRECTORY_TRAVERSE,
31 STANDARD_RIGHTS_WRITE | DIRECTORY_CREATE_SUBDIRECTORY |
32 DIRECTORY_CREATE_OBJECT,
33 STANDARD_RIGHTS_EXECUTE | DIRECTORY_QUERY |
34 DIRECTORY_TRAVERSE,
35 DIRECTORY_ALL_ACCESS
36 };
37
38 GENERIC_MAPPING ObpSymbolicLinkMapping =
39 {
40 STANDARD_RIGHTS_READ | SYMBOLIC_LINK_QUERY,
41 STANDARD_RIGHTS_WRITE,
42 STANDARD_RIGHTS_EXECUTE | SYMBOLIC_LINK_QUERY,
43 SYMBOLIC_LINK_ALL_ACCESS
44 };
45
46 PDEVICE_MAP ObSystemDeviceMap = NULL;
47 ULONG ObpTraceLevel = 0;
48
49 CODE_SEG("INIT")
50 VOID
51 NTAPI
52 PsInitializeQuotaSystem(VOID);
53
54 ULONG ObpInitializationPhase;
55
56 ULONG ObpObjectSecurityMode = 0;
57 ULONG ObpProtectionMode = 0;
58
59 /* PRIVATE FUNCTIONS *********************************************************/
60
61 static
62 CODE_SEG("INIT")
63 NTSTATUS
64 NTAPI
65 ObpCreateKernelObjectsSD(OUT PSECURITY_DESCRIPTOR *SecurityDescriptor)
66 {
67 PSECURITY_DESCRIPTOR Sd = NULL;
68 PACL Dacl;
69 ULONG AclSize, SdSize;
70 NTSTATUS Status;
71
72 AclSize = sizeof(ACL) +
73 sizeof(ACE) + RtlLengthSid(SeWorldSid) +
74 sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid) +
75 sizeof(ACE) + RtlLengthSid(SeLocalSystemSid);
76
77 SdSize = sizeof(SECURITY_DESCRIPTOR) + AclSize;
78
79 /* Allocate the SD and ACL */
80 Sd = ExAllocatePoolWithTag(PagedPool, SdSize, TAG_SD);
81 if (Sd == NULL)
82 {
83 return STATUS_INSUFFICIENT_RESOURCES;
84 }
85
86 /* Initialize the SD */
87 Status = RtlCreateSecurityDescriptor(Sd,
88 SECURITY_DESCRIPTOR_REVISION);
89 if (!NT_SUCCESS(Status))
90 goto done;
91
92 Dacl = (PACL)((INT_PTR)Sd + sizeof(SECURITY_DESCRIPTOR));
93
94 /* Initialize the DACL */
95 RtlCreateAcl(Dacl, AclSize, ACL_REVISION);
96
97 /* Add the ACEs */
98 RtlAddAccessAllowedAce(Dacl,
99 ACL_REVISION,
100 GENERIC_READ,
101 SeWorldSid);
102
103 RtlAddAccessAllowedAce(Dacl,
104 ACL_REVISION,
105 GENERIC_ALL,
106 SeAliasAdminsSid);
107
108 RtlAddAccessAllowedAce(Dacl,
109 ACL_REVISION,
110 GENERIC_ALL,
111 SeLocalSystemSid);
112
113 /* Attach the DACL to the SD */
114 Status = RtlSetDaclSecurityDescriptor(Sd,
115 TRUE,
116 Dacl,
117 FALSE);
118 if (!NT_SUCCESS(Status))
119 goto done;
120
121 *SecurityDescriptor = Sd;
122
123 done:
124 if (!NT_SUCCESS(Status))
125 {
126 if (Sd != NULL)
127 ExFreePoolWithTag(Sd, TAG_SD);
128 }
129
130 return Status;
131 }
132
133 CODE_SEG("INIT")
134 BOOLEAN
135 NTAPI
136 ObInit2(VOID)
137 {
138 CCHAR i;
139 PKPRCB Prcb;
140 PGENERAL_LOOKASIDE CurrentList = NULL;
141
142 /* Now allocate the per-processor lists */
143 for (i = 0; i < KeNumberProcessors; i++)
144 {
145 /* Get the PRCB for this CPU */
146 Prcb = KiProcessorBlock[(int)i];
147
148 /* Set the OBJECT_CREATE_INFORMATION List */
149 Prcb->PPLookasideList[LookasideCreateInfoList].L = &ObpCreateInfoLookasideList;
150 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
151 sizeof(GENERAL_LOOKASIDE),
152 'ICbO');
153 if (CurrentList)
154 {
155 /* Initialize it */
156 ExInitializeSystemLookasideList(CurrentList,
157 NonPagedPool,
158 sizeof(OBJECT_CREATE_INFORMATION),
159 'ICbO',
160 32,
161 &ExSystemLookasideListHead);
162 }
163 else
164 {
165 /* No list, use the static buffer */
166 CurrentList = &ObpCreateInfoLookasideList;
167 }
168
169 /* Link it */
170 Prcb->PPLookasideList[LookasideCreateInfoList].P = CurrentList;
171
172 /* Set the captured UNICODE_STRING Object Name List */
173 Prcb->PPLookasideList[LookasideNameBufferList].L = &ObpNameBufferLookasideList;
174 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
175 sizeof(GENERAL_LOOKASIDE),
176 'MNbO');
177 if (CurrentList)
178 {
179 /* Initialize it */
180 ExInitializeSystemLookasideList(CurrentList,
181 PagedPool,
182 248,
183 'MNbO',
184 16,
185 &ExSystemLookasideListHead);
186 }
187 else
188 {
189 /* No list, use the static buffer */
190 CurrentList = &ObpNameBufferLookasideList;
191 }
192
193 /* Link it */
194 Prcb->PPLookasideList[LookasideNameBufferList].P = CurrentList;
195 }
196
197 return TRUE;
198 }
199
200 CODE_SEG("INIT")
201 BOOLEAN
202 NTAPI
203 ObInitSystem(VOID)
204 {
205 OBJECT_ATTRIBUTES ObjectAttributes;
206 UNICODE_STRING Name;
207 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
208 OBP_LOOKUP_CONTEXT Context;
209 HANDLE Handle;
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;
216 NTSTATUS Status;
217
218 /* Check if this is actually Phase 1 initialization */
219 if (ObpInitializationPhase != 0) goto ObPostPhase0;
220
221 /* Initialize the OBJECT_CREATE_INFORMATION List */
222 ExInitializeSystemLookasideList(&ObpCreateInfoLookasideList,
223 NonPagedPool,
224 sizeof(OBJECT_CREATE_INFORMATION),
225 'ICbO',
226 32,
227 &ExSystemLookasideListHead);
228
229 /* Set the captured UNICODE_STRING Object Name List */
230 ExInitializeSystemLookasideList(&ObpNameBufferLookasideList,
231 PagedPool,
232 248,
233 'MNbO',
234 16,
235 &ExSystemLookasideListHead);
236
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;
242
243 /* Initialize the security descriptor cache */
244 ObpInitSdCache();
245
246 /* Initialize the Default Event */
247 KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE);
248
249 /* Initialize the Dos Device Map mutex */
250 KeInitializeGuardedMutex(&ObpDeviceMapLock);
251
252 /* Setup default access for the system process */
253 PsGetCurrentProcess()->GrantedAccess = PROCESS_ALL_ACCESS;
254 PsGetCurrentThread()->GrantedAccess = THREAD_ALL_ACCESS;
255
256 /* Setup the Object Reaper */
257 ExInitializeWorkItem(&ObpReaperWorkItem, ObpReapObject, NULL);
258
259 /* Initialize default Quota block */
260 PsInitializeQuotaSystem();
261
262 /* Create kernel handle table */
263 PsGetCurrentProcess()->ObjectTable = ExCreateHandleTable(NULL);
264 ObpKernelHandleTable = PsGetCurrentProcess()->ObjectTable;
265
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);
279
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;
291
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;
301
302 /* Phase 0 initialization complete */
303 ObpInitializationPhase++;
304 return TRUE;
305
306 ObPostPhase0:
307
308 /* Re-initialize lookaside lists */
309 ObInit2();
310
311 /* Initialize Object Types directory attributes */
312 RtlInitUnicodeString(&Name, L"\\");
313 InitializeObjectAttributes(&ObjectAttributes,
314 &Name,
315 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
316 NULL,
317 SePublicDefaultUnrestrictedSd);
318
319 /* Create the directory */
320 Status = NtCreateDirectoryObject(&Handle,
321 DIRECTORY_ALL_ACCESS,
322 &ObjectAttributes);
323 if (!NT_SUCCESS(Status)) return FALSE;
324
325 /* Get a handle to it */
326 Status = ObReferenceObjectByHandle(Handle,
327 0,
328 ObpDirectoryObjectType,
329 KernelMode,
330 (PVOID*)&ObpRootDirectoryObject,
331 NULL);
332 if (!NT_SUCCESS(Status)) return FALSE;
333
334 /* Close the extra handle */
335 Status = NtClose(Handle);
336 if (!NT_SUCCESS(Status)) return FALSE;
337
338 /* Create a custom security descriptor for the KernelObjects directory */
339 Status = ObpCreateKernelObjectsSD(&KernelObjectsSD);
340 if (!NT_SUCCESS(Status))
341 return FALSE;
342
343 /* Initialize the KernelObjects directory attributes */
344 RtlInitUnicodeString(&Name, L"\\KernelObjects");
345 InitializeObjectAttributes(&ObjectAttributes,
346 &Name,
347 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
348 NULL,
349 KernelObjectsSD);
350
351 /* Create the directory */
352 Status = NtCreateDirectoryObject(&Handle,
353 DIRECTORY_ALL_ACCESS,
354 &ObjectAttributes);
355 ExFreePoolWithTag(KernelObjectsSD, TAG_SD);
356 if (!NT_SUCCESS(Status)) return FALSE;
357
358 /* Close the extra handle */
359 Status = NtClose(Handle);
360 if (!NT_SUCCESS(Status)) return FALSE;
361
362 /* Initialize ObjectTypes directory attributes */
363 RtlInitUnicodeString(&Name, L"\\ObjectTypes");
364 InitializeObjectAttributes(&ObjectAttributes,
365 &Name,
366 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
367 NULL,
368 NULL);
369
370 /* Create the directory */
371 Status = NtCreateDirectoryObject(&Handle,
372 DIRECTORY_ALL_ACCESS,
373 &ObjectAttributes);
374 if (!NT_SUCCESS(Status)) return FALSE;
375
376 /* Get a handle to it */
377 Status = ObReferenceObjectByHandle(Handle,
378 0,
379 ObpDirectoryObjectType,
380 KernelMode,
381 (PVOID*)&ObpTypeDirectoryObject,
382 NULL);
383 if (!NT_SUCCESS(Status)) return FALSE;
384
385 /* Close the extra handle */
386 Status = NtClose(Handle);
387 if (!NT_SUCCESS(Status)) return FALSE;
388
389 /* Initialize lookup context */
390 ObpInitializeLookupContext(&Context);
391
392 /* Lock it */
393 ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context);
394
395 /* Loop the object types */
396 ListHead = &ObpTypeObjectType->TypeList;
397 NextEntry = ListHead->Flink;
398 while (ListHead != NextEntry)
399 {
400 /* Get the creator info from the list */
401 CreatorInfo = CONTAINING_RECORD(NextEntry,
402 OBJECT_HEADER_CREATOR_INFO,
403 TypeList);
404
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);
408
409 /* Make sure we have a name, and aren't inserted yet */
410 if ((NameInfo) && !(NameInfo->Directory))
411 {
412 /* Do the initial lookup to setup the context */
413 if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
414 &NameInfo->Name,
415 OBJ_CASE_INSENSITIVE,
416 FALSE,
417 &Context))
418 {
419 /* Insert this object type */
420 ObpInsertEntryDirectory(ObpTypeDirectoryObject,
421 &Context,
422 Header);
423 }
424 }
425
426 /* Move to the next entry */
427 NextEntry = NextEntry->Flink;
428 }
429
430 /* Cleanup after lookup */
431 ObpReleaseLookupContext(&Context);
432
433 /* Initialize DOS Devices Directory and related Symbolic Links */
434 Status = ObpCreateDosDevicesDirectory();
435 if (!NT_SUCCESS(Status)) return FALSE;
436 return TRUE;
437 }
438
439 /* EOF */