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