2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/arcname.c
5 * PURPOSE: ARC Path Initialization Functions
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Pierre Schweitzer (pierre.schweitzer@reactos.org)
11 /* INCLUDES ******************************************************************/
17 /* GLOBALS *******************************************************************/
19 UNICODE_STRING IoArcHalDeviceName
, IoArcBootDeviceName
;
20 PCHAR IoLoaderArcBootDeviceName
;
22 /* FUNCTIONS *****************************************************************/
27 IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
32 IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
33 IN BOOLEAN SingleDisk
,
34 OUT PBOOLEAN FoundBoot
);
39 IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
45 BOOLEAN FoundBoot
= FALSE
;
46 UNICODE_STRING SystemDevice
, LoaderPathNameW
, BootDeviceName
;
47 PARC_DISK_INFORMATION ArcDiskInfo
= LoaderBlock
->ArcDiskInformation
;
48 ANSI_STRING ArcSystemString
, ArcString
, LanmanRedirector
, LoaderPathNameA
;
50 /* Check if we only have one disk on the machine */
51 SingleDisk
= (ArcDiskInfo
->DiskSignatureListHead
.Flink
->Flink
==
52 &ArcDiskInfo
->DiskSignatureListHead
);
54 /* Create the global HAL partition name */
55 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcHalDeviceName
);
56 RtlInitAnsiString(&ArcString
, Buffer
);
57 Status
= RtlAnsiStringToUnicodeString(&IoArcHalDeviceName
, &ArcString
, TRUE
);
58 if (!NT_SUCCESS(Status
))
61 /* Create the global system partition name */
62 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
63 RtlInitAnsiString(&ArcString
, Buffer
);
64 Status
= RtlAnsiStringToUnicodeString(&IoArcBootDeviceName
, &ArcString
, TRUE
);
65 if (!NT_SUCCESS(Status
))
68 /* Allocate memory for the string */
69 Length
= strlen(LoaderBlock
->ArcBootDeviceName
) + sizeof(ANSI_NULL
);
70 IoLoaderArcBootDeviceName
= ExAllocatePoolWithTag(PagedPool
,
73 if (IoLoaderArcBootDeviceName
)
76 RtlCopyMemory(IoLoaderArcBootDeviceName
,
77 LoaderBlock
->ArcBootDeviceName
,
81 /* Check if we only found a disk, but we're booting from CD-ROM */
82 if ((SingleDisk
) && strstr(LoaderBlock
->ArcBootDeviceName
, "cdrom"))
84 /* Then disable single-disk mode, since there's a CD drive out there */
88 /* Build the boot strings */
89 RtlInitAnsiString(&ArcSystemString
, LoaderBlock
->ArcHalDeviceName
);
91 /* If we are doing remote booting */
92 if (IoRemoteBootClient
)
94 /* Yes, we have found boot device */
97 /* Get NT device name */
98 RtlInitAnsiString(&LanmanRedirector
, "\\Device\\LanmanRedirector");
99 Status
= RtlAnsiStringToUnicodeString(&SystemDevice
, &LanmanRedirector
, TRUE
);
100 if (!NT_SUCCESS(Status
))
105 /* Get ARC booting device name (in net(0) something) */
106 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
107 RtlInitAnsiString(&ArcString
, Buffer
);
108 Status
= RtlAnsiStringToUnicodeString(&BootDeviceName
, &ArcString
, TRUE
);
109 if (NT_SUCCESS(Status
))
111 /* Map ARC to NT name */
112 IoAssignArcName(&BootDeviceName
, &SystemDevice
);
113 RtlFreeUnicodeString(&BootDeviceName
);
115 /* Now, get loader path name */
116 RtlInitAnsiString(&LoaderPathNameA
, LoaderBlock
->NtHalPathName
);
117 Status
= RtlAnsiStringToUnicodeString(&LoaderPathNameW
, &LoaderPathNameA
, TRUE
);
118 if (!NT_SUCCESS(Status
))
120 RtlFreeUnicodeString(&SystemDevice
);
124 /* And set it has system partition */
125 IopStoreSystemPartitionInformation(&SystemDevice
, &LoaderPathNameW
);
128 RtlFreeUnicodeString(&SystemDevice
);
130 /* Don't quit here, even if everything went fine!
131 * We need IopCreateArcNamesDisk to properly map
132 * devices with symlinks.
133 * It will return success if the mapping process went fine
134 * even if it didn't find boot device.
135 * It won't reset boot device finding status as well.
139 /* Loop every disk and try to find boot disk */
140 Status
= IopCreateArcNamesDisk(LoaderBlock
, SingleDisk
, &FoundBoot
);
141 /* If it succeeded but we didn't find boot device, try to browse Cds */
142 if (NT_SUCCESS(Status
) && !FoundBoot
)
144 Status
= IopCreateArcNamesCd(LoaderBlock
);
154 IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
159 PLIST_ENTRY NextEntry
;
160 PFILE_OBJECT FileObject
;
161 PDEVICE_OBJECT DeviceObject
;
162 LARGE_INTEGER StartingOffset
;
163 IO_STATUS_BLOCK IoStatusBlock
;
164 PULONG PartitionBuffer
= NULL
;
165 CHAR Buffer
[128], ArcBuffer
[128];
166 BOOLEAN NotEnabledPresent
= FALSE
;
167 STORAGE_DEVICE_NUMBER DeviceNumber
;
168 ANSI_STRING DeviceStringA
, ArcNameStringA
;
169 PWSTR SymbolicLinkList
, lSymbolicLinkList
;
170 PARC_DISK_SIGNATURE ArcDiskSignature
= NULL
;
171 UNICODE_STRING DeviceStringW
, ArcNameStringW
;
172 ULONG DiskNumber
, CdRomCount
, CheckSum
, i
, EnabledDisks
= 0;
173 PARC_DISK_INFORMATION ArcDiskInformation
= LoaderBlock
->ArcDiskInformation
;
175 /* Get all the Cds present in the system */
176 CdRomCount
= IoGetConfigurationInformation()->CdRomCount
;
178 /* Get enabled Cds and check if result matches
179 * For the record, enabled Cds (or even disk) are Cds/disks
180 * that have been successfully handled by MountMgr driver
181 * and that already own their device name. This is the "new" way
182 * to handle them, that came with NT5.
183 * Currently, Windows 2003 provides an ARC names creation based
184 * on both enabled drives and not enabled drives (lack from
186 * Given the current ReactOS state, that's good for us.
187 * To sum up, this is NOT a hack or whatsoever.
189 Status
= IopFetchConfigurationInformation(&SymbolicLinkList
,
190 GUID_DEVINTERFACE_CDROM
,
193 if (!NT_SUCCESS(Status
))
195 NotEnabledPresent
= TRUE
;
197 /* Save symbolic link list address in order to free it after */
198 lSymbolicLinkList
= SymbolicLinkList
;
199 /* For the moment, we won't fail */
200 Status
= STATUS_SUCCESS
;
202 /* Browse all the ARC devices trying to find the one matching boot device */
203 for (NextEntry
= ArcDiskInformation
->DiskSignatureListHead
.Flink
;
204 NextEntry
!= &ArcDiskInformation
->DiskSignatureListHead
;
205 NextEntry
= NextEntry
->Flink
)
207 ArcDiskSignature
= CONTAINING_RECORD(NextEntry
,
211 if (strcmp(LoaderBlock
->ArcBootDeviceName
, ArcDiskSignature
->ArcName
) == 0)
216 ArcDiskSignature
= NULL
;
219 /* Not found... Not booting from a Cd */
220 if (!ArcDiskSignature
)
222 DPRINT("Failed finding a cd that could match current boot device\n");
226 /* Allocate needed space for reading Cd */
227 PartitionBuffer
= ExAllocatePoolWithTag(NonPagedPoolCacheAligned
, 2048, TAG_IO
);
228 if (!PartitionBuffer
)
230 DPRINT("Failed allocating resources!\n");
231 /* Here, we fail, BUT we return success, some Microsoft joke */
235 /* If we have more enabled Cds, take that into account */
236 if (EnabledDisks
> CdRomCount
)
238 CdRomCount
= EnabledDisks
;
241 /* If we'll have to browse for none enabled Cds, fix higher count */
242 if (NotEnabledPresent
&& !EnabledDisks
)
247 /* Finally, if in spite of all that work, we still don't have Cds, leave */
253 /* Start browsing Cds */
254 for (DiskNumber
= 0, EnabledDisks
= 0; DiskNumber
< CdRomCount
; DiskNumber
++)
256 /* Check if we have an enabled disk */
257 if (lSymbolicLinkList
&& *lSymbolicLinkList
!= UNICODE_NULL
)
259 /* Create its device name using first symbolic link */
260 RtlInitUnicodeString(&DeviceStringW
, lSymbolicLinkList
);
261 /* Then, update symbolic links list */
262 lSymbolicLinkList
+= wcslen(lSymbolicLinkList
) + (sizeof(UNICODE_NULL
) / sizeof(WCHAR
));
264 /* Get its associated device object and file object */
265 Status
= IoGetDeviceObjectPointer(&DeviceStringW
,
266 FILE_READ_ATTRIBUTES
,
269 /* Failure? Good bye! */
270 if (!NT_SUCCESS(Status
))
275 /* Now, we'll ask the device its device number */
276 Irp
= IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER
,
281 sizeof(DeviceNumber
),
285 /* Failure? Good bye! */
288 /* Dereference file object before leaving */
289 ObDereferenceObject(FileObject
);
290 Status
= STATUS_INSUFFICIENT_RESOURCES
;
294 /* Call the driver, and wait for it if needed */
295 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
296 Status
= IoCallDriver(DeviceObject
, Irp
);
297 if (Status
== STATUS_PENDING
)
299 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
300 Status
= IoStatusBlock
.Status
;
302 if (!NT_SUCCESS(Status
))
304 ObDereferenceObject(FileObject
);
308 /* Finally, build proper device name */
309 sprintf(Buffer
, "\\Device\\CdRom%lu", DeviceNumber
.DeviceNumber
);
310 RtlInitAnsiString(&DeviceStringA
, Buffer
);
311 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
312 if (!NT_SUCCESS(Status
))
314 ObDereferenceObject(FileObject
);
320 /* Create device name for the cd */
321 sprintf(Buffer
, "\\Device\\CdRom%lu", EnabledDisks
++);
322 RtlInitAnsiString(&DeviceStringA
, Buffer
);
323 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
324 if (!NT_SUCCESS(Status
))
329 /* Get its device object */
330 Status
= IoGetDeviceObjectPointer(&DeviceStringW
,
331 FILE_READ_ATTRIBUTES
,
334 if (!NT_SUCCESS(Status
))
336 RtlFreeUnicodeString(&DeviceStringW
);
341 /* Initiate data for reading cd and compute checksum */
342 StartingOffset
.QuadPart
= 0x8000;
344 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
353 /* Call the driver, and wait for it if needed */
354 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
355 Status
= IoCallDriver(DeviceObject
, Irp
);
356 if (Status
== STATUS_PENDING
)
358 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
359 Status
= IoStatusBlock
.Status
;
362 /* If reading succeeded, compute checksum by adding data, 2048 bytes checksum */
363 if (NT_SUCCESS(Status
))
365 for (i
= 0; i
< 2048 / sizeof(ULONG
); i
++)
367 CheckSum
+= PartitionBuffer
[i
];
372 /* Dereference file object */
373 ObDereferenceObject(FileObject
);
375 /* If checksums are matching, we have the proper cd */
376 if (CheckSum
+ ArcDiskSignature
->CheckSum
== 0)
378 /* Create ARC name */
379 sprintf(ArcBuffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
380 RtlInitAnsiString(&ArcNameStringA
, ArcBuffer
);
381 Status
= RtlAnsiStringToUnicodeString(&ArcNameStringW
, &ArcNameStringA
, TRUE
);
382 if (NT_SUCCESS(Status
))
384 /* Create symbolic link */
385 IoAssignArcName(&ArcNameStringW
, &DeviceStringW
);
386 RtlFreeUnicodeString(&ArcNameStringW
);
387 DPRINT("Boot device found\n");
390 /* And quit, whatever happens */
391 RtlFreeUnicodeString(&DeviceStringW
);
395 /* Free string before trying another disk */
396 RtlFreeUnicodeString(&DeviceStringW
);
402 ExFreePoolWithTag(PartitionBuffer
, TAG_IO
);
405 if (SymbolicLinkList
)
407 ExFreePool(SymbolicLinkList
);
416 IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
417 IN BOOLEAN SingleDisk
,
418 OUT PBOOLEAN FoundBoot
)
424 PLIST_ENTRY NextEntry
;
425 PFILE_OBJECT FileObject
;
426 DISK_GEOMETRY DiskGeometry
;
427 PDEVICE_OBJECT DeviceObject
;
428 LARGE_INTEGER StartingOffset
;
429 PULONG PartitionBuffer
= NULL
;
430 IO_STATUS_BLOCK IoStatusBlock
;
431 CHAR Buffer
[128], ArcBuffer
[128];
432 BOOLEAN NotEnabledPresent
= FALSE
;
433 STORAGE_DEVICE_NUMBER DeviceNumber
;
434 PARC_DISK_SIGNATURE ArcDiskSignature
;
435 PWSTR SymbolicLinkList
, lSymbolicLinkList
;
436 PDRIVE_LAYOUT_INFORMATION_EX DriveLayout
= NULL
;
437 UNICODE_STRING DeviceStringW
, ArcNameStringW
, HalPathStringW
;
438 ULONG DiskNumber
, DiskCount
, CheckSum
, i
, Signature
, EnabledDisks
= 0;
439 PARC_DISK_INFORMATION ArcDiskInformation
= LoaderBlock
->ArcDiskInformation
;
440 ANSI_STRING ArcBootString
, ArcSystemString
, DeviceStringA
, ArcNameStringA
, HalPathStringA
;
442 /* Initialise device number */
443 DeviceNumber
.DeviceNumber
= ULONG_MAX
;
444 /* Get all the disks present in the system */
445 DiskCount
= IoGetConfigurationInformation()->DiskCount
;
447 /* Get enabled disks and check if result matches */
448 Status
= IopFetchConfigurationInformation(&SymbolicLinkList
,
449 GUID_DEVINTERFACE_DISK
,
452 if (!NT_SUCCESS(Status
))
454 NotEnabledPresent
= TRUE
;
457 /* Save symbolic link list address in order to free it after */
458 lSymbolicLinkList
= SymbolicLinkList
;
460 /* Build the boot strings */
461 RtlInitAnsiString(&ArcBootString
, LoaderBlock
->ArcBootDeviceName
);
462 RtlInitAnsiString(&ArcSystemString
, LoaderBlock
->ArcHalDeviceName
);
464 /* If we have more enabled disks, take that into account */
465 if (EnabledDisks
> DiskCount
)
467 DiskCount
= EnabledDisks
;
470 /* If we'll have to browse for none enabled disks, fix higher count */
471 if (NotEnabledPresent
&& !EnabledDisks
)
476 /* Finally, if in spite of all that work, we still don't have disks, leave */
482 /* Start browsing disks */
483 for (DiskNumber
= 0; DiskNumber
< DiskCount
; DiskNumber
++)
485 ASSERT(DriveLayout
== NULL
);
487 /* Check if we have an enabled disk */
488 if (lSymbolicLinkList
&& *lSymbolicLinkList
!= UNICODE_NULL
)
490 /* Create its device name using first symbolic link */
491 RtlInitUnicodeString(&DeviceStringW
, lSymbolicLinkList
);
492 /* Then, update symbolic links list */
493 lSymbolicLinkList
+= wcslen(lSymbolicLinkList
) + (sizeof(UNICODE_NULL
) / sizeof(WCHAR
));
495 /* Get its associated device object and file object */
496 Status
= IoGetDeviceObjectPointer(&DeviceStringW
,
497 FILE_READ_ATTRIBUTES
,
500 if (NT_SUCCESS(Status
))
502 /* Now, we'll ask the device its device number */
503 Irp
= IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER
,
508 sizeof(DeviceNumber
),
512 /* Missing resources is a shame... No need to go farther */
515 ObDereferenceObject(FileObject
);
516 Status
= STATUS_INSUFFICIENT_RESOURCES
;
520 /* Call the driver, and wait for it if needed */
521 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
522 Status
= IoCallDriver(DeviceObject
, Irp
);
523 if (Status
== STATUS_PENDING
)
525 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
526 Status
= IoStatusBlock
.Status
;
529 /* If we didn't get the appriopriate data, just skip that disk */
530 if (!NT_SUCCESS(Status
))
532 ObDereferenceObject(FileObject
);
537 /* End of enabled disks enumeration */
538 if (NotEnabledPresent
&& *lSymbolicLinkList
== UNICODE_NULL
)
540 /* No enabled disk worked, reset field */
541 if (DeviceNumber
.DeviceNumber
== ULONG_MAX
)
543 DeviceNumber
.DeviceNumber
= 0;
546 /* Update disk number to enable the following not enabled disks */
547 if (DeviceNumber
.DeviceNumber
> DiskNumber
)
549 DiskNumber
= DeviceNumber
.DeviceNumber
;
552 /* Increase a bit more */
553 DiskCount
= DiskNumber
+ 20;
558 /* Create device name for the disk */
559 sprintf(Buffer
, "\\Device\\Harddisk%lu\\Partition0", DiskNumber
);
560 RtlInitAnsiString(&DeviceStringA
, Buffer
);
561 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
562 if (!NT_SUCCESS(Status
))
567 /* Get its device object */
568 Status
= IoGetDeviceObjectPointer(&DeviceStringW
,
569 FILE_READ_ATTRIBUTES
,
573 RtlFreeUnicodeString(&DeviceStringW
);
574 /* This is a security measure, to ensure DiskNumber will be used */
575 DeviceNumber
.DeviceNumber
= ULONG_MAX
;
578 /* Something failed somewhere earlier, just skip the disk */
579 if (!NT_SUCCESS(Status
))
584 /* Let's ask the disk for its geometry */
585 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
590 sizeof(DiskGeometry
),
594 /* Missing resources is a shame... No need to go farther */
597 ObDereferenceObject(FileObject
);
598 Status
= STATUS_INSUFFICIENT_RESOURCES
;
602 /* Call the driver, and wait for it if needed */
603 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
604 Status
= IoCallDriver(DeviceObject
, Irp
);
605 if (Status
== STATUS_PENDING
)
607 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
608 Status
= IoStatusBlock
.Status
;
610 /* Failure, skip disk */
611 if (!NT_SUCCESS(Status
))
613 ObDereferenceObject(FileObject
);
617 /* Read the partition table */
618 Status
= IoReadPartitionTableEx(DeviceObject
,
620 if (!NT_SUCCESS(Status
))
622 ObDereferenceObject(FileObject
);
626 /* Ensure we have at least 512 bytes per sector */
627 if (DiskGeometry
.BytesPerSector
< 512)
629 DiskGeometry
.BytesPerSector
= 512;
632 /* Check MBR type against EZ Drive type */
633 StartingOffset
.QuadPart
= 0;
634 HalExamineMBR(DeviceObject
, DiskGeometry
.BytesPerSector
, 0x55, &Data
);
637 /* If MBR is of the EZ Drive type, we'll read after it */
638 StartingOffset
.QuadPart
= DiskGeometry
.BytesPerSector
;
642 /* Allocate for reading enough data for checksum */
643 PartitionBuffer
= ExAllocatePoolWithTag(NonPagedPoolCacheAligned
, DiskGeometry
.BytesPerSector
, TAG_IO
);
644 if (!PartitionBuffer
)
646 ObDereferenceObject(FileObject
);
647 Status
= STATUS_INSUFFICIENT_RESOURCES
;
651 /* Read the first sector for computing checksum */
652 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
655 DiskGeometry
.BytesPerSector
,
661 ExFreePoolWithTag(PartitionBuffer
, TAG_IO
);
662 ObDereferenceObject(FileObject
);
663 Status
= STATUS_INSUFFICIENT_RESOURCES
;
667 /* Call the driver to perform reading */
668 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
669 Status
= IoCallDriver(DeviceObject
, Irp
);
670 if (Status
== STATUS_PENDING
)
672 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
673 Status
= IoStatusBlock
.Status
;
676 /* If reading succeeded, calculate checksum by adding data */
677 if (NT_SUCCESS(Status
))
679 for (i
= 0, CheckSum
= 0; i
< 512 / sizeof(ULONG
); i
++)
681 CheckSum
+= PartitionBuffer
[i
];
685 /* Release now unnecessary resources */
686 ExFreePoolWithTag(PartitionBuffer
, TAG_IO
);
687 ObDereferenceObject(FileObject
);
689 /* If we failed, release drive layout before going to next disk */
690 if (!NT_SUCCESS(Status
))
692 ExFreePool(DriveLayout
);
697 /* Browse each ARC disk */
698 for (NextEntry
= ArcDiskInformation
->DiskSignatureListHead
.Flink
;
699 NextEntry
!= &ArcDiskInformation
->DiskSignatureListHead
;
700 NextEntry
= NextEntry
->Flink
)
702 ArcDiskSignature
= CONTAINING_RECORD(NextEntry
,
706 /* If they match, i.e.
707 * - There's only one disk for both BIOS and detected/enabled
708 * - Signatures are matching
709 * - Checksums are matching
712 if (((SingleDisk
&& DiskCount
== 1) ||
713 (IopVerifyDiskSignature(DriveLayout
, ArcDiskSignature
, &Signature
) &&
714 (ArcDiskSignature
->CheckSum
+ CheckSum
== 0))) &&
715 (DriveLayout
->PartitionStyle
== PARTITION_STYLE_MBR
))
717 /* Create device name */
718 sprintf(Buffer
, "\\Device\\Harddisk%lu\\Partition0", (DeviceNumber
.DeviceNumber
!= ULONG_MAX
) ? DeviceNumber
.DeviceNumber
: DiskNumber
);
719 RtlInitAnsiString(&DeviceStringA
, Buffer
);
720 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
721 if (!NT_SUCCESS(Status
))
726 /* Create ARC name */
727 sprintf(ArcBuffer
, "\\ArcName\\%s", ArcDiskSignature
->ArcName
);
728 RtlInitAnsiString(&ArcNameStringA
, ArcBuffer
);
729 Status
= RtlAnsiStringToUnicodeString(&ArcNameStringW
, &ArcNameStringA
, TRUE
);
730 if (!NT_SUCCESS(Status
))
732 RtlFreeUnicodeString(&DeviceStringW
);
737 IoAssignArcName(&ArcNameStringW
, &DeviceStringW
);
739 /* And release resources */
740 RtlFreeUnicodeString(&ArcNameStringW
);
741 RtlFreeUnicodeString(&DeviceStringW
);
743 /* Now, browse for every partition */
744 for (i
= 1; i
<= DriveLayout
->PartitionCount
; i
++)
746 /* Create device name */
747 sprintf(Buffer
, "\\Device\\Harddisk%lu\\Partition%lu", (DeviceNumber
.DeviceNumber
!= ULONG_MAX
) ? DeviceNumber
.DeviceNumber
: DiskNumber
, i
);
748 RtlInitAnsiString(&DeviceStringA
, Buffer
);
749 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
750 if (!NT_SUCCESS(Status
))
755 /* Create partial ARC name */
756 sprintf(ArcBuffer
, "%spartition(%lu)", ArcDiskSignature
->ArcName
, i
);
757 RtlInitAnsiString(&ArcNameStringA
, ArcBuffer
);
759 /* Is that boot device? */
760 if (RtlEqualString(&ArcNameStringA
, &ArcBootString
, TRUE
))
762 DPRINT("Found boot device\n");
766 /* Is that system partition? */
767 if (RtlEqualString(&ArcNameStringA
, &ArcSystemString
, TRUE
))
769 /* Create HAL path name */
770 RtlInitAnsiString(&HalPathStringA
, LoaderBlock
->NtHalPathName
);
771 Status
= RtlAnsiStringToUnicodeString(&HalPathStringW
, &HalPathStringA
, TRUE
);
772 if (!NT_SUCCESS(Status
))
774 RtlFreeUnicodeString(&DeviceStringW
);
778 /* Then store those information to registry */
779 IopStoreSystemPartitionInformation(&DeviceStringW
, &HalPathStringW
);
780 RtlFreeUnicodeString(&HalPathStringW
);
783 /* Create complete ARC name */
784 sprintf(ArcBuffer
, "\\ArcName\\%spartition(%lu)", ArcDiskSignature
->ArcName
, i
);
785 RtlInitAnsiString(&ArcNameStringA
, ArcBuffer
);
786 Status
= RtlAnsiStringToUnicodeString(&ArcNameStringW
, &ArcNameStringA
, TRUE
);
787 if (!NT_SUCCESS(Status
))
789 RtlFreeUnicodeString(&DeviceStringW
);
793 /* Link device name & ARC name */
794 IoAssignArcName(&ArcNameStringW
, &DeviceStringW
);
796 /* Release strings */
797 RtlFreeUnicodeString(&ArcNameStringW
);
798 RtlFreeUnicodeString(&DeviceStringW
);
803 /* Debugging feedback: Warn in case there's a valid partition,
804 * a matching signature, BUT a non-matching checksum: this can
805 * be the sign of a duplicate signature, or even worse a virus
806 * played with the partition table. */
807 if (ArcDiskSignature
->ValidPartitionTable
&&
808 (ArcDiskSignature
->Signature
== Signature
) &&
809 (ArcDiskSignature
->CheckSum
+ CheckSum
!= 0))
811 DPRINT("Be careful, you have a duplicate disk signature, or a virus altered your MBR!\n");
816 /* Finally, release drive layout */
817 ExFreePool(DriveLayout
);
821 Status
= STATUS_SUCCESS
;
826 ExFreePool(DriveLayout
);
829 if (SymbolicLinkList
)
831 ExFreePool(SymbolicLinkList
);
840 IopReassignSystemRoot(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
841 OUT PANSI_STRING NtBootPath
)
843 OBJECT_ATTRIBUTES ObjectAttributes
;
845 CHAR Buffer
[256], AnsiBuffer
[256];
846 WCHAR ArcNameBuffer
[64];
847 ANSI_STRING TargetString
, ArcString
, TempString
;
848 UNICODE_STRING LinkName
, TargetName
, ArcName
;
851 /* Create the Unicode name for the current ARC boot device */
852 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
853 RtlInitAnsiString(&TargetString
, Buffer
);
854 Status
= RtlAnsiStringToUnicodeString(&TargetName
, &TargetString
, TRUE
);
855 if (!NT_SUCCESS(Status
)) return FALSE
;
857 /* Initialize the attributes and open the link */
858 InitializeObjectAttributes(&ObjectAttributes
,
860 OBJ_CASE_INSENSITIVE
,
863 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
864 SYMBOLIC_LINK_ALL_ACCESS
,
866 if (!NT_SUCCESS(Status
))
868 /* We failed, free the string */
869 RtlFreeUnicodeString(&TargetName
);
873 /* Query the current \\SystemRoot */
874 ArcName
.Buffer
= ArcNameBuffer
;
876 ArcName
.MaximumLength
= sizeof(ArcNameBuffer
);
877 Status
= NtQuerySymbolicLinkObject(LinkHandle
, &ArcName
, NULL
);
878 if (!NT_SUCCESS(Status
))
880 /* We failed, free the string */
881 RtlFreeUnicodeString(&TargetName
);
885 /* Convert it to Ansi */
886 ArcString
.Buffer
= AnsiBuffer
;
887 ArcString
.Length
= 0;
888 ArcString
.MaximumLength
= sizeof(AnsiBuffer
);
889 Status
= RtlUnicodeStringToAnsiString(&ArcString
, &ArcName
, FALSE
);
890 AnsiBuffer
[ArcString
.Length
] = ANSI_NULL
;
892 /* Close the link handle and free the name */
893 ObCloseHandle(LinkHandle
, KernelMode
);
894 RtlFreeUnicodeString(&TargetName
);
896 /* Setup the system root name again */
897 RtlInitAnsiString(&TempString
, "\\SystemRoot");
898 Status
= RtlAnsiStringToUnicodeString(&LinkName
, &TempString
, TRUE
);
899 if (!NT_SUCCESS(Status
)) return FALSE
;
901 /* Open the symbolic link for it */
902 InitializeObjectAttributes(&ObjectAttributes
,
904 OBJ_CASE_INSENSITIVE
,
907 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
908 SYMBOLIC_LINK_ALL_ACCESS
,
910 if (!NT_SUCCESS(Status
)) return FALSE
;
913 NtMakeTemporaryObject(LinkHandle
);
914 ObCloseHandle(LinkHandle
, KernelMode
);
916 /* Now create the new name for it */
917 sprintf(Buffer
, "%s%s", ArcString
.Buffer
, LoaderBlock
->NtBootPathName
);
919 /* Copy it into the passed parameter and null-terminate it */
920 RtlCopyString(NtBootPath
, &ArcString
);
921 Buffer
[strlen(Buffer
) - 1] = ANSI_NULL
;
923 /* Setup the Unicode-name for the new symbolic link value */
924 RtlInitAnsiString(&TargetString
, Buffer
);
925 InitializeObjectAttributes(&ObjectAttributes
,
927 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
930 Status
= RtlAnsiStringToUnicodeString(&ArcName
, &TargetString
, TRUE
);
931 if (!NT_SUCCESS(Status
)) return FALSE
;
934 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
935 SYMBOLIC_LINK_ALL_ACCESS
,
939 /* Free all the strings and close the handle and return success */
940 RtlFreeUnicodeString(&ArcName
);
941 RtlFreeUnicodeString(&LinkName
);
942 ObCloseHandle(LinkHandle
, KernelMode
);
948 IopVerifyDiskSignature(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout
,
949 IN PARC_DISK_SIGNATURE ArcDiskSignature
,
950 OUT PULONG Signature
)
952 /* First condition: having a valid partition table */
953 if (!ArcDiskSignature
->ValidPartitionTable
)
958 /* If that partition table is the MBR */
959 if (DriveLayout
->PartitionStyle
== PARTITION_STYLE_MBR
)
961 /* Then check MBR signature */
962 if (DriveLayout
->Mbr
.Signature
== ArcDiskSignature
->Signature
)
967 *Signature
= DriveLayout
->Mbr
.Signature
;
973 /* If that partition table is the GPT */
974 else if (DriveLayout
->PartitionStyle
== PARTITION_STYLE_GPT
)
976 /* Check we are using GPT and compare GUID */
977 if (ArcDiskSignature
->IsGpt
&&
978 (((PULONG
)ArcDiskSignature
->GptSignature
)[0] == DriveLayout
->Gpt
.DiskId
.Data1
&&
979 ((PUSHORT
)ArcDiskSignature
->GptSignature
)[2] == DriveLayout
->Gpt
.DiskId
.Data2
&&
980 ((PUSHORT
)ArcDiskSignature
->GptSignature
)[3] == DriveLayout
->Gpt
.DiskId
.Data3
&&
981 ((PULONGLONG
)ArcDiskSignature
->GptSignature
)[1] == ((PULONGLONG
)DriveLayout
->Gpt
.DiskId
.Data4
)[0]))
983 /* There's no signature to give, so we just zero output */
992 /* If we fall here, it means that something went wrong, so return that */