8d01f35079edaa780a931aac7f7c922f9fd6a7d7
[reactos.git] / ntoskrnl / io / iomgr / iomgr.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/io/iomgr/iomgr.c
5 * PURPOSE: I/O Manager Initialization and Misc Utility Functions
6 *
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
8 */
9
10 /* INCLUDES ****************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 ULONG IopTraceLevel = 0;
17 BOOLEAN PnpSystemInit = FALSE;
18
19 VOID
20 NTAPI
21 IopTimerDispatch(
22 IN PKDPC Dpc,
23 IN PVOID DeferredContext,
24 IN PVOID SystemArgument1,
25 IN PVOID SystemArgument2
26 );
27
28 BOOLEAN
29 NTAPI
30 WmiInitialize(
31 VOID);
32
33 /* DATA ********************************************************************/
34
35 POBJECT_TYPE IoDeviceObjectType = NULL;
36 POBJECT_TYPE IoFileObjectType = NULL;
37 extern POBJECT_TYPE IoControllerObjectType;
38 BOOLEAN IoCountOperations = TRUE;
39 ULONG IoReadOperationCount = 0;
40 LARGE_INTEGER IoReadTransferCount = {{0, 0}};
41 ULONG IoWriteOperationCount = 0;
42 LARGE_INTEGER IoWriteTransferCount = {{0, 0}};
43 ULONG IoOtherOperationCount = 0;
44 LARGE_INTEGER IoOtherTransferCount = {{0, 0}};
45 KSPIN_LOCK IoStatisticsLock = 0;
46 ULONG IopNumTriageDumpDataBlocks;
47 PVOID IopTriageDumpDataBlocks[64];
48
49 GENERIC_MAPPING IopFileMapping = {
50 FILE_GENERIC_READ,
51 FILE_GENERIC_WRITE,
52 FILE_GENERIC_EXECUTE,
53 FILE_ALL_ACCESS};
54
55 extern LIST_ENTRY ShutdownListHead;
56 extern LIST_ENTRY LastChanceShutdownListHead;
57 extern KSPIN_LOCK ShutdownListLock;
58 extern POBJECT_TYPE IoAdapterObjectType;
59 extern ERESOURCE IopDatabaseResource;
60 ERESOURCE IopSecurityResource;
61 extern ERESOURCE IopDriverLoadResource;
62 extern KGUARDED_MUTEX PnpNotifyListLock;
63 extern LIST_ENTRY IopDiskFileSystemQueueHead;
64 extern LIST_ENTRY IopCdRomFileSystemQueueHead;
65 extern LIST_ENTRY IopTapeFileSystemQueueHead;
66 extern LIST_ENTRY IopNetworkFileSystemQueueHead;
67 extern LIST_ENTRY DriverBootReinitListHead;
68 extern LIST_ENTRY DriverReinitListHead;
69 extern LIST_ENTRY PnpNotifyListHead;
70 extern LIST_ENTRY IopFsNotifyChangeQueueHead;
71 extern LIST_ENTRY IopErrorLogListHead;
72 extern LIST_ENTRY IopTimerQueueHead;
73 extern KDPC IopTimerDpc;
74 extern KTIMER IopTimer;
75 extern KSPIN_LOCK IoStatisticsLock;
76 extern KSPIN_LOCK DriverReinitListLock;
77 extern KSPIN_LOCK DriverBootReinitListLock;
78 extern KSPIN_LOCK IopLogListLock;
79 extern KSPIN_LOCK IopTimerLock;
80
81 extern PDEVICE_OBJECT IopErrorLogObject;
82
83 GENERAL_LOOKASIDE IoLargeIrpLookaside;
84 GENERAL_LOOKASIDE IoSmallIrpLookaside;
85 GENERAL_LOOKASIDE IopMdlLookasideList;
86 extern GENERAL_LOOKASIDE IoCompletionPacketLookaside;
87
88 PLOADER_PARAMETER_BLOCK IopLoaderBlock;
89
90 #if defined (ALLOC_PRAGMA)
91 #pragma alloc_text(INIT, IoInitSystem)
92 #endif
93
94 /* INIT FUNCTIONS ************************************************************/
95
96 VOID
97 INIT_FUNCTION
98 NTAPI
99 IopInitLookasideLists(VOID)
100 {
101 ULONG LargeIrpSize, SmallIrpSize, MdlSize;
102 LONG i;
103 PKPRCB Prcb;
104 PGENERAL_LOOKASIDE CurrentList = NULL;
105
106 /* Calculate the sizes */
107 LargeIrpSize = sizeof(IRP) + (8 * sizeof(IO_STACK_LOCATION));
108 SmallIrpSize = sizeof(IRP) + sizeof(IO_STACK_LOCATION);
109 MdlSize = sizeof(MDL) + (23 * sizeof(PFN_NUMBER));
110
111 /* Initialize the Lookaside List for I\O Completion */
112 ExInitializeSystemLookasideList(&IoCompletionPacketLookaside,
113 NonPagedPool,
114 sizeof(IOP_MINI_COMPLETION_PACKET),
115 IOC_TAG1,
116 32,
117 &ExSystemLookasideListHead);
118
119 /* Initialize the Lookaside List for Large IRPs */
120 ExInitializeSystemLookasideList(&IoLargeIrpLookaside,
121 NonPagedPool,
122 LargeIrpSize,
123 IO_LARGEIRP,
124 64,
125 &ExSystemLookasideListHead);
126
127
128 /* Initialize the Lookaside List for Small IRPs */
129 ExInitializeSystemLookasideList(&IoSmallIrpLookaside,
130 NonPagedPool,
131 SmallIrpSize,
132 IO_SMALLIRP,
133 32,
134 &ExSystemLookasideListHead);
135
136 /* Initialize the Lookaside List for MDLs */
137 ExInitializeSystemLookasideList(&IopMdlLookasideList,
138 NonPagedPool,
139 MdlSize,
140 TAG_MDL,
141 128,
142 &ExSystemLookasideListHead);
143
144 /* Allocate the global lookaside list buffer */
145 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
146 4 * KeNumberProcessors *
147 sizeof(GENERAL_LOOKASIDE),
148 TAG_IO);
149
150 /* Loop all processors */
151 for (i = 0; i < KeNumberProcessors; i++)
152 {
153 /* Get the PRCB for this CPU */
154 Prcb = KiProcessorBlock[i];
155 DPRINT("Setting up lookaside for CPU: %x, PRCB: %p\n", i, Prcb);
156
157 /* Write IRP credit limit */
158 Prcb->LookasideIrpFloat = 512 / KeNumberProcessors;
159
160 /* Set the I/O Completion List */
161 Prcb->PPLookasideList[LookasideCompletionList].L = &IoCompletionPacketLookaside;
162 if (CurrentList)
163 {
164 /* Initialize the Lookaside List for mini-packets */
165 ExInitializeSystemLookasideList(CurrentList,
166 NonPagedPool,
167 sizeof(IOP_MINI_COMPLETION_PACKET),
168 IO_SMALLIRP_CPU,
169 32,
170 &ExSystemLookasideListHead);
171 Prcb->PPLookasideList[LookasideCompletionList].P = CurrentList;
172 CurrentList++;
173
174 }
175 else
176 {
177 Prcb->PPLookasideList[LookasideCompletionList].P = &IoCompletionPacketLookaside;
178 }
179
180 /* Set the Large IRP List */
181 Prcb->PPLookasideList[LookasideLargeIrpList].L = &IoLargeIrpLookaside;
182 if (CurrentList)
183 {
184 /* Initialize the Lookaside List for Large IRPs */
185 ExInitializeSystemLookasideList(CurrentList,
186 NonPagedPool,
187 LargeIrpSize,
188 IO_LARGEIRP_CPU,
189 64,
190 &ExSystemLookasideListHead);
191 Prcb->PPLookasideList[LookasideLargeIrpList].P = CurrentList;
192 CurrentList++;
193
194 }
195 else
196 {
197 Prcb->PPLookasideList[LookasideLargeIrpList].P = &IoLargeIrpLookaside;
198 }
199
200 /* Set the Small IRP List */
201 Prcb->PPLookasideList[LookasideSmallIrpList].L = &IoSmallIrpLookaside;
202 if (CurrentList)
203 {
204 /* Initialize the Lookaside List for Small IRPs */
205 ExInitializeSystemLookasideList(CurrentList,
206 NonPagedPool,
207 SmallIrpSize,
208 IO_SMALLIRP_CPU,
209 32,
210 &ExSystemLookasideListHead);
211 Prcb->PPLookasideList[LookasideSmallIrpList].P = CurrentList;
212 CurrentList++;
213
214 }
215 else
216 {
217 Prcb->PPLookasideList[LookasideSmallIrpList].P = &IoSmallIrpLookaside;
218 }
219
220 /* Set the MDL Completion List */
221 Prcb->PPLookasideList[LookasideMdlList].L = &IopMdlLookasideList;
222 if (CurrentList)
223 {
224 /* Initialize the Lookaside List for MDLs */
225 ExInitializeSystemLookasideList(CurrentList,
226 NonPagedPool,
227 SmallIrpSize,
228 TAG_MDL,
229 128,
230 &ExSystemLookasideListHead);
231
232 Prcb->PPLookasideList[LookasideMdlList].P = CurrentList;
233 CurrentList++;
234
235 }
236 else
237 {
238 Prcb->PPLookasideList[LookasideMdlList].P = &IopMdlLookasideList;
239 }
240 }
241 }
242
243 BOOLEAN
244 INIT_FUNCTION
245 NTAPI
246 IopCreateObjectTypes(VOID)
247 {
248 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
249 UNICODE_STRING Name;
250
251 /* Initialize default settings */
252 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
253 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
254 ObjectTypeInitializer.PoolType = NonPagedPool;
255 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
256 ObjectTypeInitializer.ValidAccessMask = FILE_ALL_ACCESS;
257 ObjectTypeInitializer.UseDefaultObject = TRUE;
258 ObjectTypeInitializer.GenericMapping = IopFileMapping;
259
260 /* Do the Adapter Type */
261 RtlInitUnicodeString(&Name, L"Adapter");
262 if (!NT_SUCCESS(ObCreateObjectType(&Name,
263 &ObjectTypeInitializer,
264 NULL,
265 &IoAdapterObjectType))) return FALSE;
266
267 /* Do the Controller Type */
268 RtlInitUnicodeString(&Name, L"Controller");
269 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CONTROLLER_OBJECT);
270 if (!NT_SUCCESS(ObCreateObjectType(&Name,
271 &ObjectTypeInitializer,
272 NULL,
273 &IoControllerObjectType))) return FALSE;
274
275 /* Do the Device Type */
276 RtlInitUnicodeString(&Name, L"Device");
277 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DEVICE_OBJECT);
278 ObjectTypeInitializer.DeleteProcedure = IopDeleteDevice;
279 ObjectTypeInitializer.ParseProcedure = IopParseDevice;
280 ObjectTypeInitializer.SecurityProcedure = IopGetSetSecurityObject;
281 ObjectTypeInitializer.CaseInsensitive = TRUE;
282 if (!NT_SUCCESS(ObCreateObjectType(&Name,
283 &ObjectTypeInitializer,
284 NULL,
285 &IoDeviceObjectType))) return FALSE;
286
287 /* Initialize the Driver object type */
288 RtlInitUnicodeString(&Name, L"Driver");
289 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DRIVER_OBJECT);
290 ObjectTypeInitializer.DeleteProcedure = IopDeleteDriver;
291 ObjectTypeInitializer.ParseProcedure = NULL;
292 ObjectTypeInitializer.SecurityProcedure = NULL;
293 if (!NT_SUCCESS(ObCreateObjectType(&Name,
294 &ObjectTypeInitializer,
295 NULL,
296 &IoDriverObjectType))) return FALSE;
297
298 /* Initialize the I/O Completion object type */
299 RtlInitUnicodeString(&Name, L"IoCompletion");
300 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KQUEUE);
301 ObjectTypeInitializer.ValidAccessMask = IO_COMPLETION_ALL_ACCESS;
302 ObjectTypeInitializer.InvalidAttributes |= OBJ_PERMANENT;
303 ObjectTypeInitializer.GenericMapping = IopCompletionMapping;
304 ObjectTypeInitializer.DeleteProcedure = IopDeleteIoCompletion;
305 if (!NT_SUCCESS(ObCreateObjectType(&Name,
306 &ObjectTypeInitializer,
307 NULL,
308 &IoCompletionType))) return FALSE;
309
310 /* Initialize the File object type */
311 RtlInitUnicodeString(&Name, L"File");
312 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(FILE_OBJECT);
313 ObjectTypeInitializer.InvalidAttributes |= OBJ_EXCLUSIVE;
314 ObjectTypeInitializer.MaintainHandleCount = TRUE;
315 ObjectTypeInitializer.ValidAccessMask = FILE_ALL_ACCESS;
316 ObjectTypeInitializer.GenericMapping = IopFileMapping;
317 ObjectTypeInitializer.CloseProcedure = IopCloseFile;
318 ObjectTypeInitializer.DeleteProcedure = IopDeleteFile;
319 ObjectTypeInitializer.SecurityProcedure = IopGetSetSecurityObject;
320 ObjectTypeInitializer.QueryNameProcedure = IopQueryName;
321 ObjectTypeInitializer.ParseProcedure = IopParseFile;
322 ObjectTypeInitializer.UseDefaultObject = FALSE;
323 if (!NT_SUCCESS(ObCreateObjectType(&Name,
324 &ObjectTypeInitializer,
325 NULL,
326 &IoFileObjectType))) return FALSE;
327
328 /* Success */
329 return TRUE;
330 }
331
332 BOOLEAN
333 INIT_FUNCTION
334 NTAPI
335 IopCreateRootDirectories(VOID)
336 {
337 OBJECT_ATTRIBUTES ObjectAttributes;
338 UNICODE_STRING DirName;
339 HANDLE Handle;
340 NTSTATUS Status;
341
342 /* Create the '\Driver' object directory */
343 RtlInitUnicodeString(&DirName, L"\\Driver");
344 InitializeObjectAttributes(&ObjectAttributes,
345 &DirName,
346 OBJ_PERMANENT,
347 NULL,
348 NULL);
349 Status = NtCreateDirectoryObject(&Handle,
350 DIRECTORY_ALL_ACCESS,
351 &ObjectAttributes);
352 if (!NT_SUCCESS(Status))
353 {
354 DPRINT1("Failed to create \\Driver directory: 0x%lx\n", Status);
355 return FALSE;
356 }
357 NtClose(Handle);
358
359 /* Create the '\FileSystem' object directory */
360 RtlInitUnicodeString(&DirName, L"\\FileSystem");
361 InitializeObjectAttributes(&ObjectAttributes,
362 &DirName,
363 OBJ_PERMANENT,
364 NULL,
365 NULL);
366 Status = NtCreateDirectoryObject(&Handle,
367 DIRECTORY_ALL_ACCESS,
368 &ObjectAttributes);
369 if (!NT_SUCCESS(Status))
370 {
371 DPRINT1("Failed to create \\FileSystem directory: 0x%lx\n", Status);
372 return FALSE;
373 }
374 NtClose(Handle);
375
376 /* Create the '\FileSystem' object directory */
377 RtlInitUnicodeString(&DirName, L"\\FileSystem\\Filters");
378 InitializeObjectAttributes(&ObjectAttributes,
379 &DirName,
380 OBJ_PERMANENT,
381 NULL,
382 NULL);
383 Status = NtCreateDirectoryObject(&Handle,
384 DIRECTORY_ALL_ACCESS,
385 &ObjectAttributes);
386 if (!NT_SUCCESS(Status))
387 {
388 DPRINT1("Failed to create \\FileSystem\\Filters directory: 0x%lx\n", Status);
389 return FALSE;
390 }
391 NtClose(Handle);
392
393 /* Return success */
394 return TRUE;
395 }
396
397 BOOLEAN
398 INIT_FUNCTION
399 NTAPI
400 IopMarkBootPartition(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
401 {
402 OBJECT_ATTRIBUTES ObjectAttributes;
403 STRING DeviceString;
404 CHAR Buffer[256];
405 UNICODE_STRING DeviceName;
406 NTSTATUS Status;
407 HANDLE FileHandle;
408 IO_STATUS_BLOCK IoStatusBlock;
409 PFILE_OBJECT FileObject;
410
411 /* Build the ARC device name */
412 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
413 RtlInitAnsiString(&DeviceString, Buffer);
414 Status = RtlAnsiStringToUnicodeString(&DeviceName, &DeviceString, TRUE);
415 if (!NT_SUCCESS(Status)) return FALSE;
416
417 /* Open it */
418 InitializeObjectAttributes(&ObjectAttributes,
419 &DeviceName,
420 OBJ_CASE_INSENSITIVE,
421 NULL,
422 NULL);
423 Status = ZwOpenFile(&FileHandle,
424 FILE_READ_ATTRIBUTES,
425 &ObjectAttributes,
426 &IoStatusBlock,
427 0,
428 FILE_NON_DIRECTORY_FILE);
429 if (!NT_SUCCESS(Status))
430 {
431 /* Fail */
432 KeBugCheckEx(INACCESSIBLE_BOOT_DEVICE,
433 (ULONG_PTR)&DeviceName,
434 Status,
435 0,
436 0);
437 }
438
439 /* Get the DO */
440 Status = ObReferenceObjectByHandle(FileHandle,
441 0,
442 IoFileObjectType,
443 KernelMode,
444 (PVOID *)&FileObject,
445 NULL);
446 if (!NT_SUCCESS(Status))
447 {
448 /* Fail */
449 RtlFreeUnicodeString(&DeviceName);
450 return FALSE;
451 }
452
453 /* Mark it as the boot partition */
454 FileObject->DeviceObject->Flags |= DO_SYSTEM_BOOT_PARTITION;
455
456 /* Save a copy of the DO for the I/O Error Logger */
457 ObReferenceObject(FileObject->DeviceObject);
458 IopErrorLogObject = FileObject->DeviceObject;
459
460 /* Cleanup and return success */
461 RtlFreeUnicodeString(&DeviceName);
462 NtClose(FileHandle);
463 ObDereferenceObject(FileObject);
464 return TRUE;
465 }
466
467 BOOLEAN
468 INIT_FUNCTION
469 NTAPI
470 IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
471 {
472 LARGE_INTEGER ExpireTime;
473 NTSTATUS Status;
474 CHAR Buffer[256];
475 ANSI_STRING NtBootPath, RootString;
476
477 /* Initialize empty NT Boot Path */
478 RtlInitEmptyAnsiString(&NtBootPath, Buffer, sizeof(Buffer));
479
480 /* Initialize the lookaside lists */
481 IopInitLookasideLists();
482
483 /* Initialize all locks and lists */
484 ExInitializeResourceLite(&IopDatabaseResource);
485 ExInitializeResourceLite(&IopSecurityResource);
486 ExInitializeResourceLite(&IopDriverLoadResource);
487 KeInitializeGuardedMutex(&PnpNotifyListLock);
488 InitializeListHead(&IopDiskFileSystemQueueHead);
489 InitializeListHead(&IopCdRomFileSystemQueueHead);
490 InitializeListHead(&IopTapeFileSystemQueueHead);
491 InitializeListHead(&IopNetworkFileSystemQueueHead);
492 InitializeListHead(&DriverBootReinitListHead);
493 InitializeListHead(&DriverReinitListHead);
494 InitializeListHead(&PnpNotifyListHead);
495 InitializeListHead(&ShutdownListHead);
496 InitializeListHead(&LastChanceShutdownListHead);
497 InitializeListHead(&IopFsNotifyChangeQueueHead);
498 InitializeListHead(&IopErrorLogListHead);
499 KeInitializeSpinLock(&IoStatisticsLock);
500 KeInitializeSpinLock(&DriverReinitListLock);
501 KeInitializeSpinLock(&DriverBootReinitListLock);
502 KeInitializeSpinLock(&ShutdownListLock);
503 KeInitializeSpinLock(&IopLogListLock);
504
505 /* Initialize the reserve IRP */
506 if (!IopInitializeReserveIrp(&IopReserveIrpAllocator))
507 {
508 DPRINT1("IopInitializeReserveIrp failed!\n");
509 return FALSE;
510 }
511
512 /* Initialize Timer List Lock */
513 KeInitializeSpinLock(&IopTimerLock);
514
515 /* Initialize Timer List */
516 InitializeListHead(&IopTimerQueueHead);
517
518 /* Initialize the DPC/Timer which will call the other Timer Routines */
519 ExpireTime.QuadPart = -10000000;
520 KeInitializeDpc(&IopTimerDpc, IopTimerDispatch, NULL);
521 KeInitializeTimerEx(&IopTimer, SynchronizationTimer);
522 KeSetTimerEx(&IopTimer, ExpireTime, 1000, &IopTimerDpc);
523
524 /* Create Object Types */
525 if (!IopCreateObjectTypes())
526 {
527 DPRINT1("IopCreateObjectTypes failed!\n");
528 return FALSE;
529 }
530
531 /* Create Object Directories */
532 if (!IopCreateRootDirectories())
533 {
534 DPRINT1("IopCreateRootDirectories failed!\n");
535 return FALSE;
536 }
537
538 /* Initialize PnP manager */
539 IopInitializePlugPlayServices();
540
541 /* Initialize SHIM engine */
542 ApphelpCacheInitialize();
543
544 /* Initialize WMI */
545 WmiInitialize();
546
547 /* Initialize HAL Root Bus Driver */
548 HalInitPnpDriver();
549
550 /* Make loader block available for the whole kernel */
551 IopLoaderBlock = LoaderBlock;
552
553 /* Load boot start drivers */
554 IopInitializeBootDrivers();
555
556 /* Call back drivers that asked for */
557 IopReinitializeBootDrivers();
558
559 /* Check if this was a ramdisk boot */
560 if (!_strnicmp(LoaderBlock->ArcBootDeviceName, "ramdisk(0)", 10))
561 {
562 /* Initialize the ramdisk driver */
563 IopStartRamdisk(LoaderBlock);
564 }
565
566 /* No one should need loader block any longer */
567 IopLoaderBlock = NULL;
568
569 /* Create ARC names for boot devices */
570 Status = IopCreateArcNames(LoaderBlock);
571 if (!NT_SUCCESS(Status))
572 {
573 DPRINT1("IopCreateArcNames failed: %lx\n", Status);
574 return FALSE;
575 }
576
577 /* Mark the system boot partition */
578 if (!IopMarkBootPartition(LoaderBlock))
579 {
580 DPRINT1("IopMarkBootPartition failed!\n");
581 return FALSE;
582 }
583
584 /* Initialize PnP root relations */
585 IopEnumerateDevice(IopRootDeviceNode->PhysicalDeviceObject);
586
587 #ifndef _WINKD_
588 /* Read KDB Data */
589 KdbInit();
590
591 /* I/O is now setup for disk access, so phase 3 */
592 KdInitSystem(3, LoaderBlock);
593 #endif
594
595 /* Load services for devices found by PnP manager */
596 IopInitializePnpServices(IopRootDeviceNode);
597
598 /* Load system start drivers */
599 IopInitializeSystemDrivers();
600 PnpSystemInit = TRUE;
601
602 /* Reinitialize drivers that requested it */
603 IopReinitializeDrivers();
604
605 /* Convert SystemRoot from ARC to NT path */
606 Status = IopReassignSystemRoot(LoaderBlock, &NtBootPath);
607 if (!NT_SUCCESS(Status))
608 {
609 DPRINT1("IopReassignSystemRoot failed: %lx\n", Status);
610 return FALSE;
611 }
612
613 /* Set the ANSI_STRING for the root path */
614 RootString.MaximumLength = NtSystemRoot.MaximumLength / sizeof(WCHAR);
615 RootString.Length = 0;
616 RootString.Buffer = ExAllocatePoolWithTag(PagedPool,
617 RootString.MaximumLength,
618 TAG_IO);
619
620 /* Convert the path into the ANSI_STRING */
621 Status = RtlUnicodeStringToAnsiString(&RootString, &NtSystemRoot, FALSE);
622 if (!NT_SUCCESS(Status))
623 {
624 DPRINT1("RtlUnicodeStringToAnsiString failed: %lx\n", Status);
625 return FALSE;
626 }
627
628 /* Assign drive letters */
629 IoAssignDriveLetters(LoaderBlock,
630 &NtBootPath,
631 (PUCHAR)RootString.Buffer,
632 &RootString);
633
634 /* Update system root */
635 Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &RootString, FALSE);
636 if (!NT_SUCCESS(Status))
637 {
638 DPRINT1("RtlAnsiStringToUnicodeString failed: %lx\n", Status);
639 return FALSE;
640 }
641
642 /* Load the System DLL and its Entrypoints */
643 Status = PsLocateSystemDll();
644 if (!NT_SUCCESS(Status))
645 {
646 DPRINT1("PsLocateSystemDll failed: %lx\n", Status);
647 return FALSE;
648 }
649
650 /* Return success */
651 return TRUE;
652 }
653
654 BOOLEAN
655 NTAPI
656 IoInitializeCrashDump(IN HANDLE PageFileHandle)
657 {
658 UNIMPLEMENTED;
659 return FALSE;
660 }
661
662 /* EOF */