* Sync up to trunk head (r64959).
[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.PoolType = PagedPool;
206 ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS;
207 ObjectTypeInitializer.CaseInsensitive = TRUE;
208 ObjectTypeInitializer.MaintainTypeList = FALSE;
209 ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping;
210 ObjectTypeInitializer.DeleteProcedure = NULL;
211 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_DIRECTORY);
212 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObDirectoryType);
213 ObDirectoryType->TypeInfo.ValidAccessMask &= ~SYNCHRONIZE;
214
215 /* Create 'symbolic link' object type */
216 RtlInitUnicodeString(&Name, L"SymbolicLink");
217 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_SYMBOLIC_LINK);
218 ObjectTypeInitializer.GenericMapping = ObpSymbolicLinkMapping;
219 ObjectTypeInitializer.ValidAccessMask = SYMBOLIC_LINK_ALL_ACCESS;
220 ObjectTypeInitializer.ParseProcedure = ObpParseSymbolicLink;
221 ObjectTypeInitializer.DeleteProcedure = ObpDeleteSymbolicLink;
222 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObSymbolicLinkType);
223 ObSymbolicLinkType->TypeInfo.ValidAccessMask &= ~SYNCHRONIZE;
224
225 /* Phase 0 initialization complete */
226 ObpInitializationPhase++;
227 return TRUE;
228
229 ObPostPhase0:
230
231 /* Re-initialize lookaside lists */
232 ObInit2();
233
234 /* Initialize Object Types directory attributes */
235 RtlInitUnicodeString(&Name, L"\\");
236 InitializeObjectAttributes(&ObjectAttributes,
237 &Name,
238 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
239 NULL,
240 SePublicDefaultUnrestrictedSd);
241
242 /* Create the directory */
243 Status = NtCreateDirectoryObject(&Handle,
244 DIRECTORY_ALL_ACCESS,
245 &ObjectAttributes);
246 if (!NT_SUCCESS(Status)) return FALSE;
247
248 /* Get a handle to it */
249 Status = ObReferenceObjectByHandle(Handle,
250 0,
251 ObDirectoryType,
252 KernelMode,
253 (PVOID*)&ObpRootDirectoryObject,
254 NULL);
255 if (!NT_SUCCESS(Status)) return FALSE;
256
257 /* Close the extra handle */
258 Status = NtClose(Handle);
259 if (!NT_SUCCESS(Status)) return FALSE;
260
261 /* Initialize Object Types directory attributes */
262 RtlInitUnicodeString(&Name, L"\\KernelObjects");
263 InitializeObjectAttributes(&ObjectAttributes,
264 &Name,
265 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
266 NULL,
267 NULL);
268
269 /* Create the directory */
270 Status = NtCreateDirectoryObject(&Handle,
271 DIRECTORY_ALL_ACCESS,
272 &ObjectAttributes);
273 if (!NT_SUCCESS(Status)) return FALSE;
274
275 /* Close the extra handle */
276 Status = NtClose(Handle);
277 if (!NT_SUCCESS(Status)) return FALSE;
278
279 /* Initialize Object Types directory attributes */
280 RtlInitUnicodeString(&Name, L"\\ObjectTypes");
281 InitializeObjectAttributes(&ObjectAttributes,
282 &Name,
283 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
284 NULL,
285 NULL);
286
287 /* Create the directory */
288 Status = NtCreateDirectoryObject(&Handle,
289 DIRECTORY_ALL_ACCESS,
290 &ObjectAttributes);
291 if (!NT_SUCCESS(Status)) return FALSE;
292
293 /* Get a handle to it */
294 Status = ObReferenceObjectByHandle(Handle,
295 0,
296 ObDirectoryType,
297 KernelMode,
298 (PVOID*)&ObpTypeDirectoryObject,
299 NULL);
300 if (!NT_SUCCESS(Status)) return FALSE;
301
302 /* Close the extra handle */
303 Status = NtClose(Handle);
304 if (!NT_SUCCESS(Status)) return FALSE;
305
306 /* Initialize lookup context */
307 ObpInitializeLookupContext(&Context);
308
309 /* Lock it */
310 ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context);
311
312 /* Loop the object types */
313 ListHead = &ObpTypeObjectType->TypeList;
314 NextEntry = ListHead->Flink;
315 while (ListHead != NextEntry)
316 {
317 /* Get the creator info from the list */
318 CreatorInfo = CONTAINING_RECORD(NextEntry,
319 OBJECT_HEADER_CREATOR_INFO,
320 TypeList);
321
322 /* Recover the header and the name header from the creator info */
323 Header = (POBJECT_HEADER)(CreatorInfo + 1);
324 NameInfo = OBJECT_HEADER_TO_NAME_INFO(Header);
325
326 /* Make sure we have a name, and aren't inserted yet */
327 if ((NameInfo) && !(NameInfo->Directory))
328 {
329 /* Do the initial lookup to setup the context */
330 if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
331 &NameInfo->Name,
332 OBJ_CASE_INSENSITIVE,
333 FALSE,
334 &Context))
335 {
336 /* Insert this object type */
337 ObpInsertEntryDirectory(ObpTypeDirectoryObject,
338 &Context,
339 Header);
340 }
341 }
342
343 /* Move to the next entry */
344 NextEntry = NextEntry->Flink;
345 }
346
347 /* Cleanup after lookup */
348 ObpReleaseLookupContext(&Context);
349
350 /* Initialize DOS Devices Directory and related Symbolic Links */
351 Status = ObpCreateDosDevicesDirectory();
352 if (!NT_SUCCESS(Status)) return FALSE;
353 return TRUE;
354 }
355
356 /* EOF */