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
;
21 extern BOOLEAN IoRemoteBootClient
;
23 /* FUNCTIONS *****************************************************************/
28 IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock
34 IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
35 IN BOOLEAN SingleDisk
,
42 IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
48 BOOLEAN FoundBoot
= FALSE
;
49 UNICODE_STRING SystemDevice
, LoaderPathNameW
, BootDeviceName
;
50 PARC_DISK_INFORMATION ArcDiskInfo
= LoaderBlock
->ArcDiskInformation
;
51 ANSI_STRING ArcSystemString
, ArcString
, LanmanRedirector
, LoaderPathNameA
;
53 /* Check if we only have one disk on the machine */
54 SingleDisk
= ArcDiskInfo
->DiskSignatureListHead
.Flink
->Flink
==
55 (&ArcDiskInfo
->DiskSignatureListHead
);
57 /* Create the global HAL partition name */
58 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcHalDeviceName
);
59 RtlInitAnsiString(&ArcString
, Buffer
);
60 RtlAnsiStringToUnicodeString(&IoArcHalDeviceName
, &ArcString
, TRUE
);
62 /* Create the global system partition name */
63 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
64 RtlInitAnsiString(&ArcString
, Buffer
);
65 RtlAnsiStringToUnicodeString(&IoArcBootDeviceName
, &ArcString
, TRUE
);
67 /* Allocate memory for the string */
68 Length
= strlen(LoaderBlock
->ArcBootDeviceName
) + sizeof(ANSI_NULL
);
69 IoLoaderArcBootDeviceName
= ExAllocatePoolWithTag(PagedPool
,
72 if (IoLoaderArcBootDeviceName
)
75 RtlCopyMemory(IoLoaderArcBootDeviceName
,
76 LoaderBlock
->ArcBootDeviceName
,
80 /* Check if we only found a disk, but we're booting from CD-ROM */
81 if ((SingleDisk
) && strstr(LoaderBlock
->ArcBootDeviceName
, "cdrom"))
83 /* Then disable single-disk mode, since there's a CD drive out there */
87 /* Build the boot strings */
88 RtlInitAnsiString(&ArcSystemString
, LoaderBlock
->ArcHalDeviceName
);
90 /* If we are doing remote booting */
91 if (IoRemoteBootClient
)
93 /* Yes, we have found boot device */
96 /* Get NT device name */
97 RtlInitAnsiString(&LanmanRedirector
, "\\Device\\LanmanRedirector");
98 Status
= RtlAnsiStringToUnicodeString(&SystemDevice
, &LanmanRedirector
, TRUE
);
99 if (!NT_SUCCESS(Status
))
104 /* Get ARC booting device name (in net(0) something) */
105 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
106 RtlInitAnsiString(&ArcString
, Buffer
);
107 Status
= RtlAnsiStringToUnicodeString(&BootDeviceName
, &ArcString
, TRUE
);
108 if (NT_SUCCESS(Status
))
110 /* Map ARC to NT name */
111 IoAssignArcName(&BootDeviceName
, &SystemDevice
);
112 RtlFreeUnicodeString(&BootDeviceName
);
114 /* Now, get loader path name */
115 RtlInitAnsiString(&LoaderPathNameA
, LoaderBlock
->NtHalPathName
);
116 Status
= RtlAnsiStringToUnicodeString(&LoaderPathNameW
, &LoaderPathNameA
, TRUE
);
117 if (!NT_SUCCESS(Status
))
119 RtlFreeUnicodeString(&SystemDevice
);
123 /* And set it has system partition */
124 IopStoreSystemPartitionInformation(&SystemDevice
, &LoaderPathNameW
);
127 RtlFreeUnicodeString(&SystemDevice
);
129 /* Don't quit here, even if everything went fine!
130 * We need IopCreateArcNamesDisk to properly map
131 * devices with symlinks.
132 * It will return success if the mapping process went fine
133 * even if it didn't find boot device.
134 * It won't reset boot device finding status as well.
138 /* Loop every disk and try to find boot disk */
139 Status
= IopCreateArcNamesDisk(LoaderBlock
, SingleDisk
, &FoundBoot
);
140 /* If it succeed but we didn't find boot device, try to browse Cds */
141 if (NT_SUCCESS(Status
) && !FoundBoot
)
143 Status
= IopCreateArcNamesCd(LoaderBlock
);
153 IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
158 PLIST_ENTRY NextEntry
;
159 PFILE_OBJECT FileObject
;
160 PDEVICE_OBJECT DeviceObject
;
161 LARGE_INTEGER StartingOffset
;
162 IO_STATUS_BLOCK IoStatusBlock
;
163 PULONG PartitionBuffer
= NULL
;
164 CHAR Buffer
[128], ArcBuffer
[128];
165 BOOLEAN NotEnabledPresent
= FALSE
;
166 STORAGE_DEVICE_NUMBER DeviceNumber
;
167 ANSI_STRING DeviceStringA
, ArcNameStringA
;
168 PWSTR SymbolicLinkList
, lSymbolicLinkList
;
169 PARC_DISK_SIGNATURE ArcDiskSignature
= NULL
;
170 UNICODE_STRING DeviceStringW
, ArcNameStringW
;
171 ULONG DiskNumber
, CdRomCount
, CheckSum
, i
, EnabledDisks
= 0;
172 PARC_DISK_INFORMATION ArcDiskInformation
= LoaderBlock
->ArcDiskInformation
;
174 /* Get all the Cds present in the system */
175 CdRomCount
= IoGetConfigurationInformation()->CdRomCount
;
177 /* Get enabled Cds and check if result matches
178 * For the record, enabled Cds (or even disk) are Cds/disks
179 * that have been successfully handled by MountMgr driver
180 * and that already own their device name. This is the "new" way
181 * to handle them, that came with NT5.
182 * Currently, Windows 2003 provides an arc names creation based
183 * on both enabled drives and not enabled drives (lack from
185 * Given the current ReactOS state, that's good for us.
186 * To sum up, this is NOT a hack or whatsoever.
188 Status
= IopFetchConfigurationInformation(&SymbolicLinkList
,
189 GUID_DEVINTERFACE_CDROM
,
192 if (!NT_SUCCESS(Status
))
194 NotEnabledPresent
= TRUE
;
196 /* Save symbolic link list address in order to free it after */
197 lSymbolicLinkList
= SymbolicLinkList
;
198 /* For the moment, we won't fail */
199 Status
= STATUS_SUCCESS
;
201 /* Browse all the ARC devices trying to find the one matching boot device */
202 for (NextEntry
= ArcDiskInformation
->DiskSignatureListHead
.Flink
;
203 NextEntry
!= &ArcDiskInformation
->DiskSignatureListHead
;
204 NextEntry
= NextEntry
->Flink
)
206 ArcDiskSignature
= CONTAINING_RECORD(NextEntry
,
210 if (strcmp(LoaderBlock
->ArcBootDeviceName
, ArcDiskSignature
->ArcName
) == 0)
215 ArcDiskSignature
= NULL
;
218 /* Not found... Not booting from a Cd */
219 if (!ArcDiskSignature
)
221 DPRINT("Failed finding a cd that could match current boot device\n");
225 /* Allocate needed space for reading Cd */
226 PartitionBuffer
= ExAllocatePoolWithTag(NonPagedPoolCacheAligned
, 2048, TAG_IO
);
227 if (!PartitionBuffer
)
229 DPRINT("Failed allocating resources!\n");
230 /* Here, we fail, BUT we return success, some Microsoft joke */
234 /* If we have more enabled Cds, take that into account */
235 if (EnabledDisks
> CdRomCount
)
237 CdRomCount
= EnabledDisks
;
240 /* If we'll have to browse for none enabled Cds, fix higher count */
241 if (NotEnabledPresent
&& !EnabledDisks
)
246 /* Finally, if in spite of all that work, we still don't have Cds, leave */
252 /* Start browsing Cds */
253 for (DiskNumber
= 0, EnabledDisks
= 0; DiskNumber
< CdRomCount
; DiskNumber
++)
255 /* Check if we have an enabled disk */
256 if (SymbolicLinkList
&& *SymbolicLinkList
!= UNICODE_NULL
)
258 /* Create its device name using first symbolic link */
259 RtlInitUnicodeString(&DeviceStringW
, lSymbolicLinkList
);
260 /* Then, update symbolic links list */
261 lSymbolicLinkList
+= wcslen(lSymbolicLinkList
) + (sizeof(UNICODE_NULL
) / sizeof(WCHAR
));
263 /* Get its associated device object and file object */
264 Status
= IoGetDeviceObjectPointer(&DeviceStringW
,
265 FILE_READ_ATTRIBUTES
,
268 /* Failure? Good bye! */
269 if (!NT_SUCCESS(Status
))
274 /* Now, we'll ask the device its device number */
275 Irp
= IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER
,
280 sizeof(STORAGE_DEVICE_NUMBER
),
284 /* Failure? Good bye! */
287 /* Dereference file object before leaving */
288 ObDereferenceObject(FileObject
);
289 Status
= STATUS_INSUFFICIENT_RESOURCES
;
293 /* Call the driver, and wait for it if needed */
294 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
295 Status
= IoCallDriver(DeviceObject
, Irp
);
296 if (Status
== STATUS_PENDING
)
298 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
299 Status
= IoStatusBlock
.Status
;
301 if (!NT_SUCCESS(Status
))
303 ObDereferenceObject(FileObject
);
307 /* Finally, build proper device name */
308 sprintf(Buffer
, "\\Device\\CdRom%lu", DeviceNumber
.DeviceNumber
);
309 RtlInitAnsiString(&DeviceStringA
, Buffer
);
310 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
311 if (!NT_SUCCESS(Status
))
313 ObDereferenceObject(FileObject
);
319 /* Create device name for the cd */
320 sprintf(Buffer
, "\\Device\\CdRom%lu", EnabledDisks
++);
321 RtlInitAnsiString(&DeviceStringA
, Buffer
);
322 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
323 if (!NT_SUCCESS(Status
))
328 /* Get its device object */
329 Status
= IoGetDeviceObjectPointer(&DeviceStringW
,
330 FILE_READ_ATTRIBUTES
,
333 if (!NT_SUCCESS(Status
))
335 RtlFreeUnicodeString(&DeviceStringW
);
340 /* Initiate data for reading cd and compute checksum */
341 StartingOffset
.QuadPart
= 0x8000;
343 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
352 /* Call the driver, and wait for it if needed */
353 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
354 Status
= IoCallDriver(DeviceObject
, Irp
);
355 if (Status
== STATUS_PENDING
)
357 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
358 Status
= IoStatusBlock
.Status
;
361 /* Reading succeed, compute checksum by adding data, 2048 bytes checksum */
362 if (NT_SUCCESS(Status
))
364 for (i
= 0; i
< 2048 / sizeof(ULONG
); i
++)
366 CheckSum
+= PartitionBuffer
[i
];
371 /* Dereference file object */
372 ObDereferenceObject(FileObject
);
374 /* If checksums are matching, we have the proper cd */
375 if (CheckSum
+ ArcDiskSignature
->CheckSum
== 0)
377 /* Create ARC name */
378 sprintf(ArcBuffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
379 RtlInitAnsiString(&ArcNameStringA
, ArcBuffer
);
380 Status
= RtlAnsiStringToUnicodeString(&ArcNameStringW
, &ArcNameStringA
, TRUE
);
381 if (NT_SUCCESS(Status
))
383 /* Create symbolic link */
384 IoAssignArcName(&ArcNameStringW
, &DeviceStringW
);
385 RtlFreeUnicodeString(&ArcNameStringW
);
386 DPRINT1("Boot device found\n");
389 /* And quit, whatever happens */
390 RtlFreeUnicodeString(&DeviceStringW
);
394 /* Free string before trying another disk */
395 RtlFreeUnicodeString(&DeviceStringW
);
401 ExFreePoolWithTag(PartitionBuffer
, TAG_IO
);
404 if (SymbolicLinkList
)
406 ExFreePool(SymbolicLinkList
);
415 IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
416 IN BOOLEAN SingleDisk
,
417 IN PBOOLEAN FoundBoot
)
423 PLIST_ENTRY NextEntry
;
424 PFILE_OBJECT FileObject
;
425 DISK_GEOMETRY DiskGeometry
;
426 PDEVICE_OBJECT DeviceObject
;
427 LARGE_INTEGER StartingOffset
;
428 PULONG PartitionBuffer
= NULL
;
429 IO_STATUS_BLOCK IoStatusBlock
;
430 CHAR Buffer
[128], ArcBuffer
[128];
431 BOOLEAN NotEnabledPresent
= FALSE
;
432 STORAGE_DEVICE_NUMBER DeviceNumber
;
433 PARC_DISK_SIGNATURE ArcDiskSignature
;
434 PWSTR SymbolicLinkList
, lSymbolicLinkList
;
435 PDRIVE_LAYOUT_INFORMATION_EX DriveLayout
= NULL
;
436 UNICODE_STRING DeviceStringW
, ArcNameStringW
, HalPathStringW
;
437 ULONG DiskNumber
, DiskCount
, CheckSum
, i
, Signature
, EnabledDisks
= 0;
438 PARC_DISK_INFORMATION ArcDiskInformation
= LoaderBlock
->ArcDiskInformation
;
439 ANSI_STRING ArcBootString
, ArcSystemString
, DeviceStringA
, ArcNameStringA
, HalPathStringA
;
441 /* Initialise device number */
442 DeviceNumber
.DeviceNumber
= ULONG_MAX
;
443 /* Get all the disks present in the system */
444 DiskCount
= IoGetConfigurationInformation()->DiskCount
;
446 /* Get enabled disks and check if result matches */
447 Status
= IopFetchConfigurationInformation(&SymbolicLinkList
,
448 GUID_DEVINTERFACE_DISK
,
451 if (!NT_SUCCESS(Status
))
453 NotEnabledPresent
= TRUE
;
456 /* Save symbolic link list address in order to free it after */
457 lSymbolicLinkList
= SymbolicLinkList
;
459 /* Build the boot strings */
460 RtlInitAnsiString(&ArcBootString
, LoaderBlock
->ArcBootDeviceName
);
461 RtlInitAnsiString(&ArcSystemString
, LoaderBlock
->ArcHalDeviceName
);
463 /* If we have more enabled disks, take that into account */
464 if (EnabledDisks
> DiskCount
)
466 DiskCount
= EnabledDisks
;
469 /* If we'll have to browse for none enabled disks, fix higher count */
470 if (NotEnabledPresent
&& !EnabledDisks
)
475 /* Finally, if in spite of all that work, we still don't have disks, leave */
481 /* Start browsing disks */
482 for (DiskNumber
= 0; DiskNumber
< DiskCount
; DiskNumber
++)
484 /* Check if we have an enabled disk */
485 if (lSymbolicLinkList
&& *lSymbolicLinkList
!= UNICODE_NULL
)
487 /* Create its device name using first symbolic link */
488 RtlInitUnicodeString(&DeviceStringW
, lSymbolicLinkList
);
489 /* Then, update symbolic links list */
490 lSymbolicLinkList
+= wcslen(lSymbolicLinkList
) + (sizeof(UNICODE_NULL
) / sizeof(WCHAR
));
492 /* Get its associated device object and file object */
493 Status
= IoGetDeviceObjectPointer(&DeviceStringW
,
494 FILE_READ_ATTRIBUTES
,
497 if (NT_SUCCESS(Status
))
499 /* Now, we'll ask the device its device number */
500 Irp
= IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER
,
505 sizeof(STORAGE_DEVICE_NUMBER
),
509 /* Missing resources is a shame... No need to go farther */
512 ObDereferenceObject(FileObject
);
513 Status
= STATUS_INSUFFICIENT_RESOURCES
;
517 /* Call the driver, and wait for it if needed */
518 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
519 Status
= IoCallDriver(DeviceObject
, Irp
);
520 if (Status
== STATUS_PENDING
)
522 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
523 Status
= IoStatusBlock
.Status
;
526 /* If we didn't get the appriopriate data, just skip that disk */
527 if (!NT_SUCCESS(Status
))
529 ObDereferenceObject(FileObject
);
534 /* End of enabled disks enumeration */
535 if (NotEnabledPresent
&& *lSymbolicLinkList
== UNICODE_NULL
)
537 /* No enabled disk worked, reset field */
538 if (DeviceNumber
.DeviceNumber
== ULONG_MAX
)
540 DeviceNumber
.DeviceNumber
= 0;
543 /* Update disk number to enable the following not enabled disks */
544 if (DeviceNumber
.DeviceNumber
> DiskNumber
)
546 DiskNumber
= DeviceNumber
.DeviceNumber
;
549 /* Increase a bit more */
550 DiskCount
= DiskNumber
+ 20;
555 /* Create device name for the disk */
556 sprintf(Buffer
, "\\Device\\Harddisk%lu\\Partition0", DiskNumber
);
557 RtlInitAnsiString(&DeviceStringA
, Buffer
);
558 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
559 if (!NT_SUCCESS(Status
))
564 /* Get its device object */
565 Status
= IoGetDeviceObjectPointer(&DeviceStringW
,
566 FILE_READ_ATTRIBUTES
,
570 RtlFreeUnicodeString(&DeviceStringW
);
571 /* This is a security measure, to ensure DiskNumber will be used */
572 DeviceNumber
.DeviceNumber
= ULONG_MAX
;
575 /* Something failed somewhere earlier, just skip the disk */
576 if (!NT_SUCCESS(Status
))
581 /* Let's ask the disk for its geometry */
582 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
587 sizeof(DISK_GEOMETRY
),
591 /* Missing resources is a shame... No need to go farther */
594 ObDereferenceObject(FileObject
);
595 Status
= STATUS_INSUFFICIENT_RESOURCES
;
599 /* Call the driver, and wait for it if needed */
600 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
601 Status
= IoCallDriver(DeviceObject
, Irp
);
602 if (Status
== STATUS_PENDING
)
604 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
605 Status
= IoStatusBlock
.Status
;
607 /* Failure, skip disk */
608 if (!NT_SUCCESS(Status
))
610 ObDereferenceObject(FileObject
);
614 /* Read the partition table */
615 Status
= IoReadPartitionTableEx(DeviceObject
,
617 if (!NT_SUCCESS(Status
))
619 ObDereferenceObject(FileObject
);
623 /* Ensure we have at least 512 bytes per sector */
624 if (DiskGeometry
.BytesPerSector
< 512)
626 DiskGeometry
.BytesPerSector
= 512;
629 /* Check MBR type against EZ Drive type */
630 StartingOffset
.QuadPart
= 0;
631 HalExamineMBR(DeviceObject
, DiskGeometry
.BytesPerSector
, 0x55, &Data
);
634 /* If MBR is of the EZ Drive type, we'll read after it */
635 StartingOffset
.QuadPart
= DiskGeometry
.BytesPerSector
;
639 /* Allocate for reading enough data for checksum */
640 PartitionBuffer
= ExAllocatePoolWithTag(NonPagedPoolCacheAligned
, DiskGeometry
.BytesPerSector
, TAG_IO
);
641 if (!PartitionBuffer
)
643 ObDereferenceObject(FileObject
);
644 Status
= STATUS_INSUFFICIENT_RESOURCES
;
648 /* Read a sector for computing checksum */
649 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
652 DiskGeometry
.BytesPerSector
,
658 ObDereferenceObject(FileObject
);
659 Status
= STATUS_INSUFFICIENT_RESOURCES
;
663 /* Call the driver to perform reading */
664 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
665 Status
= IoCallDriver(DeviceObject
, Irp
);
666 if (Status
== STATUS_PENDING
)
668 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
669 Status
= IoStatusBlock
.Status
;
671 if (!NT_SUCCESS(Status
))
673 ExFreePool(DriveLayout
);
674 ExFreePoolWithTag(PartitionBuffer
, TAG_IO
);
675 ObDereferenceObject(FileObject
);
679 ObDereferenceObject(FileObject
);
681 /* Calculate checksum, that's an easy computation, just adds read data */
682 for (i
= 0, CheckSum
= 0; i
< 512 / sizeof(ULONG
) ; i
++)
684 CheckSum
+= PartitionBuffer
[i
];
687 /* Browse each ARC disk */
688 for (NextEntry
= ArcDiskInformation
->DiskSignatureListHead
.Flink
;
689 NextEntry
!= &ArcDiskInformation
->DiskSignatureListHead
;
690 NextEntry
= NextEntry
->Flink
)
692 ArcDiskSignature
= CONTAINING_RECORD(NextEntry
,
696 /* If they matches, ie
697 * - There's only one disk for both BIOS and detected/enabled
698 * - Signatures are matching
699 * - Checksums are matching
702 if (((SingleDisk
&& DiskCount
== 1) ||
703 (IopVerifyDiskSignature(DriveLayout
, ArcDiskSignature
, &Signature
) &&
704 (ArcDiskSignature
->CheckSum
+ CheckSum
== 0))) &&
705 (DriveLayout
->PartitionStyle
== PARTITION_STYLE_MBR
))
707 /* Create device name */
708 sprintf(Buffer
, "\\Device\\Harddisk%lu\\Partition0", (DeviceNumber
.DeviceNumber
!= ULONG_MAX
) ? DeviceNumber
.DeviceNumber
: DiskNumber
);
709 RtlInitAnsiString(&DeviceStringA
, Buffer
);
710 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
711 if (!NT_SUCCESS(Status
))
716 /* Create ARC name */
717 sprintf(ArcBuffer
, "\\ArcName\\%s", ArcDiskSignature
->ArcName
);
718 RtlInitAnsiString(&ArcNameStringA
, ArcBuffer
);
719 Status
= RtlAnsiStringToUnicodeString(&ArcNameStringW
, &ArcNameStringA
, TRUE
);
720 if (!NT_SUCCESS(Status
))
722 RtlFreeUnicodeString(&DeviceStringW
);
727 IoAssignArcName(&ArcNameStringW
, &DeviceStringW
);
729 /* And release resources */
730 RtlFreeUnicodeString(&ArcNameStringW
);
731 RtlFreeUnicodeString(&DeviceStringW
);
733 /* Now, browse for every partition */
734 for (i
= 1; i
<= DriveLayout
->PartitionCount
; i
++)
736 /* Create device name */
737 sprintf(Buffer
, "\\Device\\Harddisk%lu\\Partition%lu", (DeviceNumber
.DeviceNumber
!= ULONG_MAX
) ? DeviceNumber
.DeviceNumber
: DiskNumber
, i
);
738 RtlInitAnsiString(&DeviceStringA
, Buffer
);
739 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
740 if (!NT_SUCCESS(Status
))
745 /* Create partial ARC name */
746 sprintf(ArcBuffer
, "%spartition(%lu)", ArcDiskSignature
->ArcName
, i
);
747 RtlInitAnsiString(&ArcNameStringA
, ArcBuffer
);
749 /* Is that boot device? */
750 if (RtlEqualString(&ArcNameStringA
, &ArcBootString
, TRUE
))
752 DPRINT("Found boot device\n");
756 /* Is that system partition? */
757 if (RtlEqualString(&ArcNameStringA
, &ArcSystemString
, TRUE
))
759 /* Create HAL path name */
760 RtlInitAnsiString(&HalPathStringA
, LoaderBlock
->NtHalPathName
);
761 Status
= RtlAnsiStringToUnicodeString(&HalPathStringW
, &HalPathStringA
, TRUE
);
762 if (!NT_SUCCESS(Status
))
764 RtlFreeUnicodeString(&DeviceStringW
);
768 /* Then store those information to registry */
769 IopStoreSystemPartitionInformation(&DeviceStringW
, &HalPathStringW
);
770 RtlFreeUnicodeString(&HalPathStringW
);
773 /* Create complete ARC name */
774 sprintf(ArcBuffer
, "\\ArcName\\%spartition(%lu)", ArcDiskSignature
->ArcName
, i
);
775 RtlInitAnsiString(&ArcNameStringA
, ArcBuffer
);
776 Status
= RtlAnsiStringToUnicodeString(&ArcNameStringW
, &ArcNameStringA
, TRUE
);
777 if (!NT_SUCCESS(Status
))
779 RtlFreeUnicodeString(&DeviceStringW
);
783 /* Link device name & ARC name */
784 IoAssignArcName(&ArcNameStringW
, &DeviceStringW
);
786 /* Release strings */
787 RtlFreeUnicodeString(&ArcNameStringW
);
788 RtlFreeUnicodeString(&DeviceStringW
);
793 /* In case there's a valid partition, a matching signature,
794 BUT a none matching checksum, or there's a duplicate
795 signature, or even worse a virus played with partition
797 if (ArcDiskSignature
->Signature
== Signature
&&
798 (ArcDiskSignature
->CheckSum
+ CheckSum
!= 0) &&
799 ArcDiskSignature
->ValidPartitionTable
)
801 DPRINT("Be careful, or you have a duplicate disk signature, or a virus altered your MBR!\n");
806 /* Release memory before jumping to next item */
807 ExFreePool(DriveLayout
);
809 ExFreePoolWithTag(PartitionBuffer
, TAG_IO
);
810 PartitionBuffer
= NULL
;
813 Status
= STATUS_SUCCESS
;
816 if (SymbolicLinkList
)
818 ExFreePool(SymbolicLinkList
);
823 ExFreePool(DriveLayout
);
828 ExFreePoolWithTag(PartitionBuffer
, TAG_IO
);
837 IopReassignSystemRoot(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
838 OUT PANSI_STRING NtBootPath
)
840 OBJECT_ATTRIBUTES ObjectAttributes
;
842 CHAR Buffer
[256], AnsiBuffer
[256];
843 WCHAR ArcNameBuffer
[64];
844 ANSI_STRING TargetString
, ArcString
, TempString
;
845 UNICODE_STRING LinkName
, TargetName
, ArcName
;
848 /* Create the Unicode name for the current ARC boot device */
849 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
850 RtlInitAnsiString(&TargetString
, Buffer
);
851 Status
= RtlAnsiStringToUnicodeString(&TargetName
, &TargetString
, TRUE
);
852 if (!NT_SUCCESS(Status
)) return FALSE
;
854 /* Initialize the attributes and open the link */
855 InitializeObjectAttributes(&ObjectAttributes
,
857 OBJ_CASE_INSENSITIVE
,
860 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
861 SYMBOLIC_LINK_ALL_ACCESS
,
863 if (!NT_SUCCESS(Status
))
865 /* We failed, free the string */
866 RtlFreeUnicodeString(&TargetName
);
870 /* Query the current \\SystemRoot */
871 ArcName
.Buffer
= ArcNameBuffer
;
873 ArcName
.MaximumLength
= sizeof(ArcNameBuffer
);
874 Status
= NtQuerySymbolicLinkObject(LinkHandle
, &ArcName
, NULL
);
875 if (!NT_SUCCESS(Status
))
877 /* We failed, free the string */
878 RtlFreeUnicodeString(&TargetName
);
882 /* Convert it to Ansi */
883 ArcString
.Buffer
= AnsiBuffer
;
884 ArcString
.Length
= 0;
885 ArcString
.MaximumLength
= sizeof(AnsiBuffer
);
886 Status
= RtlUnicodeStringToAnsiString(&ArcString
, &ArcName
, FALSE
);
887 AnsiBuffer
[ArcString
.Length
] = ANSI_NULL
;
889 /* Close the link handle and free the name */
890 ObCloseHandle(LinkHandle
, KernelMode
);
891 RtlFreeUnicodeString(&TargetName
);
893 /* Setup the system root name again */
894 RtlInitAnsiString(&TempString
, "\\SystemRoot");
895 Status
= RtlAnsiStringToUnicodeString(&LinkName
, &TempString
, TRUE
);
896 if (!NT_SUCCESS(Status
)) return FALSE
;
898 /* Open the symbolic link for it */
899 InitializeObjectAttributes(&ObjectAttributes
,
901 OBJ_CASE_INSENSITIVE
,
904 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
905 SYMBOLIC_LINK_ALL_ACCESS
,
907 if (!NT_SUCCESS(Status
)) return FALSE
;
910 NtMakeTemporaryObject(LinkHandle
);
911 ObCloseHandle(LinkHandle
, KernelMode
);
913 /* Now create the new name for it */
914 sprintf(Buffer
, "%s%s", ArcString
.Buffer
, LoaderBlock
->NtBootPathName
);
916 /* Copy it into the passed parameter and null-terminate it */
917 RtlCopyString(NtBootPath
, &ArcString
);
918 Buffer
[strlen(Buffer
) - 1] = ANSI_NULL
;
920 /* Setup the Unicode-name for the new symbolic link value */
921 RtlInitAnsiString(&TargetString
, Buffer
);
922 InitializeObjectAttributes(&ObjectAttributes
,
924 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
927 Status
= RtlAnsiStringToUnicodeString(&ArcName
, &TargetString
, TRUE
);
928 if (!NT_SUCCESS(Status
)) return FALSE
;
931 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
932 SYMBOLIC_LINK_ALL_ACCESS
,
936 /* Free all the strings and close the handle and return success */
937 RtlFreeUnicodeString(&ArcName
);
938 RtlFreeUnicodeString(&LinkName
);
939 ObCloseHandle(LinkHandle
, KernelMode
);
945 IopVerifyDiskSignature(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout
,
946 IN PARC_DISK_SIGNATURE ArcDiskSignature
,
947 OUT PULONG Signature
)
949 /* First condition: having a valid partition table */
950 if (!ArcDiskSignature
->ValidPartitionTable
)
955 /* If that partition table is the MBR */
956 if (DriveLayout
->PartitionStyle
== PARTITION_STYLE_MBR
)
958 /* Then check MBR signature */
959 if (DriveLayout
->Mbr
.Signature
== ArcDiskSignature
->Signature
)
964 *Signature
= DriveLayout
->Mbr
.Signature
;
970 /* If that partition table is the GPT */
971 else if (DriveLayout
->PartitionStyle
== PARTITION_STYLE_GPT
)
973 /* Check we are using GPT and compare GUID */
974 if (ArcDiskSignature
->IsGpt
&&
975 (((PULONG
)ArcDiskSignature
->GptSignature
)[0] == DriveLayout
->Gpt
.DiskId
.Data1
&&
976 ((PUSHORT
)ArcDiskSignature
->GptSignature
)[2] == DriveLayout
->Gpt
.DiskId
.Data2
&&
977 ((PUSHORT
)ArcDiskSignature
->GptSignature
)[3] == DriveLayout
->Gpt
.DiskId
.Data3
&&
978 ((PULONGLONG
)ArcDiskSignature
->GptSignature
)[1] == ((PULONGLONG
)DriveLayout
->Gpt
.DiskId
.Data4
)[0]))
980 /* There's no signature to give, so we just zero output */
989 /* If we fall here, it means that something went wrong, so return that */