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
33 IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
34 IN BOOLEAN SingleDisk
,
41 IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
47 BOOLEAN FoundBoot
= FALSE
;
48 UNICODE_STRING SystemDevice
, LoaderPathNameW
, BootDeviceName
;
49 PARC_DISK_INFORMATION ArcDiskInfo
= LoaderBlock
->ArcDiskInformation
;
50 ANSI_STRING ArcSystemString
, ArcString
, LanmanRedirector
, LoaderPathNameA
;
52 /* Check if we only have one disk on the machine */
53 SingleDisk
= ArcDiskInfo
->DiskSignatureListHead
.Flink
->Flink
==
54 (&ArcDiskInfo
->DiskSignatureListHead
);
56 /* Create the global HAL partition name */
57 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcHalDeviceName
);
58 RtlInitAnsiString(&ArcString
, Buffer
);
59 RtlAnsiStringToUnicodeString(&IoArcHalDeviceName
, &ArcString
, TRUE
);
61 /* Create the global system partition name */
62 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
63 RtlInitAnsiString(&ArcString
, Buffer
);
64 RtlAnsiStringToUnicodeString(&IoArcBootDeviceName
, &ArcString
, TRUE
);
66 /* Allocate memory for the string */
67 Length
= strlen(LoaderBlock
->ArcBootDeviceName
) + sizeof(ANSI_NULL
);
68 IoLoaderArcBootDeviceName
= ExAllocatePoolWithTag(PagedPool
,
71 if (IoLoaderArcBootDeviceName
)
74 RtlCopyMemory(IoLoaderArcBootDeviceName
,
75 LoaderBlock
->ArcBootDeviceName
,
79 /* Check if we only found a disk, but we're booting from CD-ROM */
80 if ((SingleDisk
) && strstr(LoaderBlock
->ArcBootDeviceName
, "cdrom"))
82 /* Then disable single-disk mode, since there's a CD drive out there */
86 /* Build the boot strings */
87 RtlInitAnsiString(&ArcSystemString
, LoaderBlock
->ArcHalDeviceName
);
89 /* If we are doing remote booting */
90 if (IoRemoteBootClient
)
92 /* Yes, we have found boot device */
95 /* Get NT device name */
96 RtlInitAnsiString(&LanmanRedirector
, "\\Device\\LanmanRedirector");
97 Status
= RtlAnsiStringToUnicodeString(&SystemDevice
, &LanmanRedirector
, TRUE
);
98 if (!NT_SUCCESS(Status
))
103 /* Get ARC booting device name (in net(0) something) */
104 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
105 RtlInitAnsiString(&ArcString
, Buffer
);
106 Status
= RtlAnsiStringToUnicodeString(&BootDeviceName
, &ArcString
, TRUE
);
107 if (NT_SUCCESS(Status
))
109 /* Map ARC to NT name */
110 IoAssignArcName(&BootDeviceName
, &SystemDevice
);
111 RtlFreeUnicodeString(&BootDeviceName
);
113 /* Now, get loader path name */
114 RtlInitAnsiString(&LoaderPathNameA
, LoaderBlock
->NtHalPathName
);
115 Status
= RtlAnsiStringToUnicodeString(&LoaderPathNameW
, &LoaderPathNameA
, TRUE
);
116 if (!NT_SUCCESS(Status
))
118 RtlFreeUnicodeString(&SystemDevice
);
122 /* And set it has system partition */
123 IopStoreSystemPartitionInformation(&SystemDevice
, &LoaderPathNameW
);
126 RtlFreeUnicodeString(&SystemDevice
);
128 /* Don't quit here, even if everything went fine!
129 * We need IopCreateArcNamesDisk to properly map
130 * devices with symlinks.
131 * It will return success if the mapping process went fine
132 * even if it didn't find boot device.
133 * It won't reset boot device finding status as well.
137 /* Loop every disk and try to find boot disk */
138 Status
= IopCreateArcNamesDisk(LoaderBlock
, SingleDisk
, &FoundBoot
);
139 /* If it succeed but we didn't find boot device, try to browse Cds */
140 if (NT_SUCCESS(Status
) && !FoundBoot
)
142 Status
= IopCreateArcNamesCd(LoaderBlock
);
152 IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
157 PLIST_ENTRY NextEntry
;
158 PFILE_OBJECT FileObject
;
159 PDEVICE_OBJECT DeviceObject
;
160 LARGE_INTEGER StartingOffset
;
161 IO_STATUS_BLOCK IoStatusBlock
;
162 PULONG PartitionBuffer
= NULL
;
163 CHAR Buffer
[128], ArcBuffer
[128];
164 BOOLEAN NotEnabledPresent
= FALSE
;
165 STORAGE_DEVICE_NUMBER DeviceNumber
;
166 ANSI_STRING DeviceStringA
, ArcNameStringA
;
167 PWSTR SymbolicLinkList
, lSymbolicLinkList
;
168 PARC_DISK_SIGNATURE ArcDiskSignature
= NULL
;
169 UNICODE_STRING DeviceStringW
, ArcNameStringW
;
170 ULONG DiskNumber
, CdRomCount
, CheckSum
, i
, EnabledDisks
= 0;
171 PARC_DISK_INFORMATION ArcDiskInformation
= LoaderBlock
->ArcDiskInformation
;
173 /* Get all the Cds present in the system */
174 CdRomCount
= IoGetConfigurationInformation()->CdRomCount
;
176 /* Get enabled Cds and check if result matches
177 * For the record, enabled Cds (or even disk) are Cds/disks
178 * that have been successfully handled by MountMgr driver
179 * and that already own their device name. This is the "new" way
180 * to handle them, that came with NT5.
181 * Currently, Windows 2003 provides an arc names creation based
182 * on both enabled drives and not enabled drives (lack from
184 * Given the current ReactOS state, that's good for us.
185 * To sum up, this is NOT a hack or whatsoever.
187 Status
= IopFetchConfigurationInformation(&SymbolicLinkList
,
188 GUID_DEVINTERFACE_CDROM
,
191 if (!NT_SUCCESS(Status
))
193 NotEnabledPresent
= TRUE
;
195 /* Save symbolic link list address in order to free it after */
196 lSymbolicLinkList
= SymbolicLinkList
;
197 /* For the moment, we won't fail */
198 Status
= STATUS_SUCCESS
;
200 /* Browse all the ARC devices trying to find the one matching boot device */
201 for (NextEntry
= ArcDiskInformation
->DiskSignatureListHead
.Flink
;
202 NextEntry
!= &ArcDiskInformation
->DiskSignatureListHead
;
203 NextEntry
= NextEntry
->Flink
)
205 ArcDiskSignature
= CONTAINING_RECORD(NextEntry
,
209 if (strcmp(LoaderBlock
->ArcBootDeviceName
, ArcDiskSignature
->ArcName
) == 0)
214 ArcDiskSignature
= NULL
;
217 /* Not found... Not booting from a Cd */
218 if (!ArcDiskSignature
)
220 DPRINT("Failed finding a cd that could match current boot device\n");
224 /* Allocate needed space for reading Cd */
225 PartitionBuffer
= ExAllocatePoolWithTag(NonPagedPoolCacheAligned
, 2048, TAG_IO
);
226 if (!PartitionBuffer
)
228 DPRINT("Failed allocating resources!\n");
229 /* Here, we fail, BUT we return success, some Microsoft joke */
233 /* If we have more enabled Cds, take that into account */
234 if (EnabledDisks
> CdRomCount
)
236 CdRomCount
= EnabledDisks
;
239 /* If we'll have to browse for none enabled Cds, fix higher count */
240 if (NotEnabledPresent
&& !EnabledDisks
)
245 /* Finally, if in spite of all that work, we still don't have Cds, leave */
251 /* Start browsing Cds */
252 for (DiskNumber
= 0, EnabledDisks
= 0; DiskNumber
< CdRomCount
; DiskNumber
++)
254 /* Check if we have an enabled disk */
255 if (lSymbolicLinkList
&& *lSymbolicLinkList
!= UNICODE_NULL
)
257 /* Create its device name using first symbolic link */
258 RtlInitUnicodeString(&DeviceStringW
, lSymbolicLinkList
);
259 /* Then, update symbolic links list */
260 lSymbolicLinkList
+= wcslen(lSymbolicLinkList
) + (sizeof(UNICODE_NULL
) / sizeof(WCHAR
));
262 /* Get its associated device object and file object */
263 Status
= IoGetDeviceObjectPointer(&DeviceStringW
,
264 FILE_READ_ATTRIBUTES
,
267 /* Failure? Good bye! */
268 if (!NT_SUCCESS(Status
))
273 /* Now, we'll ask the device its device number */
274 Irp
= IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER
,
279 sizeof(STORAGE_DEVICE_NUMBER
),
283 /* Failure? Good bye! */
286 /* Dereference file object before leaving */
287 ObDereferenceObject(FileObject
);
288 Status
= STATUS_INSUFFICIENT_RESOURCES
;
292 /* Call the driver, and wait for it if needed */
293 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
294 Status
= IoCallDriver(DeviceObject
, Irp
);
295 if (Status
== STATUS_PENDING
)
297 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
298 Status
= IoStatusBlock
.Status
;
300 if (!NT_SUCCESS(Status
))
302 ObDereferenceObject(FileObject
);
306 /* Finally, build proper device name */
307 sprintf(Buffer
, "\\Device\\CdRom%lu", DeviceNumber
.DeviceNumber
);
308 RtlInitAnsiString(&DeviceStringA
, Buffer
);
309 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
310 if (!NT_SUCCESS(Status
))
312 ObDereferenceObject(FileObject
);
318 /* Create device name for the cd */
319 sprintf(Buffer
, "\\Device\\CdRom%lu", EnabledDisks
++);
320 RtlInitAnsiString(&DeviceStringA
, Buffer
);
321 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
322 if (!NT_SUCCESS(Status
))
327 /* Get its device object */
328 Status
= IoGetDeviceObjectPointer(&DeviceStringW
,
329 FILE_READ_ATTRIBUTES
,
332 if (!NT_SUCCESS(Status
))
334 RtlFreeUnicodeString(&DeviceStringW
);
339 /* Initiate data for reading cd and compute checksum */
340 StartingOffset
.QuadPart
= 0x8000;
342 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
351 /* Call the driver, and wait for it if needed */
352 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
353 Status
= IoCallDriver(DeviceObject
, Irp
);
354 if (Status
== STATUS_PENDING
)
356 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
357 Status
= IoStatusBlock
.Status
;
360 /* Reading succeed, compute checksum by adding data, 2048 bytes checksum */
361 if (NT_SUCCESS(Status
))
363 for (i
= 0; i
< 2048 / sizeof(ULONG
); i
++)
365 CheckSum
+= PartitionBuffer
[i
];
370 /* Dereference file object */
371 ObDereferenceObject(FileObject
);
373 /* If checksums are matching, we have the proper cd */
374 if (CheckSum
+ ArcDiskSignature
->CheckSum
== 0)
376 /* Create ARC name */
377 sprintf(ArcBuffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
378 RtlInitAnsiString(&ArcNameStringA
, ArcBuffer
);
379 Status
= RtlAnsiStringToUnicodeString(&ArcNameStringW
, &ArcNameStringA
, TRUE
);
380 if (NT_SUCCESS(Status
))
382 /* Create symbolic link */
383 IoAssignArcName(&ArcNameStringW
, &DeviceStringW
);
384 RtlFreeUnicodeString(&ArcNameStringW
);
385 DPRINT("Boot device found\n");
388 /* And quit, whatever happens */
389 RtlFreeUnicodeString(&DeviceStringW
);
393 /* Free string before trying another disk */
394 RtlFreeUnicodeString(&DeviceStringW
);
400 ExFreePoolWithTag(PartitionBuffer
, TAG_IO
);
403 if (SymbolicLinkList
)
405 ExFreePool(SymbolicLinkList
);
414 IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
415 IN BOOLEAN SingleDisk
,
416 IN PBOOLEAN FoundBoot
)
422 PLIST_ENTRY NextEntry
;
423 PFILE_OBJECT FileObject
;
424 DISK_GEOMETRY DiskGeometry
;
425 PDEVICE_OBJECT DeviceObject
;
426 LARGE_INTEGER StartingOffset
;
427 PULONG PartitionBuffer
= NULL
;
428 IO_STATUS_BLOCK IoStatusBlock
;
429 CHAR Buffer
[128], ArcBuffer
[128];
430 BOOLEAN NotEnabledPresent
= FALSE
;
431 STORAGE_DEVICE_NUMBER DeviceNumber
;
432 PARC_DISK_SIGNATURE ArcDiskSignature
;
433 PWSTR SymbolicLinkList
, lSymbolicLinkList
;
434 PDRIVE_LAYOUT_INFORMATION_EX DriveLayout
= NULL
;
435 UNICODE_STRING DeviceStringW
, ArcNameStringW
, HalPathStringW
;
436 ULONG DiskNumber
, DiskCount
, CheckSum
, i
, Signature
, EnabledDisks
= 0;
437 PARC_DISK_INFORMATION ArcDiskInformation
= LoaderBlock
->ArcDiskInformation
;
438 ANSI_STRING ArcBootString
, ArcSystemString
, DeviceStringA
, ArcNameStringA
, HalPathStringA
;
440 /* Initialise device number */
441 DeviceNumber
.DeviceNumber
= ULONG_MAX
;
442 /* Get all the disks present in the system */
443 DiskCount
= IoGetConfigurationInformation()->DiskCount
;
445 /* Get enabled disks and check if result matches */
446 Status
= IopFetchConfigurationInformation(&SymbolicLinkList
,
447 GUID_DEVINTERFACE_DISK
,
450 if (!NT_SUCCESS(Status
))
452 NotEnabledPresent
= TRUE
;
455 /* Save symbolic link list address in order to free it after */
456 lSymbolicLinkList
= SymbolicLinkList
;
458 /* Build the boot strings */
459 RtlInitAnsiString(&ArcBootString
, LoaderBlock
->ArcBootDeviceName
);
460 RtlInitAnsiString(&ArcSystemString
, LoaderBlock
->ArcHalDeviceName
);
462 /* If we have more enabled disks, take that into account */
463 if (EnabledDisks
> DiskCount
)
465 DiskCount
= EnabledDisks
;
468 /* If we'll have to browse for none enabled disks, fix higher count */
469 if (NotEnabledPresent
&& !EnabledDisks
)
474 /* Finally, if in spite of all that work, we still don't have disks, leave */
480 /* Start browsing disks */
481 for (DiskNumber
= 0; DiskNumber
< DiskCount
; DiskNumber
++)
483 /* Check if we have an enabled disk */
484 if (lSymbolicLinkList
&& *lSymbolicLinkList
!= UNICODE_NULL
)
486 /* Create its device name using first symbolic link */
487 RtlInitUnicodeString(&DeviceStringW
, lSymbolicLinkList
);
488 /* Then, update symbolic links list */
489 lSymbolicLinkList
+= wcslen(lSymbolicLinkList
) + (sizeof(UNICODE_NULL
) / sizeof(WCHAR
));
491 /* Get its associated device object and file object */
492 Status
= IoGetDeviceObjectPointer(&DeviceStringW
,
493 FILE_READ_ATTRIBUTES
,
496 if (NT_SUCCESS(Status
))
498 /* Now, we'll ask the device its device number */
499 Irp
= IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER
,
504 sizeof(STORAGE_DEVICE_NUMBER
),
508 /* Missing resources is a shame... No need to go farther */
511 ObDereferenceObject(FileObject
);
512 Status
= STATUS_INSUFFICIENT_RESOURCES
;
516 /* Call the driver, and wait for it if needed */
517 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
518 Status
= IoCallDriver(DeviceObject
, Irp
);
519 if (Status
== STATUS_PENDING
)
521 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
522 Status
= IoStatusBlock
.Status
;
525 /* If we didn't get the appriopriate data, just skip that disk */
526 if (!NT_SUCCESS(Status
))
528 ObDereferenceObject(FileObject
);
533 /* End of enabled disks enumeration */
534 if (NotEnabledPresent
&& *lSymbolicLinkList
== UNICODE_NULL
)
536 /* No enabled disk worked, reset field */
537 if (DeviceNumber
.DeviceNumber
== ULONG_MAX
)
539 DeviceNumber
.DeviceNumber
= 0;
542 /* Update disk number to enable the following not enabled disks */
543 if (DeviceNumber
.DeviceNumber
> DiskNumber
)
545 DiskNumber
= DeviceNumber
.DeviceNumber
;
548 /* Increase a bit more */
549 DiskCount
= DiskNumber
+ 20;
554 /* Create device name for the disk */
555 sprintf(Buffer
, "\\Device\\Harddisk%lu\\Partition0", DiskNumber
);
556 RtlInitAnsiString(&DeviceStringA
, Buffer
);
557 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
558 if (!NT_SUCCESS(Status
))
563 /* Get its device object */
564 Status
= IoGetDeviceObjectPointer(&DeviceStringW
,
565 FILE_READ_ATTRIBUTES
,
569 RtlFreeUnicodeString(&DeviceStringW
);
570 /* This is a security measure, to ensure DiskNumber will be used */
571 DeviceNumber
.DeviceNumber
= ULONG_MAX
;
574 /* Something failed somewhere earlier, just skip the disk */
575 if (!NT_SUCCESS(Status
))
580 /* Let's ask the disk for its geometry */
581 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
586 sizeof(DISK_GEOMETRY
),
590 /* Missing resources is a shame... No need to go farther */
593 ObDereferenceObject(FileObject
);
594 Status
= STATUS_INSUFFICIENT_RESOURCES
;
598 /* Call the driver, and wait for it if needed */
599 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
600 Status
= IoCallDriver(DeviceObject
, Irp
);
601 if (Status
== STATUS_PENDING
)
603 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
604 Status
= IoStatusBlock
.Status
;
606 /* Failure, skip disk */
607 if (!NT_SUCCESS(Status
))
609 ObDereferenceObject(FileObject
);
613 /* Read the partition table */
614 Status
= IoReadPartitionTableEx(DeviceObject
,
616 if (!NT_SUCCESS(Status
))
618 ObDereferenceObject(FileObject
);
622 /* Ensure we have at least 512 bytes per sector */
623 if (DiskGeometry
.BytesPerSector
< 512)
625 DiskGeometry
.BytesPerSector
= 512;
628 /* Check MBR type against EZ Drive type */
629 StartingOffset
.QuadPart
= 0;
630 HalExamineMBR(DeviceObject
, DiskGeometry
.BytesPerSector
, 0x55, &Data
);
633 /* If MBR is of the EZ Drive type, we'll read after it */
634 StartingOffset
.QuadPart
= DiskGeometry
.BytesPerSector
;
638 /* Allocate for reading enough data for checksum */
639 PartitionBuffer
= ExAllocatePoolWithTag(NonPagedPoolCacheAligned
, DiskGeometry
.BytesPerSector
, TAG_IO
);
640 if (!PartitionBuffer
)
642 ObDereferenceObject(FileObject
);
643 Status
= STATUS_INSUFFICIENT_RESOURCES
;
647 /* Read a sector for computing checksum */
648 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
651 DiskGeometry
.BytesPerSector
,
657 ObDereferenceObject(FileObject
);
658 Status
= STATUS_INSUFFICIENT_RESOURCES
;
662 /* Call the driver to perform reading */
663 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
664 Status
= IoCallDriver(DeviceObject
, Irp
);
665 if (Status
== STATUS_PENDING
)
667 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
668 Status
= IoStatusBlock
.Status
;
670 if (!NT_SUCCESS(Status
))
672 ExFreePool(DriveLayout
);
673 ExFreePoolWithTag(PartitionBuffer
, TAG_IO
);
674 ObDereferenceObject(FileObject
);
678 ObDereferenceObject(FileObject
);
680 /* Calculate checksum, that's an easy computation, just adds read data */
681 for (i
= 0, CheckSum
= 0; i
< 512 / sizeof(ULONG
) ; i
++)
683 CheckSum
+= PartitionBuffer
[i
];
686 /* Browse each ARC disk */
687 for (NextEntry
= ArcDiskInformation
->DiskSignatureListHead
.Flink
;
688 NextEntry
!= &ArcDiskInformation
->DiskSignatureListHead
;
689 NextEntry
= NextEntry
->Flink
)
691 ArcDiskSignature
= CONTAINING_RECORD(NextEntry
,
695 /* If they matches, ie
696 * - There's only one disk for both BIOS and detected/enabled
697 * - Signatures are matching
698 * - Checksums are matching
701 if (((SingleDisk
&& DiskCount
== 1) ||
702 (IopVerifyDiskSignature(DriveLayout
, ArcDiskSignature
, &Signature
) &&
703 (ArcDiskSignature
->CheckSum
+ CheckSum
== 0))) &&
704 (DriveLayout
->PartitionStyle
== PARTITION_STYLE_MBR
))
706 /* Create device name */
707 sprintf(Buffer
, "\\Device\\Harddisk%lu\\Partition0", (DeviceNumber
.DeviceNumber
!= ULONG_MAX
) ? DeviceNumber
.DeviceNumber
: DiskNumber
);
708 RtlInitAnsiString(&DeviceStringA
, Buffer
);
709 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
710 if (!NT_SUCCESS(Status
))
715 /* Create ARC name */
716 sprintf(ArcBuffer
, "\\ArcName\\%s", ArcDiskSignature
->ArcName
);
717 RtlInitAnsiString(&ArcNameStringA
, ArcBuffer
);
718 Status
= RtlAnsiStringToUnicodeString(&ArcNameStringW
, &ArcNameStringA
, TRUE
);
719 if (!NT_SUCCESS(Status
))
721 RtlFreeUnicodeString(&DeviceStringW
);
726 IoAssignArcName(&ArcNameStringW
, &DeviceStringW
);
728 /* And release resources */
729 RtlFreeUnicodeString(&ArcNameStringW
);
730 RtlFreeUnicodeString(&DeviceStringW
);
732 /* Now, browse for every partition */
733 for (i
= 1; i
<= DriveLayout
->PartitionCount
; i
++)
735 /* Create device name */
736 sprintf(Buffer
, "\\Device\\Harddisk%lu\\Partition%lu", (DeviceNumber
.DeviceNumber
!= ULONG_MAX
) ? DeviceNumber
.DeviceNumber
: DiskNumber
, i
);
737 RtlInitAnsiString(&DeviceStringA
, Buffer
);
738 Status
= RtlAnsiStringToUnicodeString(&DeviceStringW
, &DeviceStringA
, TRUE
);
739 if (!NT_SUCCESS(Status
))
744 /* Create partial ARC name */
745 sprintf(ArcBuffer
, "%spartition(%lu)", ArcDiskSignature
->ArcName
, i
);
746 RtlInitAnsiString(&ArcNameStringA
, ArcBuffer
);
748 /* Is that boot device? */
749 if (RtlEqualString(&ArcNameStringA
, &ArcBootString
, TRUE
))
751 DPRINT("Found boot device\n");
755 /* Is that system partition? */
756 if (RtlEqualString(&ArcNameStringA
, &ArcSystemString
, TRUE
))
758 /* Create HAL path name */
759 RtlInitAnsiString(&HalPathStringA
, LoaderBlock
->NtHalPathName
);
760 Status
= RtlAnsiStringToUnicodeString(&HalPathStringW
, &HalPathStringA
, TRUE
);
761 if (!NT_SUCCESS(Status
))
763 RtlFreeUnicodeString(&DeviceStringW
);
767 /* Then store those information to registry */
768 IopStoreSystemPartitionInformation(&DeviceStringW
, &HalPathStringW
);
769 RtlFreeUnicodeString(&HalPathStringW
);
772 /* Create complete ARC name */
773 sprintf(ArcBuffer
, "\\ArcName\\%spartition(%lu)", ArcDiskSignature
->ArcName
, i
);
774 RtlInitAnsiString(&ArcNameStringA
, ArcBuffer
);
775 Status
= RtlAnsiStringToUnicodeString(&ArcNameStringW
, &ArcNameStringA
, TRUE
);
776 if (!NT_SUCCESS(Status
))
778 RtlFreeUnicodeString(&DeviceStringW
);
782 /* Link device name & ARC name */
783 IoAssignArcName(&ArcNameStringW
, &DeviceStringW
);
785 /* Release strings */
786 RtlFreeUnicodeString(&ArcNameStringW
);
787 RtlFreeUnicodeString(&DeviceStringW
);
792 /* In case there's a valid partition, a matching signature,
793 BUT a none matching checksum, or there's a duplicate
794 signature, or even worse a virus played with partition
796 if (ArcDiskSignature
->Signature
== Signature
&&
797 (ArcDiskSignature
->CheckSum
+ CheckSum
!= 0) &&
798 ArcDiskSignature
->ValidPartitionTable
)
800 DPRINT("Be careful, or you have a duplicate disk signature, or a virus altered your MBR!\n");
805 /* Release memory before jumping to next item */
806 ExFreePool(DriveLayout
);
808 ExFreePoolWithTag(PartitionBuffer
, TAG_IO
);
809 PartitionBuffer
= NULL
;
812 Status
= STATUS_SUCCESS
;
815 if (SymbolicLinkList
)
817 ExFreePool(SymbolicLinkList
);
822 ExFreePool(DriveLayout
);
827 ExFreePoolWithTag(PartitionBuffer
, TAG_IO
);
836 IopReassignSystemRoot(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
837 OUT PANSI_STRING NtBootPath
)
839 OBJECT_ATTRIBUTES ObjectAttributes
;
841 CHAR Buffer
[256], AnsiBuffer
[256];
842 WCHAR ArcNameBuffer
[64];
843 ANSI_STRING TargetString
, ArcString
, TempString
;
844 UNICODE_STRING LinkName
, TargetName
, ArcName
;
847 /* Create the Unicode name for the current ARC boot device */
848 sprintf(Buffer
, "\\ArcName\\%s", LoaderBlock
->ArcBootDeviceName
);
849 RtlInitAnsiString(&TargetString
, Buffer
);
850 Status
= RtlAnsiStringToUnicodeString(&TargetName
, &TargetString
, TRUE
);
851 if (!NT_SUCCESS(Status
)) return FALSE
;
853 /* Initialize the attributes and open the link */
854 InitializeObjectAttributes(&ObjectAttributes
,
856 OBJ_CASE_INSENSITIVE
,
859 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
860 SYMBOLIC_LINK_ALL_ACCESS
,
862 if (!NT_SUCCESS(Status
))
864 /* We failed, free the string */
865 RtlFreeUnicodeString(&TargetName
);
869 /* Query the current \\SystemRoot */
870 ArcName
.Buffer
= ArcNameBuffer
;
872 ArcName
.MaximumLength
= sizeof(ArcNameBuffer
);
873 Status
= NtQuerySymbolicLinkObject(LinkHandle
, &ArcName
, NULL
);
874 if (!NT_SUCCESS(Status
))
876 /* We failed, free the string */
877 RtlFreeUnicodeString(&TargetName
);
881 /* Convert it to Ansi */
882 ArcString
.Buffer
= AnsiBuffer
;
883 ArcString
.Length
= 0;
884 ArcString
.MaximumLength
= sizeof(AnsiBuffer
);
885 Status
= RtlUnicodeStringToAnsiString(&ArcString
, &ArcName
, FALSE
);
886 AnsiBuffer
[ArcString
.Length
] = ANSI_NULL
;
888 /* Close the link handle and free the name */
889 ObCloseHandle(LinkHandle
, KernelMode
);
890 RtlFreeUnicodeString(&TargetName
);
892 /* Setup the system root name again */
893 RtlInitAnsiString(&TempString
, "\\SystemRoot");
894 Status
= RtlAnsiStringToUnicodeString(&LinkName
, &TempString
, TRUE
);
895 if (!NT_SUCCESS(Status
)) return FALSE
;
897 /* Open the symbolic link for it */
898 InitializeObjectAttributes(&ObjectAttributes
,
900 OBJ_CASE_INSENSITIVE
,
903 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
904 SYMBOLIC_LINK_ALL_ACCESS
,
906 if (!NT_SUCCESS(Status
)) return FALSE
;
909 NtMakeTemporaryObject(LinkHandle
);
910 ObCloseHandle(LinkHandle
, KernelMode
);
912 /* Now create the new name for it */
913 sprintf(Buffer
, "%s%s", ArcString
.Buffer
, LoaderBlock
->NtBootPathName
);
915 /* Copy it into the passed parameter and null-terminate it */
916 RtlCopyString(NtBootPath
, &ArcString
);
917 Buffer
[strlen(Buffer
) - 1] = ANSI_NULL
;
919 /* Setup the Unicode-name for the new symbolic link value */
920 RtlInitAnsiString(&TargetString
, Buffer
);
921 InitializeObjectAttributes(&ObjectAttributes
,
923 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
926 Status
= RtlAnsiStringToUnicodeString(&ArcName
, &TargetString
, TRUE
);
927 if (!NT_SUCCESS(Status
)) return FALSE
;
930 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
931 SYMBOLIC_LINK_ALL_ACCESS
,
935 /* Free all the strings and close the handle and return success */
936 RtlFreeUnicodeString(&ArcName
);
937 RtlFreeUnicodeString(&LinkName
);
938 ObCloseHandle(LinkHandle
, KernelMode
);
944 IopVerifyDiskSignature(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout
,
945 IN PARC_DISK_SIGNATURE ArcDiskSignature
,
946 OUT PULONG Signature
)
948 /* First condition: having a valid partition table */
949 if (!ArcDiskSignature
->ValidPartitionTable
)
954 /* If that partition table is the MBR */
955 if (DriveLayout
->PartitionStyle
== PARTITION_STYLE_MBR
)
957 /* Then check MBR signature */
958 if (DriveLayout
->Mbr
.Signature
== ArcDiskSignature
->Signature
)
963 *Signature
= DriveLayout
->Mbr
.Signature
;
969 /* If that partition table is the GPT */
970 else if (DriveLayout
->PartitionStyle
== PARTITION_STYLE_GPT
)
972 /* Check we are using GPT and compare GUID */
973 if (ArcDiskSignature
->IsGpt
&&
974 (((PULONG
)ArcDiskSignature
->GptSignature
)[0] == DriveLayout
->Gpt
.DiskId
.Data1
&&
975 ((PUSHORT
)ArcDiskSignature
->GptSignature
)[2] == DriveLayout
->Gpt
.DiskId
.Data2
&&
976 ((PUSHORT
)ArcDiskSignature
->GptSignature
)[3] == DriveLayout
->Gpt
.DiskId
.Data3
&&
977 ((PULONGLONG
)ArcDiskSignature
->GptSignature
)[1] == ((PULONGLONG
)DriveLayout
->Gpt
.DiskId
.Data4
)[0]))
979 /* There's no signature to give, so we just zero output */
988 /* If we fall here, it means that something went wrong, so return that */