ReactOS 0.4.17-dev-1190-g4c812f4
arcname.c
Go to the documentation of this file.
1/*
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)
7* Eric Kohl
8* Pierre Schweitzer (pierre.schweitzer@reactos.org)
9*/
10
11/* INCLUDES ******************************************************************/
12
13#include <ntoskrnl.h>
14#define NDEBUG
15#include <debug.h>
16
17/* GLOBALS *******************************************************************/
18
21
22/* FUNCTIONS *****************************************************************/
23
24CODE_SEG("INIT")
28
33 IN BOOLEAN SingleDisk,
34 OUT PBOOLEAN FoundBoot);
35
40{
43 CHAR Buffer[128];
44 BOOLEAN SingleDisk;
45 BOOLEAN FoundBoot = FALSE;
46 UNICODE_STRING SystemDevice, LoaderPathNameW, BootDeviceName;
47 PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation;
48 ANSI_STRING ArcString, LanmanRedirector, LoaderPathNameA;
49
50 /* Check if we only have one disk on the machine */
51 SingleDisk = (ArcDiskInfo->DiskSignatureListHead.Flink->Flink ==
52 &ArcDiskInfo->DiskSignatureListHead);
53
54 /* This runs again while waiting for the boot device, drop the previous names */
58 {
61 }
62
63 /* Create the firmware system loader / HAL partition global name */
64 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName);
65 RtlInitAnsiString(&ArcString, Buffer);
67 if (!NT_SUCCESS(Status))
68 return Status;
69
70 /* Create the OS boot partition global name */
71 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
72 RtlInitAnsiString(&ArcString, Buffer);
74 if (!NT_SUCCESS(Status))
75 return Status;
76
77 /* Allocate memory for the string */
78 Length = strlen(LoaderBlock->ArcBootDeviceName) + sizeof(ANSI_NULL);
80 Length,
81 TAG_IO);
83 {
84 /* Copy the name */
86 LoaderBlock->ArcBootDeviceName,
87 Length);
88 }
89
90 /* Check if we only found a disk, but we're booting from CD-ROM */
91 if ((SingleDisk) && strstr(LoaderBlock->ArcBootDeviceName, "cdrom"))
92 {
93 /* Then disable single-disk mode, since there's a CD drive out there */
94 SingleDisk = FALSE;
95 }
96
97 /* If we are doing remote booting */
99 {
100 /* Yes, we have found boot device */
101 FoundBoot = TRUE;
102
103 /* Get NT device name */
104 RtlInitAnsiString(&LanmanRedirector, "\\Device\\LanmanRedirector");
105 Status = RtlAnsiStringToUnicodeString(&SystemDevice, &LanmanRedirector, TRUE);
106 if (!NT_SUCCESS(Status))
107 {
108 return Status;
109 }
110
111 /* Get ARC booting device name (in net(0) something) */
112 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
113 RtlInitAnsiString(&ArcString, Buffer);
114 Status = RtlAnsiStringToUnicodeString(&BootDeviceName, &ArcString, TRUE);
115 if (NT_SUCCESS(Status))
116 {
117 /* Map ARC to NT name */
118 IoAssignArcName(&BootDeviceName, &SystemDevice);
119 RtlFreeUnicodeString(&BootDeviceName);
120
121 /* Now, get loader path name */
122 RtlInitAnsiString(&LoaderPathNameA, LoaderBlock->NtHalPathName);
123 Status = RtlAnsiStringToUnicodeString(&LoaderPathNameW, &LoaderPathNameA, TRUE);
124 if (!NT_SUCCESS(Status))
125 {
126 RtlFreeUnicodeString(&SystemDevice);
127 return Status;
128 }
129
130 /* And set it has system partition */
131 IopStoreSystemPartitionInformation(&SystemDevice, &LoaderPathNameW);
132 }
133
134 RtlFreeUnicodeString(&SystemDevice);
135
136 /* Don't quit here, even if everything went fine!
137 * We need IopCreateArcNamesDisk to properly map
138 * devices with symlinks.
139 * It will return success if the mapping process went fine
140 * even if it didn't find boot device.
141 * It won't reset boot device finding status as well.
142 */
143 }
144
145 /* Loop every disk and try to find boot disk */
146 Status = IopCreateArcNamesDisk(LoaderBlock, SingleDisk, &FoundBoot);
147 /* If it succeeded but we didn't find boot device, try to browse Cds */
148 if (NT_SUCCESS(Status) && !FoundBoot)
149 {
150 Status = IopCreateArcNamesCd(LoaderBlock);
151 }
152
153 /* Return success */
154 return Status;
155}
156
157CODE_SEG("INIT")
159NTAPI
161{
162 PIRP Irp;
165 PLIST_ENTRY NextEntry;
171 CHAR Buffer[128], ArcBuffer[128];
172 BOOLEAN NotEnabledPresent = FALSE;
174 ANSI_STRING DeviceStringA, ArcNameStringA;
175 PWSTR SymbolicLinkList, lSymbolicLinkList;
176 PARC_DISK_SIGNATURE ArcDiskSignature = NULL;
177 UNICODE_STRING DeviceStringW, ArcNameStringW;
178 ULONG DiskNumber, CdRomCount, CheckSum, i, EnabledDisks = 0;
179 PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation;
180
181 /* Get all the Cds present in the system */
183
184 /* Get enabled Cds and check if result matches
185 * For the record, enabled Cds (or even disk) are Cds/disks
186 * that have been successfully handled by MountMgr driver
187 * and that already own their device name. This is the "new" way
188 * to handle them, that came with NT5.
189 * Currently, Windows 2003 provides an ARC names creation based
190 * on both enabled drives and not enabled drives (lack from
191 * the driver).
192 * Given the current ReactOS state, that's good for us.
193 * To sum up, this is NOT a hack or whatsoever.
194 */
196 GUID_DEVINTERFACE_CDROM,
197 CdRomCount,
198 &EnabledDisks);
199 if (!NT_SUCCESS(Status))
200 {
201 NotEnabledPresent = TRUE;
202 }
203 /* Save symbolic link list address in order to free it after */
204 lSymbolicLinkList = SymbolicLinkList;
205 /* For the moment, we won't fail */
207
208 /* Browse all the ARC devices trying to find the one matching boot device */
209 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
210 NextEntry != &ArcDiskInformation->DiskSignatureListHead;
211 NextEntry = NextEntry->Flink)
212 {
213 ArcDiskSignature = CONTAINING_RECORD(NextEntry,
215 ListEntry);
216
217 if (strcmp(LoaderBlock->ArcBootDeviceName, ArcDiskSignature->ArcName) == 0)
218 {
219 break;
220 }
221
222 ArcDiskSignature = NULL;
223 }
224
225 /* Not found... Not booting from a Cd */
226 if (!ArcDiskSignature)
227 {
228 DPRINT("Failed finding a cd that could match current boot device\n");
229 goto Cleanup;
230 }
231
232 /* Allocate needed space for reading Cd */
234 if (!PartitionBuffer)
235 {
236 DPRINT("Failed allocating resources!\n");
237 /* Here, we fail, BUT we return success, some Microsoft joke */
238 goto Cleanup;
239 }
240
241 /* If we have more enabled Cds, take that into account */
242 if (EnabledDisks > CdRomCount)
243 {
244 CdRomCount = EnabledDisks;
245 }
246
247 /* If we'll have to browse for none enabled Cds, fix higher count */
248 if (NotEnabledPresent && !EnabledDisks)
249 {
250 CdRomCount += 5;
251 }
252
253 /* Finally, if in spite of all that work, we still don't have Cds, leave */
254 if (!CdRomCount)
255 {
256 goto Cleanup;
257 }
258
259 /* Start browsing Cds */
260 for (DiskNumber = 0, EnabledDisks = 0; DiskNumber < CdRomCount; DiskNumber++)
261 {
262 /* Check if we have an enabled disk */
263 if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL)
264 {
265 /* Create its device name using first symbolic link */
266 RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList);
267 /* Then, update symbolic links list */
268 lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR));
269
270 /* Get its associated device object and file object */
271 Status = IoGetDeviceObjectPointer(&DeviceStringW,
273 &FileObject,
274 &DeviceObject);
275 /* Failure? Good bye! */
276 if (!NT_SUCCESS(Status))
277 {
278 goto Cleanup;
279 }
280
281 /* Now, we'll ask the device its device number */
284 NULL,
285 0,
287 sizeof(DeviceNumber),
288 FALSE,
289 &Event,
291 /* Failure? Good bye! */
292 if (!Irp)
293 {
294 /* Dereference file object before leaving */
297 goto Cleanup;
298 }
299
300 /* Call the driver, and wait for it if needed */
303 if (Status == STATUS_PENDING)
304 {
306 Status = IoStatusBlock.Status;
307 }
308 if (!NT_SUCCESS(Status))
309 {
311 goto Cleanup;
312 }
313
314 /* Finally, build proper device name */
315 sprintf(Buffer, "\\Device\\CdRom%lu", DeviceNumber.DeviceNumber);
316 RtlInitAnsiString(&DeviceStringA, Buffer);
317 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
318 if (!NT_SUCCESS(Status))
319 {
321 goto Cleanup;
322 }
323 }
324 else
325 {
326 /* Create device name for the cd */
327 sprintf(Buffer, "\\Device\\CdRom%lu", EnabledDisks++);
328 RtlInitAnsiString(&DeviceStringA, Buffer);
329 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
330 if (!NT_SUCCESS(Status))
331 {
332 goto Cleanup;
333 }
334
335 /* Get its device object */
336 Status = IoGetDeviceObjectPointer(&DeviceStringW,
338 &FileObject,
339 &DeviceObject);
340 if (!NT_SUCCESS(Status))
341 {
342 RtlFreeUnicodeString(&DeviceStringW);
343 goto Cleanup;
344 }
345 }
346
347 /* Initiate data for reading cd and compute checksum */
348 StartingOffset.QuadPart = 0x8000;
349 CheckSum = 0;
353 2048,
355 &Event,
357 if (Irp)
358 {
359 /* Call the driver, and wait for it if needed */
362 if (Status == STATUS_PENDING)
363 {
365 Status = IoStatusBlock.Status;
366 }
367
368 /* If reading succeeded, compute checksum by adding data, 2048 bytes checksum */
369 if (NT_SUCCESS(Status))
370 {
371 for (i = 0; i < 2048 / sizeof(ULONG); i++)
372 {
373 CheckSum += PartitionBuffer[i];
374 }
375 }
376 }
377
378 /* Dereference file object */
380
381 /* If checksums are matching, we have the proper cd */
382 if (CheckSum + ArcDiskSignature->CheckSum == 0)
383 {
384 /* Create ARC name */
385 sprintf(ArcBuffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
386 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
387 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
388 if (NT_SUCCESS(Status))
389 {
390 /* Create symbolic link */
391 IoAssignArcName(&ArcNameStringW, &DeviceStringW);
392 RtlFreeUnicodeString(&ArcNameStringW);
393 DPRINT("Boot device found\n");
394 }
395
396 /* And quit, whatever happens */
397 RtlFreeUnicodeString(&DeviceStringW);
398 goto Cleanup;
399 }
400
401 /* Free string before trying another disk */
402 RtlFreeUnicodeString(&DeviceStringW);
403 }
404
405Cleanup:
406 if (PartitionBuffer)
407 {
409 }
410
412 {
414 }
415
416 return Status;
417}
418
419CODE_SEG("INIT")
421NTAPI
423 IN BOOLEAN SingleDisk,
424 OUT PBOOLEAN FoundBoot)
425{
426 PIRP Irp;
427 PVOID Data;
430 PLIST_ENTRY NextEntry;
432 DISK_GEOMETRY DiskGeometry;
437 CHAR Buffer[128], ArcBuffer[128];
438 BOOLEAN NotEnabledPresent = FALSE;
440 PARC_DISK_SIGNATURE ArcDiskSignature;
441 PWSTR SymbolicLinkList, lSymbolicLinkList;
442 PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL;
443 UNICODE_STRING DeviceStringW, ArcNameStringW, HalPathStringW;
444 ULONG DiskNumber, DiskCount, CheckSum, i, Signature, EnabledDisks = 0;
445 PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation;
446 ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA, HalPathStringA;
447
448 /* Initialise device number */
449 DeviceNumber.DeviceNumber = ULONG_MAX;
450 /* Get all the disks present in the system */
452
453 /* Get enabled disks and check if result matches */
455 GUID_DEVINTERFACE_DISK,
456 DiskCount,
457 &EnabledDisks);
458 if (!NT_SUCCESS(Status))
459 {
460 NotEnabledPresent = TRUE;
461 }
462
463 /* Save symbolic link list address in order to free it after */
464 lSymbolicLinkList = SymbolicLinkList;
465
466 /* Build the boot strings */
467 RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName);
468 RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
469
470 /* If we have more enabled disks, take that into account */
471 if (EnabledDisks > DiskCount)
472 {
473 DiskCount = EnabledDisks;
474 }
475
476 /* If we'll have to browse for none enabled disks, fix higher count */
477 if (NotEnabledPresent && !EnabledDisks)
478 {
479 DiskCount += 20;
480 }
481
482 /* Finally, if in spite of all that work, we still don't have disks, leave */
483 if (!DiskCount)
484 {
485 goto Cleanup;
486 }
487
488 /* Start browsing disks */
489 for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++)
490 {
491 ASSERT(DriveLayout == NULL);
492
493 /* Check if we have an enabled disk */
494 if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL)
495 {
496 /* Create its device name using first symbolic link */
497 RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList);
498 /* Then, update symbolic links list */
499 lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR));
500
501 /* Get its associated device object and file object */
502 Status = IoGetDeviceObjectPointer(&DeviceStringW,
504 &FileObject,
505 &DeviceObject);
506 if (NT_SUCCESS(Status))
507 {
508 /* Now, we'll ask the device its device number */
511 NULL,
512 0,
514 sizeof(DeviceNumber),
515 FALSE,
516 &Event,
518 /* Missing resources is a shame... No need to go farther */
519 if (!Irp)
520 {
523 goto Cleanup;
524 }
525
526 /* Call the driver, and wait for it if needed */
529 if (Status == STATUS_PENDING)
530 {
532 Status = IoStatusBlock.Status;
533 }
534
535 /* If we didn't get the appropriate data, just skip that disk */
536 if (!NT_SUCCESS(Status))
537 {
539 continue;
540 }
541 }
542
543 /* End of enabled disks enumeration */
544 if (NotEnabledPresent && *lSymbolicLinkList == UNICODE_NULL)
545 {
546 /* No enabled disk worked, reset field */
547 if (DeviceNumber.DeviceNumber == ULONG_MAX)
548 {
549 DeviceNumber.DeviceNumber = 0;
550 }
551
552 /* Update disk number to enable the following not enabled disks */
553 if (DeviceNumber.DeviceNumber > DiskNumber)
554 {
555 DiskNumber = DeviceNumber.DeviceNumber;
556 }
557
558 /* Increase a bit more */
559 DiskCount = DiskNumber + 20;
560 }
561 }
562 else
563 {
564 /* Create device name for the disk */
565 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber);
566 RtlInitAnsiString(&DeviceStringA, Buffer);
567 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
568 if (!NT_SUCCESS(Status))
569 {
570 goto Cleanup;
571 }
572
573 /* Get its device object */
574 Status = IoGetDeviceObjectPointer(&DeviceStringW,
576 &FileObject,
577 &DeviceObject);
578
579 RtlFreeUnicodeString(&DeviceStringW);
580 /* This is a security measure, to ensure DiskNumber will be used */
581 DeviceNumber.DeviceNumber = ULONG_MAX;
582 }
583
584 /* Something failed somewhere earlier, just skip the disk */
585 if (!NT_SUCCESS(Status))
586 {
587 continue;
588 }
589
590 /* Let's ask the disk for its geometry */
593 NULL,
594 0,
595 &DiskGeometry,
596 sizeof(DiskGeometry),
597 FALSE,
598 &Event,
600 /* Missing resources is a shame... No need to go farther */
601 if (!Irp)
602 {
605 goto Cleanup;
606 }
607
608 /* Call the driver, and wait for it if needed */
611 if (Status == STATUS_PENDING)
612 {
614 Status = IoStatusBlock.Status;
615 }
616 /* Failure, skip disk */
617 if (!NT_SUCCESS(Status))
618 {
620 continue;
621 }
622
623 /* Read the partition table */
625 &DriveLayout);
626 if (!NT_SUCCESS(Status))
627 {
629 continue;
630 }
631
632 /* Ensure we have at least 512 bytes per sector */
633 if (DiskGeometry.BytesPerSector < 512)
634 {
635 DiskGeometry.BytesPerSector = 512;
636 }
637
638 /* Check MBR type against EZ Drive type */
639 StartingOffset.QuadPart = 0;
641 if (Data)
642 {
643 /* If MBR is of the EZ Drive type, we'll read after it */
644 StartingOffset.QuadPart = DiskGeometry.BytesPerSector;
646 }
647
648 /* Allocate for reading enough data for checksum */
650 if (!PartitionBuffer)
651 {
654 goto Cleanup;
655 }
656
657 /* Read the first sector for computing checksum */
661 DiskGeometry.BytesPerSector,
663 &Event,
665 if (!Irp)
666 {
670 goto Cleanup;
671 }
672
673 /* Call the driver to perform reading */
676 if (Status == STATUS_PENDING)
677 {
679 Status = IoStatusBlock.Status;
680 }
681
682 /* If reading succeeded, calculate checksum by adding data */
683 if (NT_SUCCESS(Status))
684 {
685 for (i = 0, CheckSum = 0; i < 512 / sizeof(ULONG); i++)
686 {
687 CheckSum += PartitionBuffer[i];
688 }
689 }
690
691 /* Release now unnecessary resources */
694
695 /* If we failed, release drive layout before going to next disk */
696 if (!NT_SUCCESS(Status))
697 {
698 ExFreePool(DriveLayout);
699 DriveLayout = NULL;
700 continue;
701 }
702
703 /* Browse each ARC disk */
704 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
705 NextEntry != &ArcDiskInformation->DiskSignatureListHead;
706 NextEntry = NextEntry->Flink)
707 {
708 ArcDiskSignature = CONTAINING_RECORD(NextEntry,
710 ListEntry);
711
712 /*
713 * If this is the only MBR disk in the ARC list and detected in
714 * the device tree, just go ahead and create the ArcName links.
715 * Otherwise, verify whether the signatures and checksums match
716 * before proceeding.
717 */
718 if ((SingleDisk && (DiskCount == 1) &&
719 (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)) ||
720 (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature) &&
721 (ArcDiskSignature->CheckSum + CheckSum == 0)))
722 {
723 /* Create device name */
724 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0",
725 (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber);
726 RtlInitAnsiString(&DeviceStringA, Buffer);
727 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
728 if (!NT_SUCCESS(Status))
729 {
730 goto Cleanup;
731 }
732
733 /* Create ARC name */
734 sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName);
735 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
736 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
737 if (!NT_SUCCESS(Status))
738 {
739 RtlFreeUnicodeString(&DeviceStringW);
740 goto Cleanup;
741 }
742
743 /* Link both */
744 IoAssignArcName(&ArcNameStringW, &DeviceStringW);
745
746 /* And release strings */
747 RtlFreeUnicodeString(&ArcNameStringW);
748 RtlFreeUnicodeString(&DeviceStringW);
749
750 /* Now, browse each partition */
751 for (i = 1; i <= DriveLayout->PartitionCount; i++)
752 {
753 /* Create device name */
754 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu",
755 (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber, i);
756 RtlInitAnsiString(&DeviceStringA, Buffer);
757 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
758 if (!NT_SUCCESS(Status))
759 {
760 goto Cleanup;
761 }
762
763 /* Create partial ARC name */
764 sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, i);
765 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
766
767 /* Is that boot device? */
768 if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE))
769 {
770 DPRINT("Found boot device\n");
771 *FoundBoot = TRUE;
772 }
773
774 /* Is that system partition? */
775 if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE))
776 {
777 /* Create HAL path name */
778 RtlInitAnsiString(&HalPathStringA, LoaderBlock->NtHalPathName);
779 Status = RtlAnsiStringToUnicodeString(&HalPathStringW, &HalPathStringA, TRUE);
780 if (!NT_SUCCESS(Status))
781 {
782 RtlFreeUnicodeString(&DeviceStringW);
783 goto Cleanup;
784 }
785
786 /* Then store those information to registry */
787 IopStoreSystemPartitionInformation(&DeviceStringW, &HalPathStringW);
788 RtlFreeUnicodeString(&HalPathStringW);
789 }
790
791 /* Create complete ARC name */
792 sprintf(ArcBuffer, "\\ArcName\\%spartition(%lu)", ArcDiskSignature->ArcName, i);
793 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
794 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
795 if (!NT_SUCCESS(Status))
796 {
797 RtlFreeUnicodeString(&DeviceStringW);
798 goto Cleanup;
799 }
800
801 /* Link device name & ARC name */
802 IoAssignArcName(&ArcNameStringW, &DeviceStringW);
803
804 /* Release strings */
805 RtlFreeUnicodeString(&ArcNameStringW);
806 RtlFreeUnicodeString(&DeviceStringW);
807 }
808 }
809 else
810 {
811 /* Debugging feedback: Warn in case there's a valid partition,
812 * a matching signature, BUT a non-matching checksum: this can
813 * be the sign of a duplicate signature, or even worse a virus
814 * played with the partition table. */
815 if (ArcDiskSignature->ValidPartitionTable &&
816 (ArcDiskSignature->Signature == Signature) &&
817 (ArcDiskSignature->CheckSum + CheckSum != 0))
818 {
819 DPRINT("Be careful, you have a duplicate disk signature, or a virus altered your MBR!\n");
820 }
821 }
822 }
823
824 /* Finally, release drive layout */
825 ExFreePool(DriveLayout);
826 DriveLayout = NULL;
827 }
828
830
831Cleanup:
832 if (DriveLayout)
833 {
834 ExFreePool(DriveLayout);
835 }
836
838 {
840 }
841
842 return Status;
843}
844
845CODE_SEG("INIT")
847NTAPI
849 OUT PANSI_STRING NtBootPath)
850{
853 CHAR Buffer[256], AnsiBuffer[256];
854 WCHAR ArcNameBuffer[64];
855 ANSI_STRING TargetString, ArcString, TempString;
856 UNICODE_STRING LinkName, TargetName, ArcName;
857 HANDLE LinkHandle;
858
859 /* Create the Unicode name for the current ARC boot device */
860 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
863 if (!NT_SUCCESS(Status)) return FALSE;
864
865 /* Initialize the attributes and open the link */
867 &TargetName,
869 NULL,
870 NULL);
871 Status = NtOpenSymbolicLinkObject(&LinkHandle,
874 if (!NT_SUCCESS(Status))
875 {
876 /* We failed, free the string */
878 return FALSE;
879 }
880
881 /* Query the current \\SystemRoot */
882 ArcName.Buffer = ArcNameBuffer;
883 ArcName.Length = 0;
884 ArcName.MaximumLength = sizeof(ArcNameBuffer);
885 Status = NtQuerySymbolicLinkObject(LinkHandle, &ArcName, NULL);
886 if (!NT_SUCCESS(Status))
887 {
888 /* We failed, free the string */
890 return FALSE;
891 }
892
893 /* Convert it to Ansi */
894 ArcString.Buffer = AnsiBuffer;
895 ArcString.Length = 0;
896 ArcString.MaximumLength = sizeof(AnsiBuffer);
897 Status = RtlUnicodeStringToAnsiString(&ArcString, &ArcName, FALSE);
898 AnsiBuffer[ArcString.Length] = ANSI_NULL;
899
900 /* Close the link handle and free the name */
901 ObCloseHandle(LinkHandle, KernelMode);
903
904 /* Setup the system root name again */
905 RtlInitAnsiString(&TempString, "\\SystemRoot");
906 Status = RtlAnsiStringToUnicodeString(&LinkName, &TempString, TRUE);
907 if (!NT_SUCCESS(Status)) return FALSE;
908
909 /* Open the symbolic link for it */
911 &LinkName,
913 NULL,
914 NULL);
915 Status = NtOpenSymbolicLinkObject(&LinkHandle,
918 if (!NT_SUCCESS(Status)) return FALSE;
919
920 /* Destroy it */
921 NtMakeTemporaryObject(LinkHandle);
922 ObCloseHandle(LinkHandle, KernelMode);
923
924 /* Now create the new name for it */
925 sprintf(Buffer, "%s%s", ArcString.Buffer, LoaderBlock->NtBootPathName);
926
927 /* Copy it into the passed parameter and null-terminate it */
928 RtlCopyString(NtBootPath, &ArcString);
930
931 /* Setup the Unicode-name for the new symbolic link value */
934 &LinkName,
936 NULL,
937 NULL);
939 if (!NT_SUCCESS(Status)) return FALSE;
940
941 /* Create it */
945 &ArcName);
946
947 /* Free all the strings and close the handle and return success */
948 RtlFreeUnicodeString(&ArcName);
949 RtlFreeUnicodeString(&LinkName);
950 ObCloseHandle(LinkHandle, KernelMode);
951 return TRUE;
952}
953
956 _In_ PDRIVE_LAYOUT_INFORMATION_EX DriveLayout,
957 _In_ PARC_DISK_SIGNATURE ArcDiskSignature,
959{
960 /* Fail if the partition table is invalid */
961 if (!ArcDiskSignature->ValidPartitionTable)
962 return FALSE;
963
964 /* If the partition style is MBR */
965 if (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)
966 {
967 /* Check the MBR signature */
968 if (DriveLayout->Mbr.Signature == ArcDiskSignature->Signature)
969 {
970 /* And return it */
971 if (Signature)
972 *Signature = DriveLayout->Mbr.Signature;
973 return TRUE;
974 }
975 }
976 /* If the partition style is GPT */
977 else if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
978 {
979 /* Verify whether the signature is GPT and compare the GUID */
980 if (ArcDiskSignature->IsGpt &&
981 IsEqualGUID((PGUID)&ArcDiskSignature->GptSignature, &DriveLayout->Gpt.DiskId))
982 {
983 /* There is no signature to return, just zero it */
984 if (Signature)
985 *Signature = 0;
986 return TRUE;
987 }
988 }
989
990 /* If we get there, something went wrong, so fail */
991 return FALSE;
992}
993
994/* EOF */
#define CODE_SEG(...)
unsigned char BOOLEAN
Definition: actypes.h:127
@ INIT
Definition: arabic.c:42
LONG NTSTATUS
Definition: precomp.h:26
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
_In_z_ PCHAR TargetString
Definition: cdrom.h:954
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
Definition: bufpool.h:45
_In_ PCHAR _In_ ULONG DeviceNumber
Definition: classpnp.h:1230
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_In_ PIO_STATUS_BLOCK IoStatusBlock
Definition: dispmprt.h:608
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
Definition: dispmprt.h:1287
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
#define ULONG_MAX
Definition: limits.h:31
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1597
_ACRTIMP char *__cdecl strstr(const char *, const char *)
Definition: string.c:3420
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3324
static const WCHAR Signature[]
Definition: parser.c:141
static const WCHAR Cleanup[]
Definition: register.c:80
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define NonPagedPoolCacheAligned
Definition: env_spec_w32.h:310
#define PagedPool
Definition: env_spec_w32.h:308
NTSTATUS NTAPI IoReadPartitionTableEx(IN PDEVICE_OBJECT DeviceObject, OUT PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
Definition: fstubex.c:2274
Status
Definition: gdiplustypes.h:24
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Returns a pointer to the I/O manager's global configuration information structure.
Definition: iorsrce.c:998
_In_ PIRP Irp
Definition: kse.h:79
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
@ PARTITION_STYLE_GPT
Definition: imports.h:202
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define sprintf
Definition: sprintf.c:45
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
#define KernelMode
Definition: asm.h:38
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define SYMBOLIC_LINK_ALL_ACCESS
Definition: nt_native.h:1270
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlCopyString(PSTRING DestinationString, PSTRING SourceString)
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
NTSYSAPI BOOLEAN NTAPI RtlEqualString(PSTRING String1, PSTRING String2, BOOLEAN CaseInSensitive)
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
#define UNICODE_NULL
#define ANSI_NULL
#define PARTITION_EZDRIVE
Definition: ntdddisk.h:289
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
BOOLEAN IoRemoteBootClient
Definition: init.c:74
NTSTATUS IopFetchConfigurationInformation(_Out_ PWSTR *SymbolicLinkList, _In_ GUID Guid, _In_ ULONG ExpectedInterfaces, _Out_ PULONG Interfaces)
Definition: iorsrce.c:821
VOID IopStoreSystemPartitionInformation(_In_ PUNICODE_STRING NtSystemPartitionDeviceName, _In_ PUNICODE_STRING OsLoaderPathName)
Definition: iorsrce.c:860
NTSTATUS NTAPI IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN BOOLEAN SingleDisk, OUT PBOOLEAN FoundBoot)
Definition: arcname.c:422
NTSTATUS NTAPI IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: arcname.c:160
UNICODE_STRING IoArcHalDeviceName
Definition: arcname.c:19
UNICODE_STRING IoArcBootDeviceName
Definition: arcname.c:19
NTSTATUS NTAPI IopReassignSystemRoot(IN PLOADER_PARAMETER_BLOCK LoaderBlock, OUT PANSI_STRING NtBootPath)
Definition: arcname.c:848
BOOLEAN IopVerifyDiskSignature(_In_ PDRIVE_LAYOUT_INFORMATION_EX DriveLayout, _In_ PARC_DISK_SIGNATURE ArcDiskSignature, _Out_ PULONG Signature)
Definition: arcname.c:955
PCHAR IoLoaderArcBootDeviceName
Definition: arcname.c:20
NTSTATUS NTAPI IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: arcname.c:39
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1455
PIRP NTAPI IoBuildSynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:1101
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:913
#define IoCallDriver
Definition: irp.c:1257
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3411
NTSTATUS NTAPI NtMakeTemporaryObject(IN HANDLE ObjectHandle)
Definition: oblife.c:1483
#define HalExamineMBR
Definition: part_xbox.c:325
short WCHAR
Definition: pedump.c:58
char CHAR
Definition: pedump.c:57
static PCWSTR TargetName
Definition: ping.c:67
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define OBJ_PERMANENT
Definition: winternl.h:226
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
USHORT MaximumLength
Definition: env_spec_w32.h:377
LIST_ENTRY DiskSignatureListHead
Definition: arc.h:356
ULONG CheckSum
Definition: arc.h:346
PCHAR ArcName
Definition: arc.h:345
BOOLEAN ValidPartitionTable
Definition: arc.h:347
ULONG Signature
Definition: arc.h:344
ULONG BytesPerSector
Definition: ntdddisk.h:404
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define TAG_IO
Definition: tag.h:79
#define STATUS_PENDING
Definition: telnetd.h:14
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_In_opt_ PDEVICE_OBJECT _In_ ULONG _Outptr_result_nullonfailure_ _At_ * SymbolicLinkList(return==0, __drv_allocatesMem(Mem))) PZZWSTR *SymbolicLinkList
#define IoAssignArcName(_ArcName, _DeviceName)
_In_ ULONG _In_ BOOLEAN _Out_ struct _DRIVE_LAYOUT_INFORMATION ** PartitionBuffer
Definition: iofuncs.h:2052
* PFILE_OBJECT
Definition: iotypes.h:1998
@ Executive
Definition: ketypes.h:467
#define ObDereferenceObject
Definition: obfuncs.h:203