[NTOSKRNL]
[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 VOID
50 NTAPI
51 PsInitializeQuotaSystem(VOID);
52
53 ULONG ObpInitializationPhase;
54
55 /* PRIVATE FUNCTIONS *********************************************************/
56
57 BOOLEAN
58 INIT_FUNCTION
59 NTAPI
60 ObInit2(VOID)
61 {
62 CCHAR i;
63 PKPRCB Prcb;
64 PGENERAL_LOOKASIDE CurrentList = NULL;
65
66 /* Now allocate the per-processor lists */
67 for (i = 0; i < KeNumberProcessors; i++)
68 {
69 /* Get the PRCB for this CPU */
70 Prcb = KiProcessorBlock[(int)i];
71
72 /* Set the OBJECT_CREATE_INFORMATION List */
73 Prcb->PPLookasideList[LookasideCreateInfoList].L = &ObpCreateInfoLookasideList;
74 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
75 sizeof(GENERAL_LOOKASIDE),
76 'ICbO');
77 if (CurrentList)
78 {
79 /* Initialize it */
80 ExInitializeSystemLookasideList(CurrentList,
81 NonPagedPool,
82 sizeof(OBJECT_CREATE_INFORMATION),
83 'ICbO',
84 32,
85 &ExSystemLookasideListHead);
86 }
87 else
88 {
89 /* No list, use the static buffer */
90 CurrentList = &ObpCreateInfoLookasideList;
91 }
92
93 /* Link it */
94 Prcb->PPLookasideList[LookasideCreateInfoList].P = CurrentList;
95
96 /* Set the captured UNICODE_STRING Object Name List */
97 Prcb->PPLookasideList[LookasideNameBufferList].L = &ObpNameBufferLookasideList;
98 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
99 sizeof(GENERAL_LOOKASIDE),
100 'MNbO');
101 if (CurrentList)
102 {
103 /* Initialize it */
104 ExInitializeSystemLookasideList(CurrentList,
105 PagedPool,
106 248,
107 'MNbO',
108 16,
109 &ExSystemLookasideListHead);
110 }
111 else
112 {
113 /* No list, use the static buffer */
114 CurrentList = &ObpNameBufferLookasideList;
115 }
116
117 /* Link it */
118 Prcb->PPLookasideList[LookasideNameBufferList].P = CurrentList;
119 }
120
121 return TRUE;
122 }
123
124 BOOLEAN
125 INIT_FUNCTION
126 NTAPI
127 ObInitSystem(VOID)
128 {
129 OBJECT_ATTRIBUTES ObjectAttributes;
130 UNICODE_STRING Name;
131 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
132 OBP_LOOKUP_CONTEXT Context;
133 HANDLE Handle;
134 PKPRCB Prcb = KeGetCurrentPrcb();
135 PLIST_ENTRY ListHead, NextEntry;
136 POBJECT_HEADER Header;
137 POBJECT_HEADER_CREATOR_INFO CreatorInfo;
138 POBJECT_HEADER_NAME_INFO NameInfo;
139 NTSTATUS Status;
140
141 /* Check if this is actually Phase 1 initialization */
142 if (ObpInitializationPhase != 0) goto ObPostPhase0;
143
144 /* Initialize the OBJECT_CREATE_INFORMATION List */
145 ExInitializeSystemLookasideList(&ObpCreateInfoLookasideList,
146 NonPagedPool,
147 sizeof(OBJECT_CREATE_INFORMATION),
148 'ICbO',
149 32,
150 &ExSystemLookasideListHead);
151
152 /* Set the captured UNICODE_STRING Object Name List */
153 ExInitializeSystemLookasideList(&ObpNameBufferLookasideList,
154 PagedPool,
155 248,
156 'MNbO',
157 16,
158 &ExSystemLookasideListHead);
159
160 /* Temporarily setup both pointers to the shared list */
161 Prcb->PPLookasideList[LookasideCreateInfoList].L = &ObpCreateInfoLookasideList;
162 Prcb->PPLookasideList[LookasideCreateInfoList].P = &ObpCreateInfoLookasideList;
163 Prcb->PPLookasideList[LookasideNameBufferList].L = &ObpNameBufferLookasideList;
164 Prcb->PPLookasideList[LookasideNameBufferList].P = &ObpNameBufferLookasideList;
165
166 /* Initialize the security descriptor cache */
167 ObpInitSdCache();
168
169 /* Initialize the Default Event */
170 KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE);
171
172 /* Initialize the Dos Device Map mutex */
173 KeInitializeGuardedMutex(&ObpDeviceMapLock);
174
175 /* Setup default access for the system process */
176 PsGetCurrentProcess()->GrantedAccess = PROCESS_ALL_ACCESS;
177 PsGetCurrentThread()->GrantedAccess = THREAD_ALL_ACCESS;
178
179 /* Setup the Object Reaper */
180 ExInitializeWorkItem(&ObpReaperWorkItem, ObpReapObject, NULL);
181
182 /* Initialize default Quota block */
183 PsInitializeQuotaSystem();
184
185 /* Create kernel handle table */
186 PsGetCurrentProcess()->ObjectTable = ExCreateHandleTable(NULL);
187 ObpKernelHandleTable = PsGetCurrentProcess()->ObjectTable;
188
189 /* Create the Type Type */
190 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
191 RtlInitUnicodeString(&Name, L"Type");
192 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
193 ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS;
194 ObjectTypeInitializer.UseDefaultObject = TRUE;
195 ObjectTypeInitializer.MaintainTypeList = TRUE;
196 ObjectTypeInitializer.PoolType = NonPagedPool;
197 ObjectTypeInitializer.GenericMapping = ObpTypeMapping;
198 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_TYPE);
199 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
200 ObjectTypeInitializer.DeleteProcedure = ObpDeleteObjectType;
201 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObpTypeObjectType);
202
203 /* Create the Directory Type */
204 RtlInitUnicodeString(&Name, L"Directory");
205 ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS;
206 ObjectTypeInitializer.CaseInsensitive = TRUE;
207 ObjectTypeInitializer.MaintainTypeList = FALSE;
208 ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping;
209 ObjectTypeInitializer.DeleteProcedure = NULL;
210 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_DIRECTORY);
211 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObDirectoryType);
212
213 /* Create 'symbolic link' object type */
214 RtlInitUnicodeString(&Name, L"SymbolicLink");
215 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_SYMBOLIC_LINK);
216 ObjectTypeInitializer.GenericMapping = ObpSymbolicLinkMapping;
217 ObjectTypeInitializer.ValidAccessMask = SYMBOLIC_LINK_ALL_ACCESS;
218 ObjectTypeInitializer.ParseProcedure = ObpParseSymbolicLink;
219 ObjectTypeInitializer.DeleteProcedure = ObpDeleteSymbolicLink;
220 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObSymbolicLinkType);
221
222 /* Phase 0 initialization complete */
223 ObpInitializationPhase++;
224 return TRUE;
225
226 ObPostPhase0:
227
228 /* Re-initialize lookaside lists */
229 ObInit2();
230
231 /* Initialize Object Types directory attributes */
232 RtlInitUnicodeString(&Name, L"\\");
233 InitializeObjectAttributes(&ObjectAttributes,
234 &Name,
235 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
236 NULL,
237 SePublicDefaultUnrestrictedSd);
238
239 /* Create the directory */
240 Status = NtCreateDirectoryObject(&Handle,
241 DIRECTORY_ALL_ACCESS,
242 &ObjectAttributes);
243 if (!NT_SUCCESS(Status)) return FALSE;
244
245 /* Get a handle to it */
246 Status = ObReferenceObjectByHandle(Handle,
247 0,
248 ObDirectoryType,
249 KernelMode,
250 (PVOID*)&ObpRootDirectoryObject,
251 NULL);
252 if (!NT_SUCCESS(Status)) return FALSE;
253
254 /* Close the extra handle */
255 Status = NtClose(Handle);
256 if (!NT_SUCCESS(Status)) return FALSE;
257
258 /* Initialize Object Types directory attributes */
259 RtlInitUnicodeString(&Name, L"\\KernelObjects");
260 InitializeObjectAttributes(&ObjectAttributes,
261 &Name,
262 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
263 NULL,
264 NULL);
265
266 /* Create the directory */
267 Status = NtCreateDirectoryObject(&Handle,
268 DIRECTORY_ALL_ACCESS,
269 &ObjectAttributes);
270 if (!NT_SUCCESS(Status)) return FALSE;
271
272 /* Close the extra handle */
273 Status = NtClose(Handle);
274 if (!NT_SUCCESS(Status)) return FALSE;
275
276 /* Initialize Object Types directory attributes */
277 RtlInitUnicodeString(&Name, L"\\ObjectTypes");
278 InitializeObjectAttributes(&ObjectAttributes,
279 &Name,
280 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
281 NULL,
282 NULL);
283
284 /* Create the directory */
285 Status = NtCreateDirectoryObject(&Handle,
286 DIRECTORY_ALL_ACCESS,
287 &ObjectAttributes);
288 if (!NT_SUCCESS(Status)) return FALSE;
289
290 /* Get a handle to it */
291 Status = ObReferenceObjectByHandle(Handle,
292 0,
293 ObDirectoryType,
294 KernelMode,
295 (PVOID*)&ObpTypeDirectoryObject,
296 NULL);
297 if (!NT_SUCCESS(Status)) return FALSE;
298
299 /* Close the extra handle */
300 Status = NtClose(Handle);
301 if (!NT_SUCCESS(Status)) return FALSE;
302
303 /* Initialize lookup context */
304 ObpInitializeLookupContext(&Context);
305
306 /* Lock it */
307 ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context);
308
309 /* Loop the object types */
310 ListHead = &ObpTypeObjectType->TypeList;
311 NextEntry = ListHead->Flink;
312 while (ListHead != NextEntry)
313 {
314 /* Get the creator info from the list */
315 CreatorInfo = CONTAINING_RECORD(NextEntry,
316 OBJECT_HEADER_CREATOR_INFO,
317 TypeList);
318
319 /* Recover the header and the name header from the creator info */
320 Header = (POBJECT_HEADER)(CreatorInfo + 1);
321 NameInfo = OBJECT_HEADER_TO_NAME_INFO(Header);
322
323 /* Make sure we have a name, and aren't inserted yet */
324 if ((NameInfo) && !(NameInfo->Directory))
325 {
326 /* Do the initial lookup to setup the context */
327 if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
328 &NameInfo->Name,
329 OBJ_CASE_INSENSITIVE,
330 FALSE,
331 &Context))
332 {
333 /* Insert this object type */
334 ObpInsertEntryDirectory(ObpTypeDirectoryObject,
335 &Context,
336 Header);
337 }
338 }
339
340 /* Move to the next entry */
341 NextEntry = NextEntry->Flink;
342 }
343
344 /* Cleanup after lookup */
345 ObpReleaseLookupContext(&Context);
346
347 /* Initialize DOS Devices Directory and related Symbolic Links */
348 Status = ObpCreateDosDevicesDirectory();
349 if (!NT_SUCCESS(Status)) return FALSE;
350 return TRUE;
351 }
352
353 /* EOF */