ReactOS  0.4.15-dev-3193-g74513a7
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  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 
151 CODE_SEG("INIT")
152 NTSTATUS
153 NTAPI
155 {
156  PIRP Irp;
157  KEVENT Event;
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 */
277  DeviceObject,
278  NULL,
279  0,
280  &DeviceNumber,
281  sizeof(DeviceNumber),
282  FALSE,
283  &Event,
284  &IoStatusBlock);
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;
345  DeviceObject,
347  2048,
349  &Event,
350  &IoStatusBlock);
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  {
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 
399 Cleanup:
400  if (PartitionBuffer)
401  {
403  }
404 
405  if (SymbolicLinkList)
406  {
408  }
409 
410  return Status;
411 }
412 
413 CODE_SEG("INIT")
414 NTSTATUS
415 NTAPI
417  IN BOOLEAN SingleDisk,
418  OUT PBOOLEAN FoundBoot)
419 {
420  PIRP Irp;
421  PVOID Data;
422  KEVENT Event;
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 */
504  DeviceObject,
505  NULL,
506  0,
507  &DeviceNumber,
508  sizeof(DeviceNumber),
509  FALSE,
510  &Event,
511  &IoStatusBlock);
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 */
586  DeviceObject,
587  NULL,
588  0,
589  &DiskGeometry,
590  sizeof(DiskGeometry),
591  FALSE,
592  &Event,
593  &IoStatusBlock);
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;
639  ExFreePool(Data);
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 */
653  DeviceObject,
655  DiskGeometry.BytesPerSector,
657  &Event,
658  &IoStatusBlock);
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  {
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 
823 Cleanup:
824  if (DriveLayout)
825  {
826  ExFreePool(DriveLayout);
827  }
828 
829  if (SymbolicLinkList)
830  {
832  }
833 
834  return Status;
835 }
836 
837 CODE_SEG("INIT")
838 NTSTATUS
839 NTAPI
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);
921  Buffer[strlen(Buffer) - 1] = ANSI_NULL;
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 */
934  Status = NtCreateSymbolicLinkObject(&LinkHandle,
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 
946 BOOLEAN
947 NTAPI
948 IopVerifyDiskSignature(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 */
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:948
#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:416
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:154
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:840
_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
_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
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
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