ReactOS 0.4.15-dev-5672-gf73ac17
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 ArcSystemString, 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 global HAL partition name */
55 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName);
56 RtlInitAnsiString(&ArcString, Buffer);
58 if (!NT_SUCCESS(Status))
59 return Status;
60
61 /* Create the global system partition 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 /* Build the boot strings */
89 RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
90
91 /* If we are doing remote booting */
93 {
94 /* Yes, we have found boot device */
95 FoundBoot = TRUE;
96
97 /* Get NT device name */
98 RtlInitAnsiString(&LanmanRedirector, "\\Device\\LanmanRedirector");
99 Status = RtlAnsiStringToUnicodeString(&SystemDevice, &LanmanRedirector, TRUE);
100 if (!NT_SUCCESS(Status))
101 {
102 return Status;
103 }
104
105 /* Get ARC booting device name (in net(0) something) */
106 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
107 RtlInitAnsiString(&ArcString, Buffer);
108 Status = RtlAnsiStringToUnicodeString(&BootDeviceName, &ArcString, TRUE);
109 if (NT_SUCCESS(Status))
110 {
111 /* Map ARC to NT name */
112 IoAssignArcName(&BootDeviceName, &SystemDevice);
113 RtlFreeUnicodeString(&BootDeviceName);
114
115 /* Now, get loader path name */
116 RtlInitAnsiString(&LoaderPathNameA, LoaderBlock->NtHalPathName);
117 Status = RtlAnsiStringToUnicodeString(&LoaderPathNameW, &LoaderPathNameA, TRUE);
118 if (!NT_SUCCESS(Status))
119 {
120 RtlFreeUnicodeString(&SystemDevice);
121 return Status;
122 }
123
124 /* And set it has system partition */
125 IopStoreSystemPartitionInformation(&SystemDevice, &LoaderPathNameW);
126 }
127
128 RtlFreeUnicodeString(&SystemDevice);
129
130 /* Don't quit here, even if everything went fine!
131 * We need IopCreateArcNamesDisk to properly map
132 * devices with symlinks.
133 * It will return success if the mapping process went fine
134 * even if it didn't find boot device.
135 * It won't reset boot device finding status as well.
136 */
137 }
138
139 /* Loop every disk and try to find boot disk */
140 Status = IopCreateArcNamesDisk(LoaderBlock, SingleDisk, &FoundBoot);
141 /* If it succeeded but we didn't find boot device, try to browse Cds */
142 if (NT_SUCCESS(Status) && !FoundBoot)
143 {
144 Status = IopCreateArcNamesCd(LoaderBlock);
145 }
146
147 /* Return success */
148 return Status;
149}
150
151CODE_SEG("INIT")
153NTAPI
155{
156 PIRP Irp;
159 PLIST_ENTRY NextEntry;
165 CHAR Buffer[128], ArcBuffer[128];
166 BOOLEAN NotEnabledPresent = FALSE;
168 ANSI_STRING DeviceStringA, ArcNameStringA;
169 PWSTR SymbolicLinkList, lSymbolicLinkList;
170 PARC_DISK_SIGNATURE ArcDiskSignature = NULL;
171 UNICODE_STRING DeviceStringW, ArcNameStringW;
172 ULONG DiskNumber, CdRomCount, CheckSum, i, EnabledDisks = 0;
173 PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation;
174
175 /* Get all the Cds present in the system */
177
178 /* Get enabled Cds and check if result matches
179 * For the record, enabled Cds (or even disk) are Cds/disks
180 * that have been successfully handled by MountMgr driver
181 * and that already own their device name. This is the "new" way
182 * to handle them, that came with NT5.
183 * Currently, Windows 2003 provides an ARC names creation based
184 * on both enabled drives and not enabled drives (lack from
185 * the driver).
186 * Given the current ReactOS state, that's good for us.
187 * To sum up, this is NOT a hack or whatsoever.
188 */
190 GUID_DEVINTERFACE_CDROM,
191 CdRomCount,
192 &EnabledDisks);
193 if (!NT_SUCCESS(Status))
194 {
195 NotEnabledPresent = TRUE;
196 }
197 /* Save symbolic link list address in order to free it after */
198 lSymbolicLinkList = SymbolicLinkList;
199 /* For the moment, we won't fail */
201
202 /* Browse all the ARC devices trying to find the one matching boot device */
203 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
204 NextEntry != &ArcDiskInformation->DiskSignatureListHead;
205 NextEntry = NextEntry->Flink)
206 {
207 ArcDiskSignature = CONTAINING_RECORD(NextEntry,
209 ListEntry);
210
211 if (strcmp(LoaderBlock->ArcBootDeviceName, ArcDiskSignature->ArcName) == 0)
212 {
213 break;
214 }
215
216 ArcDiskSignature = NULL;
217 }
218
219 /* Not found... Not booting from a Cd */
220 if (!ArcDiskSignature)
221 {
222 DPRINT("Failed finding a cd that could match current boot device\n");
223 goto Cleanup;
224 }
225
226 /* Allocate needed space for reading Cd */
228 if (!PartitionBuffer)
229 {
230 DPRINT("Failed allocating resources!\n");
231 /* Here, we fail, BUT we return success, some Microsoft joke */
232 goto Cleanup;
233 }
234
235 /* If we have more enabled Cds, take that into account */
236 if (EnabledDisks > CdRomCount)
237 {
238 CdRomCount = EnabledDisks;
239 }
240
241 /* If we'll have to browse for none enabled Cds, fix higher count */
242 if (NotEnabledPresent && !EnabledDisks)
243 {
244 CdRomCount += 5;
245 }
246
247 /* Finally, if in spite of all that work, we still don't have Cds, leave */
248 if (!CdRomCount)
249 {
250 goto Cleanup;
251 }
252
253 /* Start browsing Cds */
254 for (DiskNumber = 0, EnabledDisks = 0; DiskNumber < CdRomCount; DiskNumber++)
255 {
256 /* Check if we have an enabled disk */
257 if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL)
258 {
259 /* Create its device name using first symbolic link */
260 RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList);
261 /* Then, update symbolic links list */
262 lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR));
263
264 /* Get its associated device object and file object */
265 Status = IoGetDeviceObjectPointer(&DeviceStringW,
267 &FileObject,
268 &DeviceObject);
269 /* Failure? Good bye! */
270 if (!NT_SUCCESS(Status))
271 {
272 goto Cleanup;
273 }
274
275 /* Now, we'll ask the device its device number */
278 NULL,
279 0,
281 sizeof(DeviceNumber),
282 FALSE,
283 &Event,
285 /* Failure? Good bye! */
286 if (!Irp)
287 {
288 /* Dereference file object before leaving */
291 goto Cleanup;
292 }
293
294 /* Call the driver, and wait for it if needed */
297 if (Status == STATUS_PENDING)
298 {
301 }
302 if (!NT_SUCCESS(Status))
303 {
305 goto Cleanup;
306 }
307
308 /* Finally, build proper device name */
309 sprintf(Buffer, "\\Device\\CdRom%lu", DeviceNumber.DeviceNumber);
310 RtlInitAnsiString(&DeviceStringA, Buffer);
311 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
312 if (!NT_SUCCESS(Status))
313 {
315 goto Cleanup;
316 }
317 }
318 else
319 {
320 /* Create device name for the cd */
321 sprintf(Buffer, "\\Device\\CdRom%lu", EnabledDisks++);
322 RtlInitAnsiString(&DeviceStringA, Buffer);
323 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
324 if (!NT_SUCCESS(Status))
325 {
326 goto Cleanup;
327 }
328
329 /* Get its device object */
330 Status = IoGetDeviceObjectPointer(&DeviceStringW,
332 &FileObject,
333 &DeviceObject);
334 if (!NT_SUCCESS(Status))
335 {
336 RtlFreeUnicodeString(&DeviceStringW);
337 goto Cleanup;
338 }
339 }
340
341 /* Initiate data for reading cd and compute checksum */
342 StartingOffset.QuadPart = 0x8000;
343 CheckSum = 0;
347 2048,
349 &Event,
351 if (Irp)
352 {
353 /* Call the driver, and wait for it if needed */
356 if (Status == STATUS_PENDING)
357 {
360 }
361
362 /* If reading succeeded, compute checksum by adding data, 2048 bytes checksum */
363 if (NT_SUCCESS(Status))
364 {
365 for (i = 0; i < 2048 / sizeof(ULONG); i++)
366 {
367 CheckSum += PartitionBuffer[i];
368 }
369 }
370 }
371
372 /* Dereference file object */
374
375 /* If checksums are matching, we have the proper cd */
376 if (CheckSum + ArcDiskSignature->CheckSum == 0)
377 {
378 /* Create ARC name */
379 sprintf(ArcBuffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
380 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
381 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
382 if (NT_SUCCESS(Status))
383 {
384 /* Create symbolic link */
385 IoAssignArcName(&ArcNameStringW, &DeviceStringW);
386 RtlFreeUnicodeString(&ArcNameStringW);
387 DPRINT("Boot device found\n");
388 }
389
390 /* And quit, whatever happens */
391 RtlFreeUnicodeString(&DeviceStringW);
392 goto Cleanup;
393 }
394
395 /* Free string before trying another disk */
396 RtlFreeUnicodeString(&DeviceStringW);
397 }
398
399Cleanup:
400 if (PartitionBuffer)
401 {
403 }
404
406 {
408 }
409
410 return Status;
411}
412
413CODE_SEG("INIT")
415NTAPI
417 IN BOOLEAN SingleDisk,
418 OUT PBOOLEAN FoundBoot)
419{
420 PIRP Irp;
421 PVOID Data;
424 PLIST_ENTRY NextEntry;
426 DISK_GEOMETRY DiskGeometry;
431 CHAR Buffer[128], ArcBuffer[128];
432 BOOLEAN NotEnabledPresent = FALSE;
434 PARC_DISK_SIGNATURE ArcDiskSignature;
435 PWSTR SymbolicLinkList, lSymbolicLinkList;
436 PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL;
437 UNICODE_STRING DeviceStringW, ArcNameStringW, HalPathStringW;
438 ULONG DiskNumber, DiskCount, CheckSum, i, Signature, EnabledDisks = 0;
439 PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation;
440 ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA, HalPathStringA;
441
442 /* Initialise device number */
443 DeviceNumber.DeviceNumber = ULONG_MAX;
444 /* Get all the disks present in the system */
446
447 /* Get enabled disks and check if result matches */
449 GUID_DEVINTERFACE_DISK,
450 DiskCount,
451 &EnabledDisks);
452 if (!NT_SUCCESS(Status))
453 {
454 NotEnabledPresent = TRUE;
455 }
456
457 /* Save symbolic link list address in order to free it after */
458 lSymbolicLinkList = SymbolicLinkList;
459
460 /* Build the boot strings */
461 RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName);
462 RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
463
464 /* If we have more enabled disks, take that into account */
465 if (EnabledDisks > DiskCount)
466 {
467 DiskCount = EnabledDisks;
468 }
469
470 /* If we'll have to browse for none enabled disks, fix higher count */
471 if (NotEnabledPresent && !EnabledDisks)
472 {
473 DiskCount += 20;
474 }
475
476 /* Finally, if in spite of all that work, we still don't have disks, leave */
477 if (!DiskCount)
478 {
479 goto Cleanup;
480 }
481
482 /* Start browsing disks */
483 for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++)
484 {
485 ASSERT(DriveLayout == NULL);
486
487 /* Check if we have an enabled disk */
488 if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL)
489 {
490 /* Create its device name using first symbolic link */
491 RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList);
492 /* Then, update symbolic links list */
493 lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR));
494
495 /* Get its associated device object and file object */
496 Status = IoGetDeviceObjectPointer(&DeviceStringW,
498 &FileObject,
499 &DeviceObject);
500 if (NT_SUCCESS(Status))
501 {
502 /* Now, we'll ask the device its device number */
505 NULL,
506 0,
508 sizeof(DeviceNumber),
509 FALSE,
510 &Event,
512 /* Missing resources is a shame... No need to go farther */
513 if (!Irp)
514 {
517 goto Cleanup;
518 }
519
520 /* Call the driver, and wait for it if needed */
523 if (Status == STATUS_PENDING)
524 {
527 }
528
529 /* If we didn't get the appriopriate data, just skip that disk */
530 if (!NT_SUCCESS(Status))
531 {
533 continue;
534 }
535 }
536
537 /* End of enabled disks enumeration */
538 if (NotEnabledPresent && *lSymbolicLinkList == UNICODE_NULL)
539 {
540 /* No enabled disk worked, reset field */
541 if (DeviceNumber.DeviceNumber == ULONG_MAX)
542 {
543 DeviceNumber.DeviceNumber = 0;
544 }
545
546 /* Update disk number to enable the following not enabled disks */
547 if (DeviceNumber.DeviceNumber > DiskNumber)
548 {
549 DiskNumber = DeviceNumber.DeviceNumber;
550 }
551
552 /* Increase a bit more */
553 DiskCount = DiskNumber + 20;
554 }
555 }
556 else
557 {
558 /* Create device name for the disk */
559 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber);
560 RtlInitAnsiString(&DeviceStringA, Buffer);
561 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
562 if (!NT_SUCCESS(Status))
563 {
564 goto Cleanup;
565 }
566
567 /* Get its device object */
568 Status = IoGetDeviceObjectPointer(&DeviceStringW,
570 &FileObject,
571 &DeviceObject);
572
573 RtlFreeUnicodeString(&DeviceStringW);
574 /* This is a security measure, to ensure DiskNumber will be used */
575 DeviceNumber.DeviceNumber = ULONG_MAX;
576 }
577
578 /* Something failed somewhere earlier, just skip the disk */
579 if (!NT_SUCCESS(Status))
580 {
581 continue;
582 }
583
584 /* Let's ask the disk for its geometry */
587 NULL,
588 0,
589 &DiskGeometry,
590 sizeof(DiskGeometry),
591 FALSE,
592 &Event,
594 /* Missing resources is a shame... No need to go farther */
595 if (!Irp)
596 {
599 goto Cleanup;
600 }
601
602 /* Call the driver, and wait for it if needed */
605 if (Status == STATUS_PENDING)
606 {
609 }
610 /* Failure, skip disk */
611 if (!NT_SUCCESS(Status))
612 {
614 continue;
615 }
616
617 /* Read the partition table */
619 &DriveLayout);
620 if (!NT_SUCCESS(Status))
621 {
623 continue;
624 }
625
626 /* Ensure we have at least 512 bytes per sector */
627 if (DiskGeometry.BytesPerSector < 512)
628 {
629 DiskGeometry.BytesPerSector = 512;
630 }
631
632 /* Check MBR type against EZ Drive type */
633 StartingOffset.QuadPart = 0;
634 HalExamineMBR(DeviceObject, DiskGeometry.BytesPerSector, 0x55, &Data);
635 if (Data)
636 {
637 /* If MBR is of the EZ Drive type, we'll read after it */
638 StartingOffset.QuadPart = DiskGeometry.BytesPerSector;
640 }
641
642 /* Allocate for reading enough data for checksum */
644 if (!PartitionBuffer)
645 {
648 goto Cleanup;
649 }
650
651 /* Read the first sector for computing checksum */
655 DiskGeometry.BytesPerSector,
657 &Event,
659 if (!Irp)
660 {
664 goto Cleanup;
665 }
666
667 /* Call the driver to perform reading */
670 if (Status == STATUS_PENDING)
671 {
674 }
675
676 /* If reading succeeded, calculate checksum by adding data */
677 if (NT_SUCCESS(Status))
678 {
679 for (i = 0, CheckSum = 0; i < 512 / sizeof(ULONG); i++)
680 {
681 CheckSum += PartitionBuffer[i];
682 }
683 }
684
685 /* Release now unnecessary resources */
688
689 /* If we failed, release drive layout before going to next disk */
690 if (!NT_SUCCESS(Status))
691 {
692 ExFreePool(DriveLayout);
693 DriveLayout = NULL;
694 continue;
695 }
696
697 /* Browse each ARC disk */
698 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
699 NextEntry != &ArcDiskInformation->DiskSignatureListHead;
700 NextEntry = NextEntry->Flink)
701 {
702 ArcDiskSignature = CONTAINING_RECORD(NextEntry,
704 ListEntry);
705
706 /* If they match, i.e.
707 * - There's only one disk for both BIOS and detected/enabled
708 * - Signatures are matching
709 * - Checksums are matching
710 * - This is MBR
711 */
712 if (((SingleDisk && DiskCount == 1) ||
713 (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature) &&
714 (ArcDiskSignature->CheckSum + CheckSum == 0))) &&
715 (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR))
716 {
717 /* Create device name */
718 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber);
719 RtlInitAnsiString(&DeviceStringA, Buffer);
720 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
721 if (!NT_SUCCESS(Status))
722 {
723 goto Cleanup;
724 }
725
726 /* Create ARC name */
727 sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName);
728 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
729 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
730 if (!NT_SUCCESS(Status))
731 {
732 RtlFreeUnicodeString(&DeviceStringW);
733 goto Cleanup;
734 }
735
736 /* Link both */
737 IoAssignArcName(&ArcNameStringW, &DeviceStringW);
738
739 /* And release resources */
740 RtlFreeUnicodeString(&ArcNameStringW);
741 RtlFreeUnicodeString(&DeviceStringW);
742
743 /* Now, browse for every partition */
744 for (i = 1; i <= DriveLayout->PartitionCount; i++)
745 {
746 /* Create device name */
747 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber, i);
748 RtlInitAnsiString(&DeviceStringA, Buffer);
749 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
750 if (!NT_SUCCESS(Status))
751 {
752 goto Cleanup;
753 }
754
755 /* Create partial ARC name */
756 sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, i);
757 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
758
759 /* Is that boot device? */
760 if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE))
761 {
762 DPRINT("Found boot device\n");
763 *FoundBoot = TRUE;
764 }
765
766 /* Is that system partition? */
767 if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE))
768 {
769 /* Create HAL path name */
770 RtlInitAnsiString(&HalPathStringA, LoaderBlock->NtHalPathName);
771 Status = RtlAnsiStringToUnicodeString(&HalPathStringW, &HalPathStringA, TRUE);
772 if (!NT_SUCCESS(Status))
773 {
774 RtlFreeUnicodeString(&DeviceStringW);
775 goto Cleanup;
776 }
777
778 /* Then store those information to registry */
779 IopStoreSystemPartitionInformation(&DeviceStringW, &HalPathStringW);
780 RtlFreeUnicodeString(&HalPathStringW);
781 }
782
783 /* Create complete ARC name */
784 sprintf(ArcBuffer, "\\ArcName\\%spartition(%lu)", ArcDiskSignature->ArcName, i);
785 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
786 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
787 if (!NT_SUCCESS(Status))
788 {
789 RtlFreeUnicodeString(&DeviceStringW);
790 goto Cleanup;
791 }
792
793 /* Link device name & ARC name */
794 IoAssignArcName(&ArcNameStringW, &DeviceStringW);
795
796 /* Release strings */
797 RtlFreeUnicodeString(&ArcNameStringW);
798 RtlFreeUnicodeString(&DeviceStringW);
799 }
800 }
801 else
802 {
803 /* Debugging feedback: Warn in case there's a valid partition,
804 * a matching signature, BUT a non-matching checksum: this can
805 * be the sign of a duplicate signature, or even worse a virus
806 * played with the partition table. */
807 if (ArcDiskSignature->ValidPartitionTable &&
808 (ArcDiskSignature->Signature == Signature) &&
809 (ArcDiskSignature->CheckSum + CheckSum != 0))
810 {
811 DPRINT("Be careful, you have a duplicate disk signature, or a virus altered your MBR!\n");
812 }
813 }
814 }
815
816 /* Finally, release drive layout */
817 ExFreePool(DriveLayout);
818 DriveLayout = NULL;
819 }
820
822
823Cleanup:
824 if (DriveLayout)
825 {
826 ExFreePool(DriveLayout);
827 }
828
830 {
832 }
833
834 return Status;
835}
836
837CODE_SEG("INIT")
839NTAPI
841 OUT PANSI_STRING NtBootPath)
842{
845 CHAR Buffer[256], AnsiBuffer[256];
846 WCHAR ArcNameBuffer[64];
847 ANSI_STRING TargetString, ArcString, TempString;
848 UNICODE_STRING LinkName, TargetName, ArcName;
849 HANDLE LinkHandle;
850
851 /* Create the Unicode name for the current ARC boot device */
852 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
855 if (!NT_SUCCESS(Status)) return FALSE;
856
857 /* Initialize the attributes and open the link */
859 &TargetName,
861 NULL,
862 NULL);
863 Status = NtOpenSymbolicLinkObject(&LinkHandle,
866 if (!NT_SUCCESS(Status))
867 {
868 /* We failed, free the string */
870 return FALSE;
871 }
872
873 /* Query the current \\SystemRoot */
874 ArcName.Buffer = ArcNameBuffer;
875 ArcName.Length = 0;
876 ArcName.MaximumLength = sizeof(ArcNameBuffer);
877 Status = NtQuerySymbolicLinkObject(LinkHandle, &ArcName, NULL);
878 if (!NT_SUCCESS(Status))
879 {
880 /* We failed, free the string */
882 return FALSE;
883 }
884
885 /* Convert it to Ansi */
886 ArcString.Buffer = AnsiBuffer;
887 ArcString.Length = 0;
888 ArcString.MaximumLength = sizeof(AnsiBuffer);
889 Status = RtlUnicodeStringToAnsiString(&ArcString, &ArcName, FALSE);
890 AnsiBuffer[ArcString.Length] = ANSI_NULL;
891
892 /* Close the link handle and free the name */
893 ObCloseHandle(LinkHandle, KernelMode);
895
896 /* Setup the system root name again */
897 RtlInitAnsiString(&TempString, "\\SystemRoot");
898 Status = RtlAnsiStringToUnicodeString(&LinkName, &TempString, TRUE);
899 if (!NT_SUCCESS(Status)) return FALSE;
900
901 /* Open the symbolic link for it */
903 &LinkName,
905 NULL,
906 NULL);
907 Status = NtOpenSymbolicLinkObject(&LinkHandle,
910 if (!NT_SUCCESS(Status)) return FALSE;
911
912 /* Destroy it */
913 NtMakeTemporaryObject(LinkHandle);
914 ObCloseHandle(LinkHandle, KernelMode);
915
916 /* Now create the new name for it */
917 sprintf(Buffer, "%s%s", ArcString.Buffer, LoaderBlock->NtBootPathName);
918
919 /* Copy it into the passed parameter and null-terminate it */
920 RtlCopyString(NtBootPath, &ArcString);
922
923 /* Setup the Unicode-name for the new symbolic link value */
926 &LinkName,
928 NULL,
929 NULL);
931 if (!NT_SUCCESS(Status)) return FALSE;
932
933 /* Create it */
937 &ArcName);
938
939 /* Free all the strings and close the handle and return success */
940 RtlFreeUnicodeString(&ArcName);
941 RtlFreeUnicodeString(&LinkName);
942 ObCloseHandle(LinkHandle, KernelMode);
943 return TRUE;
944}
945
947NTAPI
948IopVerifyDiskSignature(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout,
949 IN PARC_DISK_SIGNATURE ArcDiskSignature,
951{
952 /* First condition: having a valid partition table */
953 if (!ArcDiskSignature->ValidPartitionTable)
954 {
955 return FALSE;
956 }
957
958 /* If that partition table is the MBR */
959 if (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)
960 {
961 /* Then check MBR signature */
962 if (DriveLayout->Mbr.Signature == ArcDiskSignature->Signature)
963 {
964 /* And return it */
965 if (Signature)
966 {
967 *Signature = DriveLayout->Mbr.Signature;
968 }
969
970 return TRUE;
971 }
972 }
973 /* If that partition table is the GPT */
974 else if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
975 {
976 /* Check we are using GPT and compare GUID */
977 if (ArcDiskSignature->IsGpt &&
978 (((PULONG)ArcDiskSignature->GptSignature)[0] == DriveLayout->Gpt.DiskId.Data1 &&
979 ((PUSHORT)ArcDiskSignature->GptSignature)[2] == DriveLayout->Gpt.DiskId.Data2 &&
980 ((PUSHORT)ArcDiskSignature->GptSignature)[3] == DriveLayout->Gpt.DiskId.Data3 &&
981 ((PULONGLONG)ArcDiskSignature->GptSignature)[1] == ((PULONGLONG)DriveLayout->Gpt.DiskId.Data4)[0]))
982 {
983 /* There's no signature to give, so we just zero output */
984 if (Signature)
985 {
986 *Signature = 0;
987 }
988 return TRUE;
989 }
990 }
991
992 /* If we fall here, it means that something went wrong, so return that */
993 return FALSE;
994}
995
996/* EOF */
unsigned char BOOLEAN
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
LONG NTSTATUS
Definition: precomp.h:26
CHAR AnsiBuffer[1024]
Definition: debug.c:15
_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:32
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, IN PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
Definition: fstubex.c:2273
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
#define ULONG_MAX
Definition: limits.h:44
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define OBJ_PERMANENT
Definition: winternl.h:226
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Definition: iorsrce.c:830
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
@ PARTITION_STYLE_GPT
Definition: imports.h:202
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define KernelMode
Definition: asm.h:34
#define SYMBOLIC_LINK_ALL_ACCESS
Definition: nt_native.h:1267
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)
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
#define UNICODE_NULL
#define ANSI_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
@ NotificationEvent
BOOLEAN IoRemoteBootClient
Definition: init.c:70
VOID NTAPI IopStoreSystemPartitionInformation(IN PUNICODE_STRING NtSystemPartitionDeviceName, IN PUNICODE_STRING OsLoaderPathName)
Definition: iorsrce.c:697
NTSTATUS NTAPI IopFetchConfigurationInformation(OUT PWSTR *SymbolicLinkList, IN GUID Guid, IN ULONG ExpectedInterfaces, IN PULONG Interfaces)
Definition: iorsrce.c:656
NTSTATUS NTAPI IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN BOOLEAN SingleDisk, OUT PBOOLEAN FoundBoot)
Definition: arcname.c:416
NTSTATUS NTAPI IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: arcname.c:154
UNICODE_STRING IoArcHalDeviceName
Definition: arcname.c:19
BOOLEAN NTAPI IopVerifyDiskSignature(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout, IN PARC_DISK_SIGNATURE ArcDiskSignature, OUT PULONG Signature)
Definition: arcname.c:948
UNICODE_STRING IoArcBootDeviceName
Definition: arcname.c:19
NTSTATUS NTAPI IopReassignSystemRoot(IN PLOADER_PARAMETER_BLOCK LoaderBlock, OUT PANSI_STRING NtBootPath)
Definition: arcname.c:840
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:1435
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
#define STATUS_PENDING
Definition: ntstatus.h:82
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
NTSTATUS NTAPI NtMakeTemporaryObject(IN HANDLE ObjectHandle)
Definition: oblife.c:1385
#define HalExamineMBR
Definition: part_xbox.c:325
static PCWSTR TargetName
Definition: ping.c:67
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
USHORT MaximumLength
Definition: env_spec_w32.h:377
LIST_ENTRY DiskSignatureListHead
Definition: arc.h:221
ULONG CheckSum
Definition: arc.h:211
PCHAR ArcName
Definition: arc.h:210
BOOLEAN ValidPartitionTable
Definition: arc.h:212
ULONG Signature
Definition: arc.h:209
ULONG BytesPerSector
Definition: ntdddisk.h:409
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:80
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
uint16_t * PUSHORT
Definition: typedefs.h:56
#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:2055
_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:403
#define ObDereferenceObject
Definition: obfuncs.h:203
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175