878be047b4fe111957515071428f00528216d6ae
[reactos.git] / reactos / ntoskrnl / ex / init.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ex/init.c
5 * PURPOSE: Executive initalization
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Added ExpInitializeExecutive
8 * and optimized/cleaned it.
9 * Eric Kohl (ekohl@abo.rhein-zeitung.de)
10 */
11
12 #include <ntoskrnl.h>
13 #include <ntos/bootvid.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* DATA **********************************************************************/
18
19 extern ULONG MmCoreDumpType;
20 extern CHAR KiTimerSystemAuditing;
21 extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
22 extern ADDRESS_RANGE KeMemoryMap[64];
23 extern ULONG KeMemoryMapRangeCount;
24 extern ULONG_PTR FirstKrnlPhysAddr;
25 extern ULONG_PTR LastKrnlPhysAddr;
26 extern ULONG_PTR LastKernelAddress;
27 extern LOADER_MODULE KeLoaderModules[64];
28
29 /* FUNCTIONS ****************************************************************/
30
31 static
32 VOID
33 INIT_FUNCTION
34 InitSystemSharedUserPage (PCSZ ParameterLine)
35 {
36 UNICODE_STRING ArcDeviceName;
37 UNICODE_STRING ArcName;
38 UNICODE_STRING BootPath;
39 UNICODE_STRING DriveDeviceName;
40 UNICODE_STRING DriveName;
41 WCHAR DriveNameBuffer[20];
42 PCHAR ParamBuffer;
43 PWCHAR ArcNameBuffer;
44 PCHAR p;
45 NTSTATUS Status;
46 ULONG Length;
47 OBJECT_ATTRIBUTES ObjectAttributes;
48 HANDLE Handle;
49 ULONG i;
50 BOOLEAN BootDriveFound = FALSE;
51
52 /*
53 * NOTE:
54 * The shared user page has been zeroed-out right after creation.
55 * There is NO need to do this again.
56 */
57 Ki386SetProcessorFeatures();
58
59 /* Set the Version Data */
60 SharedUserData->NtProductType = NtProductWinNt;
61 SharedUserData->ProductTypeIsValid = TRUE;
62 SharedUserData->NtMajorVersion = 5;
63 SharedUserData->NtMinorVersion = 0;
64
65 /*
66 * Retrieve the current dos system path
67 * (e.g.: C:\reactos) from the given arc path
68 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
69 * Format: "<arc_name>\<path> [options...]"
70 */
71
72 /* Create local parameter line copy */
73 ParamBuffer = ExAllocatePool(PagedPool, 256);
74 strcpy (ParamBuffer, (char *)ParameterLine);
75 DPRINT("%s\n", ParamBuffer);
76
77 /* Cut options off */
78 p = strchr (ParamBuffer, ' ');
79 if (p) *p = 0;
80 DPRINT("%s\n", ParamBuffer);
81
82 /* Extract path */
83 p = strchr (ParamBuffer, '\\');
84 if (p) {
85
86 DPRINT("Boot path: %s\n", p);
87 RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
88 *p = 0;
89
90 } else {
91
92 DPRINT("Boot path: %s\n", "\\");
93 RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
94 }
95 DPRINT("Arc name: %s\n", ParamBuffer);
96
97 /* Only ARC Name left - Build full ARC Name */
98 ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
99 swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
100 RtlInitUnicodeString (&ArcName, ArcNameBuffer);
101 DPRINT("Arc name: %wZ\n", &ArcName);
102
103 /* Free ParamBuffer */
104 ExFreePool (ParamBuffer);
105
106 /* Allocate ARC Device Name string */
107 ArcDeviceName.Length = 0;
108 ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
109 ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
110
111 /* Open the Symbolic Link */
112 InitializeObjectAttributes(&ObjectAttributes,
113 &ArcName,
114 OBJ_OPENLINK,
115 NULL,
116 NULL);
117 Status = NtOpenSymbolicLinkObject(&Handle,
118 SYMBOLIC_LINK_ALL_ACCESS,
119 &ObjectAttributes);
120
121 /* Free the String */
122 RtlFreeUnicodeString (&ArcName);
123
124 /* Check for Success */
125 if (!NT_SUCCESS(Status)) {
126
127 /* Free the Strings */
128 RtlFreeUnicodeString(&BootPath);
129 RtlFreeUnicodeString(&ArcDeviceName);
130 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n", Status);
131 KEBUGCHECK(0);
132 }
133
134 /* Query the Link */
135 Status = NtQuerySymbolicLinkObject(Handle,
136 &ArcDeviceName,
137 &Length);
138 NtClose (Handle);
139
140 /* Check for Success */
141 if (!NT_SUCCESS(Status)) {
142
143 /* Free the Strings */
144 RtlFreeUnicodeString(&BootPath);
145 RtlFreeUnicodeString(&ArcDeviceName);
146 CPRINT("NtQuerySymbolicLinkObject() failed (Status %x)\n", Status);
147 KEBUGCHECK(0);
148 }
149 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
150
151 /* Allocate Device Name string */
152 DriveDeviceName.Length = 0;
153 DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
154 DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
155
156 /* Loop Drives */
157 for (i = 0; i < 26; i++) {
158
159 /* Setup the String */
160 swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
161 RtlInitUnicodeString(&DriveName,
162 DriveNameBuffer);
163
164 /* Open the Symbolic Link */
165 InitializeObjectAttributes(&ObjectAttributes,
166 &DriveName,
167 OBJ_OPENLINK,
168 NULL,
169 NULL);
170 Status = NtOpenSymbolicLinkObject(&Handle,
171 SYMBOLIC_LINK_ALL_ACCESS,
172 &ObjectAttributes);
173
174 /* If it failed, skip to the next drive */
175 if (!NT_SUCCESS(Status)) {
176 DPRINT("Failed to open link %wZ\n", &DriveName);
177 continue;
178 }
179
180 /* Query it */
181 Status = NtQuerySymbolicLinkObject(Handle,
182 &DriveDeviceName,
183 &Length);
184
185 /* If it failed, skip to the next drive */
186 if (!NT_SUCCESS(Status)) {
187 DPRINT("Failed to query link %wZ\n", &DriveName);
188 continue;
189 }
190 DPRINT("Opened link: %wZ ==> %wZ\n", &DriveName, &DriveDeviceName);
191
192 /* See if we've found the boot drive */
193 if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE)) {
194
195 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
196 swprintf(SharedUserData->NtSystemRoot, L"%C:%wZ", 'A' + i, &BootPath);
197 BootDriveFound = TRUE;
198 }
199
200 /* Close this Link */
201 NtClose (Handle);
202 }
203
204 /* Free all the Strings we have in memory */
205 RtlFreeUnicodeString (&BootPath);
206 RtlFreeUnicodeString (&DriveDeviceName);
207 RtlFreeUnicodeString (&ArcDeviceName);
208
209 /* Make sure we found the Boot Drive */
210 if (BootDriveFound == FALSE) {
211
212 DbgPrint("No system drive found!\n");
213 KEBUGCHECK (NO_BOOT_DEVICE);
214 }
215 }
216
217 inline
218 VOID
219 STDCALL
220 ExecuteRuntimeAsserts(VOID)
221 {
222 /*
223 * Fail at runtime if someone has changed various structures without
224 * updating the offsets used for the assembler code.
225 */
226 ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
227 ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
228 ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
229 ASSERT(FIELD_OFFSET(KTHREAD, NpxState) == KTHREAD_NPX_STATE);
230 ASSERT(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
231 ASSERT(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
232 ASSERT(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
233 ASSERT(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
234 ASSERT(FIELD_OFFSET(KTHREAD, ApcState.Process) == KTHREAD_APCSTATE_PROCESS);
235 ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
236 ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
237 ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
238 ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
239 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
240 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
241 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
242 ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
243 ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
244 ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);
245 ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
246 ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
247 ASSERT(FIELD_OFFSET(KTSS, Eflags) == KTSS_EFLAGS);
248 ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
249 ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
250 }
251
252 inline
253 VOID
254 STDCALL
255 ParseAndCacheLoadedModules(PBOOLEAN SetupBoot)
256 {
257 ULONG i;
258 PCHAR Name;
259
260 /* Loop the Module List and get the modules we want */
261 for (i = 1; i < KeLoaderBlock.ModsCount; i++) {
262
263 /* Get the Name of this Module */
264 if (!(Name = strrchr((PCHAR)KeLoaderModules[i].String, '\\'))) {
265
266 /* Save the name */
267 Name = (PCHAR)KeLoaderModules[i].String;
268
269 } else {
270
271 /* No name, skip */
272 Name++;
273 }
274
275 /* Now check for any of the modules we will need later */
276 if (!_stricmp(Name, "ansi.nls")) {
277
278 CachedModules[AnsiCodepage] = &KeLoaderModules[i];
279
280 } else if (!_stricmp(Name, "oem.nls")) {
281
282 CachedModules[OemCodepage] = &KeLoaderModules[i];
283
284 } else if (!_stricmp(Name, "casemap.nls")) {
285
286 CachedModules[UnicodeCasemap] = &KeLoaderModules[i];
287
288 } else if (!_stricmp(Name, "system") || !_stricmp(Name, "system.hiv")) {
289
290 CachedModules[SystemRegistry] = &KeLoaderModules[i];
291 *SetupBoot = FALSE;
292
293 } else if (!_stricmp(Name, "hardware") || !_stricmp(Name, "hardware.hiv")) {
294
295 CachedModules[HardwareRegistry] = &KeLoaderModules[i];
296 }
297 }
298 }
299
300 inline
301 VOID
302 STDCALL
303 ParseCommandLine(PULONG MaxMem, PBOOLEAN NoGuiBoot, PBOOLEAN BootLog)
304 {
305 PCHAR p1, p2;
306
307 p1 = (PCHAR)KeLoaderBlock.CommandLine;
308 while(*p1 && (p2 = strchr(p1, '/'))) {
309
310 p2++;
311 if (!_strnicmp(p2, "MAXMEM", 6)) {
312
313 p2 += 6;
314 while (isspace(*p2)) p2++;
315
316 if (*p2 == '=') {
317
318 p2++;
319
320 while(isspace(*p2)) p2++;
321
322 if (isdigit(*p2)) {
323 while (isdigit(*p2)) {
324 *MaxMem = *MaxMem * 10 + *p2 - '0';
325 p2++;
326 }
327 break;
328 }
329 }
330 } else if (!_strnicmp(p2, "NOGUIBOOT", 9)) {
331
332 p2 += 9;
333 *NoGuiBoot = TRUE;
334
335 } else if (!_strnicmp(p2, "CRASHDUMP", 9)) {
336
337 p2 += 9;
338 if (*p2 == ':') {
339
340 p2++;
341 if (!_strnicmp(p2, "FULL", 4)) {
342
343 MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
344
345 } else {
346
347 MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
348 }
349 }
350 } else if (!_strnicmp(p2, "BOOTLOG", 7)) {
351
352 p2 += 7;
353 *BootLog = TRUE;
354 }
355
356 p1 = p2;
357 }
358 }
359
360 VOID
361 INIT_FUNCTION
362 STDCALL
363 ExpInitializeExecutive(VOID)
364 {
365 CHAR str[50];
366 UNICODE_STRING EventName;
367 HANDLE InitDoneEventHandle;
368 OBJECT_ATTRIBUTES ObjectAttributes;
369 BOOLEAN NoGuiBoot = FALSE;
370 BOOLEAN BootLog = FALSE;
371 ULONG MaxMem = 0;
372 BOOLEAN SetupBoot = TRUE;
373 LARGE_INTEGER Timeout;
374 HANDLE ProcessHandle;
375 HANDLE ThreadHandle;
376 NTSTATUS Status;
377
378 /* Check if the structures match the ASM offset constants */
379 ExecuteRuntimeAsserts();
380
381 /* Sets up the Text Sections of the Kernel and HAL for debugging */
382 LdrInit1();
383
384 /* Lower the IRQL to Dispatch Level */
385 KeLowerIrql(DISPATCH_LEVEL);
386
387 /* Sets up the VDM Data */
388 NtEarlyInitVdm();
389
390 /* Parse Command Line Settings */
391 ParseCommandLine(&MaxMem, &NoGuiBoot, &BootLog);
392
393 /* Initialize Kernel Memory Address Space */
394 MmInit1(FirstKrnlPhysAddr,
395 LastKrnlPhysAddr,
396 LastKernelAddress,
397 (PADDRESS_RANGE)&KeMemoryMap,
398 KeMemoryMapRangeCount,
399 MaxMem > 8 ? MaxMem : 4096);
400
401 /* Parse the Loaded Modules (by FreeLoader) and cache the ones we'll need */
402 ParseAndCacheLoadedModules(&SetupBoot);
403
404 /* Initialize the kernel debugger */
405 KdInitSystem (1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
406
407 /* Initialize the Dispatcher, Clock and Bug Check Mechanisms. */
408 KeInit2();
409
410 /* Bring back the IRQL to Passive */
411 KeLowerIrql(PASSIVE_LEVEL);
412
413 /* Load basic Security for other Managers */
414 if (!SeInit1()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
415
416 /* Create the Basic Object Manager Types to allow new Object Types */
417 ObInit();
418
419 /* Initialize Lookaside Lists */
420 ExInit2();
421
422 /* Set up Region Maps, Sections and the Paging File */
423 MmInit2();
424
425 /* Initialize Tokens now that the Object Manager is ready */
426 if (!SeInit2()) KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
427
428 /* Set 1 CPU for now, we'll increment this later */
429 KeNumberProcessors = 1;
430
431 /* Initalize the Process Manager */
432 PiInitProcessManager();
433
434 /* Break into the Debugger if requested */
435 if (KdPollBreakIn()) DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
436
437 /* Initialize all processors */
438 while (!HalAllProcessorsStarted()) {
439
440 PVOID ProcessorStack;
441
442 /* Set up the Kernel and Process Manager for this CPU */
443 KePrepareForApplicationProcessorInit(KeNumberProcessors);
444 PsPrepareForApplicationProcessorInit(KeNumberProcessors);
445
446 /* Allocate a stack for use when booting the processor */
447 ProcessorStack = Ki386InitialStackArray[((int)KeNumberProcessors)] + MM_STACK_SIZE;
448
449 /* Tell HAL a new CPU is being started */
450 HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA));
451 KeNumberProcessors++;
452 }
453
454 /* Do Phase 1 HAL Initalization */
455 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
456
457 /* Initialize Basic System Objects and Worker Threads */
458 ExInit3();
459
460 /* Initialize the GDB Stub and break */
461 KdInit1();
462
463 /* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
464 IoInit();
465
466 /* TBD */
467 PoInit();
468
469 /* Initialize the Registry (Hives are NOT yet loaded!) */
470 CmInitializeRegistry();
471
472 /* Unmap Low memory, initialize the Page Zeroing and the Balancer Thread */
473 MmInit3();
474
475 /* Initialize Cache Views */
476 CcInit();
477
478 /* Hook System Interrupt for the Debugger */
479 KdInit2();
480
481 /* Initialize File Locking */
482 FsRtlpInitFileLockingImplementation();
483
484 /* Report all resources used by hal */
485 HalReportResourceUsage();
486
487 /* Clear the screen to blue */
488 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
489
490 /* Display version number and copyright/warranty message */
491 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
492 KERNEL_VERSION_BUILD_STR")\n");
493 HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
494 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
495 "Public License, and you\n");
496 HalDisplayString("are welcome to change it and/or distribute copies of it "
497 "under certain\n");
498 HalDisplayString("conditions. There is absolutely no warranty for "
499 "ReactOS.\n\n");
500
501 /* Display number of Processors */
502 sprintf(str,
503 "Found %d system processor(s). [%lu MB Memory]\n",
504 KeNumberProcessors,
505 (KeLoaderBlock.MemHigher + 1088)/ 1024);
506 HalDisplayString(str);
507
508 /* Print which Debugger is being used */
509 KdInit3();
510
511 /* Import and create NLS Data and Sections */
512 RtlpInitNls();
513
514 /* Import and Load Registry Hives */
515 CmInitHives(SetupBoot);
516
517 /* Initialize the time zone information from the registry */
518 ExpInitTimeZoneInfo();
519
520 /* Enter the kernel debugger before starting up the boot drivers */
521 #ifdef KDBG
522 KdbEnter();
523 #endif /* KDBG */
524
525 /* Setup Drivers and Root Device Node */
526 IoInit2(BootLog);
527
528 /* Display the boot screen image if not disabled */
529 if (!NoGuiBoot) InbvEnableBootDriver(TRUE);
530
531 /* Create ARC Names, SystemRoot SymLink, Load Drivers and Assign Letters */
532 IoInit3();
533
534 /* Initialize the Default Locale */
535 PiInitDefaultLocale();
536
537 /* Initialize shared user page. Set dos system path, dos device map, etc. */
538 InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
539
540 /* Create 'ReactOSInitDone' event */
541 RtlInitUnicodeString(&EventName, L"\\ReactOSInitDone");
542 InitializeObjectAttributes(&ObjectAttributes,
543 &EventName,
544 0,
545 NULL,
546 NULL);
547 Status = ZwCreateEvent(&InitDoneEventHandle,
548 EVENT_ALL_ACCESS,
549 &ObjectAttributes,
550 SynchronizationEvent,
551 FALSE);
552
553 /* Check for Success */
554 if (!NT_SUCCESS(Status)) {
555
556 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
557 InitDoneEventHandle = INVALID_HANDLE_VALUE;
558 }
559
560 /* Launch initial process */
561 Status = LdrLoadInitialProcess(&ProcessHandle,
562 &ThreadHandle);
563
564 /* Check for success, Bugcheck if we failed */
565 if (!NT_SUCCESS(Status)) {
566
567 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
568 }
569
570 /* Wait on the Completion Event */
571 if (InitDoneEventHandle != INVALID_HANDLE_VALUE) {
572
573 HANDLE Handles[2]; /* Init event, Initial process */
574
575 /* Setup the Handles to wait on */
576 Handles[0] = InitDoneEventHandle;
577 Handles[1] = ProcessHandle;
578
579 /* Wait for the system to be initialized */
580 Timeout.QuadPart = (LONGLONG)-1200000000; /* 120 second timeout */
581 Status = ZwWaitForMultipleObjects(2,
582 Handles,
583 WaitAny,
584 FALSE,
585 &Timeout);
586 if (!NT_SUCCESS(Status)) {
587
588 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
589
590 } else if (Status == STATUS_TIMEOUT) {
591
592 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
593
594 } else if (Status == STATUS_WAIT_0 + 1) {
595
596 /* Crash the system if the initial process was terminated. */
597 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
598 }
599
600 /* Disable the Boot Logo */
601 if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
602
603 /* Signal the Event and close the handle */
604 ZwSetEvent(InitDoneEventHandle, NULL);
605 ZwClose(InitDoneEventHandle);
606
607 } else {
608
609 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
610 if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
611
612 /* Crash the system if the initial process terminates within 5 seconds. */
613 Timeout.QuadPart = (LONGLONG)-50000000; /* 5 second timeout */
614 Status = ZwWaitForSingleObject(ProcessHandle,
615 FALSE,
616 &Timeout);
617
618 /* Check for timeout, crash if the initial process didn't initalize */
619 if (Status != STATUS_TIMEOUT) KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
620 }
621
622 /* Enable the Clock, close remaining handles */
623 KiTimerSystemAuditing = 1;
624 ZwClose(ThreadHandle);
625 ZwClose(ProcessHandle);
626 }
627
628 VOID INIT_FUNCTION
629 ExInit2(VOID)
630 {
631 ExpInitLookasideLists();
632 }
633
634 VOID INIT_FUNCTION
635 ExInit3 (VOID)
636 {
637 ExpInitializeWorkerThreads();
638 ExpInitializeEventImplementation();
639 ExpInitializeEventPairImplementation();
640 ExpInitializeMutantImplementation();
641 ExpInitializeSemaphoreImplementation();
642 ExpInitializeTimerImplementation();
643 LpcpInitSystem();
644 ExpInitializeProfileImplementation();
645 ExpWin32kInit();
646 ExpInitUuids();
647 ExpInitializeCallbacks();
648 }
649
650 /* EOF */