ReactOS 0.4.16-dev-2613-g9533ad7
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
29CODE_SEG("INIT")
33 IN BOOLEAN SingleDisk,
34 OUT PBOOLEAN FoundBoot);
35
36CODE_SEG("INIT")
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 /* Create the firmware system loader / HAL partition global name */
55 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName);
56 RtlInitAnsiString(&ArcString, Buffer);
58 if (!NT_SUCCESS(Status))
59 return Status;
60
61 /* Create the OS boot partition global name */
62 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
63 RtlInitAnsiString(&ArcString, Buffer);
65 if (!NT_SUCCESS(Status))
66 return Status;
67
68 /* Allocate memory for the string */
69 Length = strlen(LoaderBlock->ArcBootDeviceName) + sizeof(ANSI_NULL);
71 Length,
72 TAG_IO);
74 {
75 /* Copy the name */
77 LoaderBlock->ArcBootDeviceName,
78 Length);
79 }
80
81 /* Check if we only found a disk, but we're booting from CD-ROM */
82 if ((SingleDisk) && strstr(LoaderBlock->ArcBootDeviceName, "cdrom"))
83 {
84 /* Then disable single-disk mode, since there's a CD drive out there */
85 SingleDisk = FALSE;
86 }
87
88 /* If we are doing remote booting */
90 {
91 /* Yes, we have found boot device */
92 FoundBoot = TRUE;
93
94 /* Get NT device name */
95 RtlInitAnsiString(&LanmanRedirector, "\\Device\\LanmanRedirector");
96 Status = RtlAnsiStringToUnicodeString(&SystemDevice, &LanmanRedirector, TRUE);
97 if (!NT_SUCCESS(Status))
98 {
99 return Status;
100 }
101
102 /* Get ARC booting device name (in net(0) something) */
103 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
104 RtlInitAnsiString(&ArcString, Buffer);
105 Status = RtlAnsiStringToUnicodeString(&BootDeviceName, &ArcString, TRUE);
106 if (NT_SUCCESS(Status))
107 {
108 /* Map ARC to NT name */
109 IoAssignArcName(&BootDeviceName, &SystemDevice);
110 RtlFreeUnicodeString(&BootDeviceName);
111
112 /* Now, get loader path name */
113 RtlInitAnsiString(&LoaderPathNameA, LoaderBlock->NtHalPathName);
114 Status = RtlAnsiStringToUnicodeString(&LoaderPathNameW, &LoaderPathNameA, TRUE);
115 if (!NT_SUCCESS(Status))
116 {
117 RtlFreeUnicodeString(&SystemDevice);
118 return Status;
119 }
120
121 /* And set it has system partition */
122 IopStoreSystemPartitionInformation(&SystemDevice, &LoaderPathNameW);
123 }
124
125 RtlFreeUnicodeString(&SystemDevice);
126
127 /* Don't quit here, even if everything went fine!
128 * We need IopCreateArcNamesDisk to properly map
129 * devices with symlinks.
130 * It will return success if the mapping process went fine
131 * even if it didn't find boot device.
132 * It won't reset boot device finding status as well.
133 */
134 }
135
136 /* Loop every disk and try to find boot disk */
137 Status = IopCreateArcNamesDisk(LoaderBlock, SingleDisk, &FoundBoot);
138 /* If it succeeded but we didn't find boot device, try to browse Cds */
139 if (NT_SUCCESS(Status) && !FoundBoot)
140 {
141 Status = IopCreateArcNamesCd(LoaderBlock);
142 }
143
144 /* Return success */
145 return Status;
146}
147
148CODE_SEG("INIT")
150NTAPI
152{
153 PIRP Irp;
156 PLIST_ENTRY NextEntry;
162 CHAR Buffer[128], ArcBuffer[128];
163 BOOLEAN NotEnabledPresent = FALSE;
165 ANSI_STRING DeviceStringA, ArcNameStringA;
166 PWSTR SymbolicLinkList, lSymbolicLinkList;
167 PARC_DISK_SIGNATURE ArcDiskSignature = NULL;
168 UNICODE_STRING DeviceStringW, ArcNameStringW;
169 ULONG DiskNumber, CdRomCount, CheckSum, i, EnabledDisks = 0;
170 PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation;
171
172 /* Get all the Cds present in the system */
174
175 /* Get enabled Cds and check if result matches
176 * For the record, enabled Cds (or even disk) are Cds/disks
177 * that have been successfully handled by MountMgr driver
178 * and that already own their device name. This is the "new" way
179 * to handle them, that came with NT5.
180 * Currently, Windows 2003 provides an ARC names creation based
181 * on both enabled drives and not enabled drives (lack from
182 * the driver).
183 * Given the current ReactOS state, that's good for us.
184 * To sum up, this is NOT a hack or whatsoever.
185 */
187 GUID_DEVINTERFACE_CDROM,
188 CdRomCount,
189 &EnabledDisks);
190 if (!NT_SUCCESS(Status))
191 {
192 NotEnabledPresent = TRUE;
193 }
194 /* Save symbolic link list address in order to free it after */
195 lSymbolicLinkList = SymbolicLinkList;
196 /* For the moment, we won't fail */
198
199 /* Browse all the ARC devices trying to find the one matching boot device */
200 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
201 NextEntry != &ArcDiskInformation->DiskSignatureListHead;
202 NextEntry = NextEntry->Flink)
203 {
204 ArcDiskSignature = CONTAINING_RECORD(NextEntry,
206 ListEntry);
207
208 if (strcmp(LoaderBlock->ArcBootDeviceName, ArcDiskSignature->ArcName) == 0)
209 {
210 break;
211 }
212
213 ArcDiskSignature = NULL;
214 }
215
216 /* Not found... Not booting from a Cd */
217 if (!ArcDiskSignature)
218 {
219 DPRINT("Failed finding a cd that could match current boot device\n");
220 goto Cleanup;
221 }
222
223 /* Allocate needed space for reading Cd */
225 if (!PartitionBuffer)
226 {
227 DPRINT("Failed allocating resources!\n");
228 /* Here, we fail, BUT we return success, some Microsoft joke */
229 goto Cleanup;
230 }
231
232 /* If we have more enabled Cds, take that into account */
233 if (EnabledDisks > CdRomCount)
234 {
235 CdRomCount = EnabledDisks;
236 }
237
238 /* If we'll have to browse for none enabled Cds, fix higher count */
239 if (NotEnabledPresent && !EnabledDisks)
240 {
241 CdRomCount += 5;
242 }
243
244 /* Finally, if in spite of all that work, we still don't have Cds, leave */
245 if (!CdRomCount)
246 {
247 goto Cleanup;
248 }
249
250 /* Start browsing Cds */
251 for (DiskNumber = 0, EnabledDisks = 0; DiskNumber < CdRomCount; DiskNumber++)
252 {
253 /* Check if we have an enabled disk */
254 if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL)
255 {
256 /* Create its device name using first symbolic link */
257 RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList);
258 /* Then, update symbolic links list */
259 lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR));
260
261 /* Get its associated device object and file object */
262 Status = IoGetDeviceObjectPointer(&DeviceStringW,
264 &FileObject,
265 &DeviceObject);
266 /* Failure? Good bye! */
267 if (!NT_SUCCESS(Status))
268 {
269 goto Cleanup;
270 }
271
272 /* Now, we'll ask the device its device number */
275 NULL,
276 0,
278 sizeof(DeviceNumber),
279 FALSE,
280 &Event,
282 /* Failure? Good bye! */
283 if (!Irp)
284 {
285 /* Dereference file object before leaving */
288 goto Cleanup;
289 }
290
291 /* Call the driver, and wait for it if needed */
294 if (Status == STATUS_PENDING)
295 {
298 }
299 if (!NT_SUCCESS(Status))
300 {
302 goto Cleanup;
303 }
304
305 /* Finally, build proper device name */
306 sprintf(Buffer, "\\Device\\CdRom%lu", DeviceNumber.DeviceNumber);
307 RtlInitAnsiString(&DeviceStringA, Buffer);
308 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
309 if (!NT_SUCCESS(Status))
310 {
312 goto Cleanup;
313 }
314 }
315 else
316 {
317 /* Create device name for the cd */
318 sprintf(Buffer, "\\Device\\CdRom%lu", EnabledDisks++);
319 RtlInitAnsiString(&DeviceStringA, Buffer);
320 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
321 if (!NT_SUCCESS(Status))
322 {
323 goto Cleanup;
324 }
325
326 /* Get its device object */
327 Status = IoGetDeviceObjectPointer(&DeviceStringW,
329 &FileObject,
330 &DeviceObject);
331 if (!NT_SUCCESS(Status))
332 {
333 RtlFreeUnicodeString(&DeviceStringW);
334 goto Cleanup;
335 }
336 }
337
338 /* Initiate data for reading cd and compute checksum */
339 StartingOffset.QuadPart = 0x8000;
340 CheckSum = 0;
344 2048,
346 &Event,
348 if (Irp)
349 {
350 /* Call the driver, and wait for it if needed */
353 if (Status == STATUS_PENDING)
354 {
357 }
358
359 /* If reading succeeded, compute checksum by adding data, 2048 bytes checksum */
360 if (NT_SUCCESS(Status))
361 {
362 for (i = 0; i < 2048 / sizeof(ULONG); i++)
363 {
364 CheckSum += PartitionBuffer[i];
365 }
366 }
367 }
368
369 /* Dereference file object */
371
372 /* If checksums are matching, we have the proper cd */
373 if (CheckSum + ArcDiskSignature->CheckSum == 0)
374 {
375 /* Create ARC name */
376 sprintf(ArcBuffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
377 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
378 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
379 if (NT_SUCCESS(Status))
380 {
381 /* Create symbolic link */
382 IoAssignArcName(&ArcNameStringW, &DeviceStringW);
383 RtlFreeUnicodeString(&ArcNameStringW);
384 DPRINT("Boot device found\n");
385 }
386
387 /* And quit, whatever happens */
388 RtlFreeUnicodeString(&DeviceStringW);
389 goto Cleanup;
390 }
391
392 /* Free string before trying another disk */
393 RtlFreeUnicodeString(&DeviceStringW);
394 }
395
396Cleanup:
397 if (PartitionBuffer)
398 {
400 }
401
403 {
405 }
406
407 return Status;
408}
409
410CODE_SEG("INIT")
412NTAPI
414 IN BOOLEAN SingleDisk,
415 OUT PBOOLEAN FoundBoot)
416{
417 PIRP Irp;
418 PVOID Data;
421 PLIST_ENTRY NextEntry;
423 DISK_GEOMETRY DiskGeometry;
428 CHAR Buffer[128], ArcBuffer[128];
429 BOOLEAN NotEnabledPresent = FALSE;
431 PARC_DISK_SIGNATURE ArcDiskSignature;
432 PWSTR SymbolicLinkList, lSymbolicLinkList;
433 PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL;
434 UNICODE_STRING DeviceStringW, ArcNameStringW, HalPathStringW;
435 ULONG DiskNumber, DiskCount, CheckSum, i, Signature, EnabledDisks = 0;
436 PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation;
437 ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA, HalPathStringA;
438
439 /* Initialise device number */
440 DeviceNumber.DeviceNumber = ULONG_MAX;
441 /* Get all the disks present in the system */
443
444 /* Get enabled disks and check if result matches */
446 GUID_DEVINTERFACE_DISK,
447 DiskCount,
448 &EnabledDisks);
449 if (!NT_SUCCESS(Status))
450 {
451 NotEnabledPresent = TRUE;
452 }
453
454 /* Save symbolic link list address in order to free it after */
455 lSymbolicLinkList = SymbolicLinkList;
456
457 /* Build the boot strings */
458 RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName);
459 RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
460
461 /* If we have more enabled disks, take that into account */
462 if (EnabledDisks > DiskCount)
463 {
464 DiskCount = EnabledDisks;
465 }
466
467 /* If we'll have to browse for none enabled disks, fix higher count */
468 if (NotEnabledPresent && !EnabledDisks)
469 {
470 DiskCount += 20;
471 }
472
473 /* Finally, if in spite of all that work, we still don't have disks, leave */
474 if (!DiskCount)
475 {
476 goto Cleanup;
477 }
478
479 /* Start browsing disks */
480 for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++)
481 {
482 ASSERT(DriveLayout == NULL);
483
484 /* Check if we have an enabled disk */
485 if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL)
486 {
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));
491
492 /* Get its associated device object and file object */
493 Status = IoGetDeviceObjectPointer(&DeviceStringW,
495 &FileObject,
496 &DeviceObject);
497 if (NT_SUCCESS(Status))
498 {
499 /* Now, we'll ask the device its device number */
502 NULL,
503 0,
505 sizeof(DeviceNumber),
506 FALSE,
507 &Event,
509 /* Missing resources is a shame... No need to go farther */
510 if (!Irp)
511 {
514 goto Cleanup;
515 }
516
517 /* Call the driver, and wait for it if needed */
520 if (Status == STATUS_PENDING)
521 {
524 }
525
526 /* If we didn't get the appropriate data, just skip that disk */
527 if (!NT_SUCCESS(Status))
528 {
530 continue;
531 }
532 }
533
534 /* End of enabled disks enumeration */
535 if (NotEnabledPresent && *lSymbolicLinkList == UNICODE_NULL)
536 {
537 /* No enabled disk worked, reset field */
538 if (DeviceNumber.DeviceNumber == ULONG_MAX)
539 {
540 DeviceNumber.DeviceNumber = 0;
541 }
542
543 /* Update disk number to enable the following not enabled disks */
544 if (DeviceNumber.DeviceNumber > DiskNumber)
545 {
546 DiskNumber = DeviceNumber.DeviceNumber;
547 }
548
549 /* Increase a bit more */
550 DiskCount = DiskNumber + 20;
551 }
552 }
553 else
554 {
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))
560 {
561 goto Cleanup;
562 }
563
564 /* Get its device object */
565 Status = IoGetDeviceObjectPointer(&DeviceStringW,
567 &FileObject,
568 &DeviceObject);
569
570 RtlFreeUnicodeString(&DeviceStringW);
571 /* This is a security measure, to ensure DiskNumber will be used */
572 DeviceNumber.DeviceNumber = ULONG_MAX;
573 }
574
575 /* Something failed somewhere earlier, just skip the disk */
576 if (!NT_SUCCESS(Status))
577 {
578 continue;
579 }
580
581 /* Let's ask the disk for its geometry */
584 NULL,
585 0,
586 &DiskGeometry,
587 sizeof(DiskGeometry),
588 FALSE,
589 &Event,
591 /* Missing resources is a shame... No need to go farther */
592 if (!Irp)
593 {
596 goto Cleanup;
597 }
598
599 /* Call the driver, and wait for it if needed */
602 if (Status == STATUS_PENDING)
603 {
606 }
607 /* Failure, skip disk */
608 if (!NT_SUCCESS(Status))
609 {
611 continue;
612 }
613
614 /* Read the partition table */
616 &DriveLayout);
617 if (!NT_SUCCESS(Status))
618 {
620 continue;
621 }
622
623 /* Ensure we have at least 512 bytes per sector */
624 if (DiskGeometry.BytesPerSector < 512)
625 {
626 DiskGeometry.BytesPerSector = 512;
627 }
628
629 /* Check MBR type against EZ Drive type */
630 StartingOffset.QuadPart = 0;
632 if (Data)
633 {
634 /* If MBR is of the EZ Drive type, we'll read after it */
635 StartingOffset.QuadPart = DiskGeometry.BytesPerSector;
637 }
638
639 /* Allocate for reading enough data for checksum */
641 if (!PartitionBuffer)
642 {
645 goto Cleanup;
646 }
647
648 /* Read the first sector for computing checksum */
652 DiskGeometry.BytesPerSector,
654 &Event,
656 if (!Irp)
657 {
661 goto Cleanup;
662 }
663
664 /* Call the driver to perform reading */
667 if (Status == STATUS_PENDING)
668 {
671 }
672
673 /* If reading succeeded, calculate checksum by adding data */
674 if (NT_SUCCESS(Status))
675 {
676 for (i = 0, CheckSum = 0; i < 512 / sizeof(ULONG); i++)
677 {
678 CheckSum += PartitionBuffer[i];
679 }
680 }
681
682 /* Release now unnecessary resources */
685
686 /* If we failed, release drive layout before going to next disk */
687 if (!NT_SUCCESS(Status))
688 {
689 ExFreePool(DriveLayout);
690 DriveLayout = NULL;
691 continue;
692 }
693
694 /* Browse each ARC disk */
695 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
696 NextEntry != &ArcDiskInformation->DiskSignatureListHead;
697 NextEntry = NextEntry->Flink)
698 {
699 ArcDiskSignature = CONTAINING_RECORD(NextEntry,
701 ListEntry);
702
703 /*
704 * If this is the only MBR disk in the ARC list and detected in
705 * the device tree, just go ahead and create the ArcName links.
706 * Otherwise, verify whether the signatures and checksums match
707 * before proceeding.
708 */
709 if ((SingleDisk && (DiskCount == 1) &&
710 (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)) ||
711 (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature) &&
712 (ArcDiskSignature->CheckSum + CheckSum == 0)))
713 {
714 /* Create device name */
715 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0",
716 (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber);
717 RtlInitAnsiString(&DeviceStringA, Buffer);
718 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
719 if (!NT_SUCCESS(Status))
720 {
721 goto Cleanup;
722 }
723
724 /* Create ARC name */
725 sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName);
726 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
727 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
728 if (!NT_SUCCESS(Status))
729 {
730 RtlFreeUnicodeString(&DeviceStringW);
731 goto Cleanup;
732 }
733
734 /* Link both */
735 IoAssignArcName(&ArcNameStringW, &DeviceStringW);
736
737 /* And release strings */
738 RtlFreeUnicodeString(&ArcNameStringW);
739 RtlFreeUnicodeString(&DeviceStringW);
740
741 /* Now, browse each partition */
742 for (i = 1; i <= DriveLayout->PartitionCount; i++)
743 {
744 /* Create device name */
745 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu",
746 (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber, i);
747 RtlInitAnsiString(&DeviceStringA, Buffer);
748 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
749 if (!NT_SUCCESS(Status))
750 {
751 goto Cleanup;
752 }
753
754 /* Create partial ARC name */
755 sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, i);
756 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
757
758 /* Is that boot device? */
759 if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE))
760 {
761 DPRINT("Found boot device\n");
762 *FoundBoot = TRUE;
763 }
764
765 /* Is that system partition? */
766 if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE))
767 {
768 /* Create HAL path name */
769 RtlInitAnsiString(&HalPathStringA, LoaderBlock->NtHalPathName);
770 Status = RtlAnsiStringToUnicodeString(&HalPathStringW, &HalPathStringA, TRUE);
771 if (!NT_SUCCESS(Status))
772 {
773 RtlFreeUnicodeString(&DeviceStringW);
774 goto Cleanup;
775 }
776
777 /* Then store those information to registry */
778 IopStoreSystemPartitionInformation(&DeviceStringW, &HalPathStringW);
779 RtlFreeUnicodeString(&HalPathStringW);
780 }
781
782 /* Create complete ARC name */
783 sprintf(ArcBuffer, "\\ArcName\\%spartition(%lu)", ArcDiskSignature->ArcName, i);
784 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
785 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
786 if (!NT_SUCCESS(Status))
787 {
788 RtlFreeUnicodeString(&DeviceStringW);
789 goto Cleanup;
790 }
791
792 /* Link device name & ARC name */
793 IoAssignArcName(&ArcNameStringW, &DeviceStringW);
794
795 /* Release strings */
796 RtlFreeUnicodeString(&ArcNameStringW);
797 RtlFreeUnicodeString(&DeviceStringW);
798 }
799 }
800 else
801 {
802 /* Debugging feedback: Warn in case there's a valid partition,
803 * a matching signature, BUT a non-matching checksum: this can
804 * be the sign of a duplicate signature, or even worse a virus
805 * played with the partition table. */
806 if (ArcDiskSignature->ValidPartitionTable &&
807 (ArcDiskSignature->Signature == Signature) &&
808 (ArcDiskSignature->CheckSum + CheckSum != 0))
809 {
810 DPRINT("Be careful, you have a duplicate disk signature, or a virus altered your MBR!\n");
811 }
812 }
813 }
814
815 /* Finally, release drive layout */
816 ExFreePool(DriveLayout);
817 DriveLayout = NULL;
818 }
819
821
822Cleanup:
823 if (DriveLayout)
824 {
825 ExFreePool(DriveLayout);
826 }
827
829 {
831 }
832
833 return Status;
834}
835
836CODE_SEG("INIT")
838NTAPI
840 OUT PANSI_STRING NtBootPath)
841{
844 CHAR Buffer[256], AnsiBuffer[256];
845 WCHAR ArcNameBuffer[64];
846 ANSI_STRING TargetString, ArcString, TempString;
847 UNICODE_STRING LinkName, TargetName, ArcName;
848 HANDLE LinkHandle;
849
850 /* Create the Unicode name for the current ARC boot device */
851 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
854 if (!NT_SUCCESS(Status)) return FALSE;
855
856 /* Initialize the attributes and open the link */
858 &TargetName,
860 NULL,
861 NULL);
862 Status = NtOpenSymbolicLinkObject(&LinkHandle,
865 if (!NT_SUCCESS(Status))
866 {
867 /* We failed, free the string */
869 return FALSE;
870 }
871
872 /* Query the current \\SystemRoot */
873 ArcName.Buffer = ArcNameBuffer;
874 ArcName.Length = 0;
875 ArcName.MaximumLength = sizeof(ArcNameBuffer);
876 Status = NtQuerySymbolicLinkObject(LinkHandle, &ArcName, NULL);
877 if (!NT_SUCCESS(Status))
878 {
879 /* We failed, free the string */
881 return FALSE;
882 }
883
884 /* Convert it to Ansi */
885 ArcString.Buffer = AnsiBuffer;
886 ArcString.Length = 0;
887 ArcString.MaximumLength = sizeof(AnsiBuffer);
888 Status = RtlUnicodeStringToAnsiString(&ArcString, &ArcName, FALSE);
889 AnsiBuffer[ArcString.Length] = ANSI_NULL;
890
891 /* Close the link handle and free the name */
892 ObCloseHandle(LinkHandle, KernelMode);
894
895 /* Setup the system root name again */
896 RtlInitAnsiString(&TempString, "\\SystemRoot");
897 Status = RtlAnsiStringToUnicodeString(&LinkName, &TempString, TRUE);
898 if (!NT_SUCCESS(Status)) return FALSE;
899
900 /* Open the symbolic link for it */
902 &LinkName,
904 NULL,
905 NULL);
906 Status = NtOpenSymbolicLinkObject(&LinkHandle,
909 if (!NT_SUCCESS(Status)) return FALSE;
910
911 /* Destroy it */
912 NtMakeTemporaryObject(LinkHandle);
913 ObCloseHandle(LinkHandle, KernelMode);
914
915 /* Now create the new name for it */
916 sprintf(Buffer, "%s%s", ArcString.Buffer, LoaderBlock->NtBootPathName);
917
918 /* Copy it into the passed parameter and null-terminate it */
919 RtlCopyString(NtBootPath, &ArcString);
921
922 /* Setup the Unicode-name for the new symbolic link value */
925 &LinkName,
927 NULL,
928 NULL);
930 if (!NT_SUCCESS(Status)) return FALSE;
931
932 /* Create it */
936 &ArcName);
937
938 /* Free all the strings and close the handle and return success */
939 RtlFreeUnicodeString(&ArcName);
940 RtlFreeUnicodeString(&LinkName);
941 ObCloseHandle(LinkHandle, KernelMode);
942 return TRUE;
943}
944
947 _In_ PDRIVE_LAYOUT_INFORMATION_EX DriveLayout,
948 _In_ PARC_DISK_SIGNATURE ArcDiskSignature,
950{
951 /* Fail if the partition table is invalid */
952 if (!ArcDiskSignature->ValidPartitionTable)
953 return FALSE;
954
955 /* If the partition style is MBR */
956 if (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)
957 {
958 /* Check the MBR signature */
959 if (DriveLayout->Mbr.Signature == ArcDiskSignature->Signature)
960 {
961 /* And return it */
962 if (Signature)
963 *Signature = DriveLayout->Mbr.Signature;
964 return TRUE;
965 }
966 }
967 /* If the partition style is GPT */
968 else if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
969 {
970 /* Verify whether the signature is GPT and compare the GUID */
971 if (ArcDiskSignature->IsGpt &&
972 IsEqualGUID((PGUID)&ArcDiskSignature->GptSignature, &DriveLayout->Gpt.DiskId))
973 {
974 /* There is no signature to return, just zero it */
975 if (Signature)
976 *Signature = 0;
977 return TRUE;
978 }
979 }
980
981 /* If we get there, something went wrong, so fail */
982 return FALSE;
983}
984
985/* EOF */
#define CODE_SEG(...)
unsigned char BOOLEAN
Definition: actypes.h:127
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_ PIRP Irp
Definition: csq.h:116
#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:2983
#define ULONG_MAX
Definition: limits.h:31
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP char *__cdecl strstr(const char *, const char *)
Definition: string.c:3415
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
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:25
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
#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:106
#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
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
BOOLEAN IoRemoteBootClient
Definition: init.c:70
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:413
NTSTATUS NTAPI IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: arcname.c:151
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:839
BOOLEAN IopVerifyDiskSignature(_In_ PDRIVE_LAYOUT_INFORMATION_EX DriveLayout, _In_ PARC_DISK_SIGNATURE ArcDiskSignature, _Out_ PULONG Signature)
Definition: arcname.c:946
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:1446
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:1069
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:881
#define IoCallDriver
Definition: irp.c:1225
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
NTSTATUS NTAPI NtMakeTemporaryObject(IN HANDLE ObjectHandle)
Definition: oblife.c:1473
#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