ReactOS 0.4.16-dev-303-g11d5cb8
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 appropriate 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 /*
707 * If this is the only MBR disk in the ARC list and detected
708 * in the device tree, just go ahead and create the ArcName link.
709 * Otherwise, check whether the signatures and checksums match
710 * before creating the ArcName link.
711 */
712 if ((SingleDisk && (DiskCount == 1) &&
713 (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)) ||
714 (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature) &&
715 (ArcDiskSignature->CheckSum + CheckSum == 0)))
716 {
717 /* Create device name */
718 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0",
719 (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber);
720 RtlInitAnsiString(&DeviceStringA, Buffer);
721 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
722 if (!NT_SUCCESS(Status))
723 {
724 goto Cleanup;
725 }
726
727 /* Create ARC name */
728 sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName);
729 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
730 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
731 if (!NT_SUCCESS(Status))
732 {
733 RtlFreeUnicodeString(&DeviceStringW);
734 goto Cleanup;
735 }
736
737 /* Link both */
738 IoAssignArcName(&ArcNameStringW, &DeviceStringW);
739
740 /* And release strings */
741 RtlFreeUnicodeString(&ArcNameStringW);
742 RtlFreeUnicodeString(&DeviceStringW);
743
744 /* Now, browse each partition */
745 for (i = 1; i <= DriveLayout->PartitionCount; i++)
746 {
747 /* Create device name */
748 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu",
749 (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber, i);
750 RtlInitAnsiString(&DeviceStringA, Buffer);
751 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
752 if (!NT_SUCCESS(Status))
753 {
754 goto Cleanup;
755 }
756
757 /* Create partial ARC name */
758 sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, i);
759 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
760
761 /* Is that boot device? */
762 if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE))
763 {
764 DPRINT("Found boot device\n");
765 *FoundBoot = TRUE;
766 }
767
768 /* Is that system partition? */
769 if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE))
770 {
771 /* Create HAL path name */
772 RtlInitAnsiString(&HalPathStringA, LoaderBlock->NtHalPathName);
773 Status = RtlAnsiStringToUnicodeString(&HalPathStringW, &HalPathStringA, TRUE);
774 if (!NT_SUCCESS(Status))
775 {
776 RtlFreeUnicodeString(&DeviceStringW);
777 goto Cleanup;
778 }
779
780 /* Then store those information to registry */
781 IopStoreSystemPartitionInformation(&DeviceStringW, &HalPathStringW);
782 RtlFreeUnicodeString(&HalPathStringW);
783 }
784
785 /* Create complete ARC name */
786 sprintf(ArcBuffer, "\\ArcName\\%spartition(%lu)", ArcDiskSignature->ArcName, i);
787 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
788 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
789 if (!NT_SUCCESS(Status))
790 {
791 RtlFreeUnicodeString(&DeviceStringW);
792 goto Cleanup;
793 }
794
795 /* Link device name & ARC name */
796 IoAssignArcName(&ArcNameStringW, &DeviceStringW);
797
798 /* Release strings */
799 RtlFreeUnicodeString(&ArcNameStringW);
800 RtlFreeUnicodeString(&DeviceStringW);
801 }
802 }
803 else
804 {
805 /* Debugging feedback: Warn in case there's a valid partition,
806 * a matching signature, BUT a non-matching checksum: this can
807 * be the sign of a duplicate signature, or even worse a virus
808 * played with the partition table. */
809 if (ArcDiskSignature->ValidPartitionTable &&
810 (ArcDiskSignature->Signature == Signature) &&
811 (ArcDiskSignature->CheckSum + CheckSum != 0))
812 {
813 DPRINT("Be careful, you have a duplicate disk signature, or a virus altered your MBR!\n");
814 }
815 }
816 }
817
818 /* Finally, release drive layout */
819 ExFreePool(DriveLayout);
820 DriveLayout = NULL;
821 }
822
824
825Cleanup:
826 if (DriveLayout)
827 {
828 ExFreePool(DriveLayout);
829 }
830
832 {
834 }
835
836 return Status;
837}
838
839CODE_SEG("INIT")
841NTAPI
843 OUT PANSI_STRING NtBootPath)
844{
847 CHAR Buffer[256], AnsiBuffer[256];
848 WCHAR ArcNameBuffer[64];
849 ANSI_STRING TargetString, ArcString, TempString;
850 UNICODE_STRING LinkName, TargetName, ArcName;
851 HANDLE LinkHandle;
852
853 /* Create the Unicode name for the current ARC boot device */
854 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
857 if (!NT_SUCCESS(Status)) return FALSE;
858
859 /* Initialize the attributes and open the link */
861 &TargetName,
863 NULL,
864 NULL);
865 Status = NtOpenSymbolicLinkObject(&LinkHandle,
868 if (!NT_SUCCESS(Status))
869 {
870 /* We failed, free the string */
872 return FALSE;
873 }
874
875 /* Query the current \\SystemRoot */
876 ArcName.Buffer = ArcNameBuffer;
877 ArcName.Length = 0;
878 ArcName.MaximumLength = sizeof(ArcNameBuffer);
879 Status = NtQuerySymbolicLinkObject(LinkHandle, &ArcName, NULL);
880 if (!NT_SUCCESS(Status))
881 {
882 /* We failed, free the string */
884 return FALSE;
885 }
886
887 /* Convert it to Ansi */
888 ArcString.Buffer = AnsiBuffer;
889 ArcString.Length = 0;
890 ArcString.MaximumLength = sizeof(AnsiBuffer);
891 Status = RtlUnicodeStringToAnsiString(&ArcString, &ArcName, FALSE);
892 AnsiBuffer[ArcString.Length] = ANSI_NULL;
893
894 /* Close the link handle and free the name */
895 ObCloseHandle(LinkHandle, KernelMode);
897
898 /* Setup the system root name again */
899 RtlInitAnsiString(&TempString, "\\SystemRoot");
900 Status = RtlAnsiStringToUnicodeString(&LinkName, &TempString, TRUE);
901 if (!NT_SUCCESS(Status)) return FALSE;
902
903 /* Open the symbolic link for it */
905 &LinkName,
907 NULL,
908 NULL);
909 Status = NtOpenSymbolicLinkObject(&LinkHandle,
912 if (!NT_SUCCESS(Status)) return FALSE;
913
914 /* Destroy it */
915 NtMakeTemporaryObject(LinkHandle);
916 ObCloseHandle(LinkHandle, KernelMode);
917
918 /* Now create the new name for it */
919 sprintf(Buffer, "%s%s", ArcString.Buffer, LoaderBlock->NtBootPathName);
920
921 /* Copy it into the passed parameter and null-terminate it */
922 RtlCopyString(NtBootPath, &ArcString);
924
925 /* Setup the Unicode-name for the new symbolic link value */
928 &LinkName,
930 NULL,
931 NULL);
933 if (!NT_SUCCESS(Status)) return FALSE;
934
935 /* Create it */
939 &ArcName);
940
941 /* Free all the strings and close the handle and return success */
942 RtlFreeUnicodeString(&ArcName);
943 RtlFreeUnicodeString(&LinkName);
944 ObCloseHandle(LinkHandle, KernelMode);
945 return TRUE;
946}
947
950 _In_ PDRIVE_LAYOUT_INFORMATION_EX DriveLayout,
951 _In_ PARC_DISK_SIGNATURE ArcDiskSignature,
953{
954 /* Fail if the partition table is invalid */
955 if (!ArcDiskSignature->ValidPartitionTable)
956 return FALSE;
957
958 /* If the partition style is MBR */
959 if (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)
960 {
961 /* Check the MBR signature */
962 if (DriveLayout->Mbr.Signature == ArcDiskSignature->Signature)
963 {
964 /* And return it */
965 if (Signature)
966 *Signature = DriveLayout->Mbr.Signature;
967 return TRUE;
968 }
969 }
970 /* If the partition style is GPT */
971 else if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
972 {
973 /* Verify whether the signature is GPT and compare the GUID */
974 if (ArcDiskSignature->IsGpt &&
975 IsEqualGUID((PGUID)&ArcDiskSignature->GptSignature, &DriveLayout->Gpt.DiskId))
976 {
977 /* There is no signature to return, just zero it */
978 if (Signature)
979 *Signature = 0;
980 return TRUE;
981 }
982 }
983
984 /* If we get there, something went wrong, so fail */
985 return FALSE;
986}
987
988/* EOF */
#define CODE_SEG(...)
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 STATUS_PENDING
Definition: d3dkmdt.h:43
#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
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:2279
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
_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
#define ULONG_MAX
Definition: intsafe.h:155
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(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 _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#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)
#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
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:416
NTSTATUS NTAPI IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: arcname.c:154
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:842
BOOLEAN IopVerifyDiskSignature(_In_ PDRIVE_LAYOUT_INFORMATION_EX DriveLayout, _In_ PARC_DISK_SIGNATURE ArcDiskSignature, _Out_ PULONG Signature)
Definition: arcname.c:949
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
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
static PCWSTR TargetName
Definition: ping.c:67
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#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:268
ULONG CheckSum
Definition: arc.h:258
PCHAR ArcName
Definition: arc.h:257
BOOLEAN ValidPartitionTable
Definition: arc.h:259
ULONG Signature
Definition: arc.h:256
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: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
#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:415
#define ObDereferenceObject
Definition: obfuncs.h:203
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175