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