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