ReactOS  0.4.14-dev-583-g2a1ba2c
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 INIT_FUNCTION
26 NTAPI
28 );
29 
30 INIT_FUNCTION
32 NTAPI
34  IN BOOLEAN SingleDisk,
35  IN PBOOLEAN FoundBoot
36 );
37 
38 INIT_FUNCTION
40 NTAPI
42 {
43  SIZE_T Length;
45  CHAR Buffer[128];
46  BOOLEAN SingleDisk;
47  BOOLEAN FoundBoot = FALSE;
48  UNICODE_STRING SystemDevice, LoaderPathNameW, BootDeviceName;
49  PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation;
50  ANSI_STRING ArcSystemString, ArcString, LanmanRedirector, LoaderPathNameA;
51 
52  /* Check if we only have one disk on the machine */
53  SingleDisk = ArcDiskInfo->DiskSignatureListHead.Flink->Flink ==
54  (&ArcDiskInfo->DiskSignatureListHead);
55 
56  /* Create the global HAL partition name */
57  sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName);
58  RtlInitAnsiString(&ArcString, Buffer);
60 
61  /* Create the global system partition name */
62  sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
63  RtlInitAnsiString(&ArcString, Buffer);
65 
66  /* Allocate memory for the string */
67  Length = strlen(LoaderBlock->ArcBootDeviceName) + sizeof(ANSI_NULL);
69  Length,
70  TAG_IO);
72  {
73  /* Copy the name */
75  LoaderBlock->ArcBootDeviceName,
76  Length);
77  }
78 
79  /* Check if we only found a disk, but we're booting from CD-ROM */
80  if ((SingleDisk) && strstr(LoaderBlock->ArcBootDeviceName, "cdrom"))
81  {
82  /* Then disable single-disk mode, since there's a CD drive out there */
83  SingleDisk = FALSE;
84  }
85 
86  /* Build the boot strings */
87  RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
88 
89  /* If we are doing remote booting */
91  {
92  /* Yes, we have found boot device */
93  FoundBoot = TRUE;
94 
95  /* Get NT device name */
96  RtlInitAnsiString(&LanmanRedirector, "\\Device\\LanmanRedirector");
97  Status = RtlAnsiStringToUnicodeString(&SystemDevice, &LanmanRedirector, TRUE);
98  if (!NT_SUCCESS(Status))
99  {
100  return Status;
101  }
102 
103  /* Get ARC booting device name (in net(0) something) */
104  sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
105  RtlInitAnsiString(&ArcString, Buffer);
106  Status = RtlAnsiStringToUnicodeString(&BootDeviceName, &ArcString, TRUE);
107  if (NT_SUCCESS(Status))
108  {
109  /* Map ARC to NT name */
110  IoAssignArcName(&BootDeviceName, &SystemDevice);
111  RtlFreeUnicodeString(&BootDeviceName);
112 
113  /* Now, get loader path name */
114  RtlInitAnsiString(&LoaderPathNameA, LoaderBlock->NtHalPathName);
115  Status = RtlAnsiStringToUnicodeString(&LoaderPathNameW, &LoaderPathNameA, TRUE);
116  if (!NT_SUCCESS(Status))
117  {
118  RtlFreeUnicodeString(&SystemDevice);
119  return Status;
120  }
121 
122  /* And set it has system partition */
123  IopStoreSystemPartitionInformation(&SystemDevice, &LoaderPathNameW);
124  }
125 
126  RtlFreeUnicodeString(&SystemDevice);
127 
128  /* Don't quit here, even if everything went fine!
129  * We need IopCreateArcNamesDisk to properly map
130  * devices with symlinks.
131  * It will return success if the mapping process went fine
132  * even if it didn't find boot device.
133  * It won't reset boot device finding status as well.
134  */
135  }
136 
137  /* Loop every disk and try to find boot disk */
138  Status = IopCreateArcNamesDisk(LoaderBlock, SingleDisk, &FoundBoot);
139  /* If it succeed but we didn't find boot device, try to browse Cds */
140  if (NT_SUCCESS(Status) && !FoundBoot)
141  {
142  Status = IopCreateArcNamesCd(LoaderBlock);
143  }
144 
145  /* Return success */
146  return Status;
147 }
148 
149 INIT_FUNCTION
150 NTSTATUS
151 NTAPI
153 {
154  PIRP Irp;
155  KEVENT Event;
157  PLIST_ENTRY NextEntry;
163  CHAR Buffer[128], ArcBuffer[128];
164  BOOLEAN NotEnabledPresent = FALSE;
166  ANSI_STRING DeviceStringA, ArcNameStringA;
167  PWSTR SymbolicLinkList, lSymbolicLinkList;
168  PARC_DISK_SIGNATURE ArcDiskSignature = NULL;
169  UNICODE_STRING DeviceStringW, ArcNameStringW;
170  ULONG DiskNumber, CdRomCount, CheckSum, i, EnabledDisks = 0;
171  PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation;
172 
173  /* Get all the Cds present in the system */
175 
176  /* Get enabled Cds and check if result matches
177  * For the record, enabled Cds (or even disk) are Cds/disks
178  * that have been successfully handled by MountMgr driver
179  * and that already own their device name. This is the "new" way
180  * to handle them, that came with NT5.
181  * Currently, Windows 2003 provides an arc names creation based
182  * on both enabled drives and not enabled drives (lack from
183  * the driver).
184  * Given the current ReactOS state, that's good for us.
185  * To sum up, this is NOT a hack or whatsoever.
186  */
188  GUID_DEVINTERFACE_CDROM,
189  CdRomCount,
190  &EnabledDisks);
191  if (!NT_SUCCESS(Status))
192  {
193  NotEnabledPresent = TRUE;
194  }
195  /* Save symbolic link list address in order to free it after */
196  lSymbolicLinkList = SymbolicLinkList;
197  /* For the moment, we won't fail */
199 
200  /* Browse all the ARC devices trying to find the one matching boot device */
201  for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
202  NextEntry != &ArcDiskInformation->DiskSignatureListHead;
203  NextEntry = NextEntry->Flink)
204  {
205  ArcDiskSignature = CONTAINING_RECORD(NextEntry,
207  ListEntry);
208 
209  if (strcmp(LoaderBlock->ArcBootDeviceName, ArcDiskSignature->ArcName) == 0)
210  {
211  break;
212  }
213 
214  ArcDiskSignature = NULL;
215  }
216 
217  /* Not found... Not booting from a Cd */
218  if (!ArcDiskSignature)
219  {
220  DPRINT("Failed finding a cd that could match current boot device\n");
221  goto Cleanup;
222  }
223 
224  /* Allocate needed space for reading Cd */
226  if (!PartitionBuffer)
227  {
228  DPRINT("Failed allocating resources!\n");
229  /* Here, we fail, BUT we return success, some Microsoft joke */
230  goto Cleanup;
231  }
232 
233  /* If we have more enabled Cds, take that into account */
234  if (EnabledDisks > CdRomCount)
235  {
236  CdRomCount = EnabledDisks;
237  }
238 
239  /* If we'll have to browse for none enabled Cds, fix higher count */
240  if (NotEnabledPresent && !EnabledDisks)
241  {
242  CdRomCount += 5;
243  }
244 
245  /* Finally, if in spite of all that work, we still don't have Cds, leave */
246  if (!CdRomCount)
247  {
248  goto Cleanup;
249  }
250 
251  /* Start browsing Cds */
252  for (DiskNumber = 0, EnabledDisks = 0; DiskNumber < CdRomCount; DiskNumber++)
253  {
254  /* Check if we have an enabled disk */
255  if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL)
256  {
257  /* Create its device name using first symbolic link */
258  RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList);
259  /* Then, update symbolic links list */
260  lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR));
261 
262  /* Get its associated device object and file object */
263  Status = IoGetDeviceObjectPointer(&DeviceStringW,
265  &FileObject,
266  &DeviceObject);
267  /* Failure? Good bye! */
268  if (!NT_SUCCESS(Status))
269  {
270  goto Cleanup;
271  }
272 
273  /* Now, we'll ask the device its device number */
275  DeviceObject,
276  NULL,
277  0,
278  &DeviceNumber,
279  sizeof(STORAGE_DEVICE_NUMBER),
280  FALSE,
281  &Event,
282  &IoStatusBlock);
283  /* Failure? Good bye! */
284  if (!Irp)
285  {
286  /* Dereference file object before leaving */
289  goto Cleanup;
290  }
291 
292  /* Call the driver, and wait for it if needed */
295  if (Status == STATUS_PENDING)
296  {
299  }
300  if (!NT_SUCCESS(Status))
301  {
303  goto Cleanup;
304  }
305 
306  /* Finally, build proper device name */
307  sprintf(Buffer, "\\Device\\CdRom%lu", DeviceNumber.DeviceNumber);
308  RtlInitAnsiString(&DeviceStringA, Buffer);
309  Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
310  if (!NT_SUCCESS(Status))
311  {
313  goto Cleanup;
314  }
315  }
316  else
317  {
318  /* Create device name for the cd */
319  sprintf(Buffer, "\\Device\\CdRom%lu", EnabledDisks++);
320  RtlInitAnsiString(&DeviceStringA, Buffer);
321  Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
322  if (!NT_SUCCESS(Status))
323  {
324  goto Cleanup;
325  }
326 
327  /* Get its device object */
328  Status = IoGetDeviceObjectPointer(&DeviceStringW,
330  &FileObject,
331  &DeviceObject);
332  if (!NT_SUCCESS(Status))
333  {
334  RtlFreeUnicodeString(&DeviceStringW);
335  goto Cleanup;
336  }
337  }
338 
339  /* Initiate data for reading cd and compute checksum */
340  StartingOffset.QuadPart = 0x8000;
341  CheckSum = 0;
343  DeviceObject,
345  2048,
347  &Event,
348  &IoStatusBlock);
349  if (Irp)
350  {
351  /* Call the driver, and wait for it if needed */
354  if (Status == STATUS_PENDING)
355  {
358  }
359 
360  /* Reading succeed, compute checksum by adding data, 2048 bytes checksum */
361  if (NT_SUCCESS(Status))
362  {
363  for (i = 0; i < 2048 / sizeof(ULONG); i++)
364  {
366  }
367  }
368  }
369 
370  /* Dereference file object */
372 
373  /* If checksums are matching, we have the proper cd */
374  if (CheckSum + ArcDiskSignature->CheckSum == 0)
375  {
376  /* Create ARC name */
377  sprintf(ArcBuffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
378  RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
379  Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
380  if (NT_SUCCESS(Status))
381  {
382  /* Create symbolic link */
383  IoAssignArcName(&ArcNameStringW, &DeviceStringW);
384  RtlFreeUnicodeString(&ArcNameStringW);
385  DPRINT("Boot device found\n");
386  }
387 
388  /* And quit, whatever happens */
389  RtlFreeUnicodeString(&DeviceStringW);
390  goto Cleanup;
391  }
392 
393  /* Free string before trying another disk */
394  RtlFreeUnicodeString(&DeviceStringW);
395  }
396 
397 Cleanup:
398  if (PartitionBuffer)
399  {
401  }
402 
403  if (SymbolicLinkList)
404  {
406  }
407 
408  return Status;
409 }
410 
411 INIT_FUNCTION
412 NTSTATUS
413 NTAPI
415  IN BOOLEAN SingleDisk,
416  IN PBOOLEAN FoundBoot)
417 {
418  PIRP Irp;
419  PVOID Data;
420  KEVENT Event;
422  PLIST_ENTRY NextEntry;
424  DISK_GEOMETRY DiskGeometry;
429  CHAR Buffer[128], ArcBuffer[128];
430  BOOLEAN NotEnabledPresent = FALSE;
432  PARC_DISK_SIGNATURE ArcDiskSignature;
433  PWSTR SymbolicLinkList, lSymbolicLinkList;
434  PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL;
435  UNICODE_STRING DeviceStringW, ArcNameStringW, HalPathStringW;
436  ULONG DiskNumber, DiskCount, CheckSum, i, Signature, EnabledDisks = 0;
437  PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation;
438  ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA, HalPathStringA;
439 
440  /* Initialise device number */
441  DeviceNumber.DeviceNumber = ULONG_MAX;
442  /* Get all the disks present in the system */
444 
445  /* Get enabled disks and check if result matches */
447  GUID_DEVINTERFACE_DISK,
448  DiskCount,
449  &EnabledDisks);
450  if (!NT_SUCCESS(Status))
451  {
452  NotEnabledPresent = TRUE;
453  }
454 
455  /* Save symbolic link list address in order to free it after */
456  lSymbolicLinkList = SymbolicLinkList;
457 
458  /* Build the boot strings */
459  RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName);
460  RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
461 
462  /* If we have more enabled disks, take that into account */
463  if (EnabledDisks > DiskCount)
464  {
465  DiskCount = EnabledDisks;
466  }
467 
468  /* If we'll have to browse for none enabled disks, fix higher count */
469  if (NotEnabledPresent && !EnabledDisks)
470  {
471  DiskCount += 20;
472  }
473 
474  /* Finally, if in spite of all that work, we still don't have disks, leave */
475  if (!DiskCount)
476  {
477  goto Cleanup;
478  }
479 
480  /* Start browsing disks */
481  for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++)
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(STORAGE_DEVICE_NUMBER),
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(DISK_GEOMETRY),
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 a sector for computing checksum */
649  DeviceObject,
651  DiskGeometry.BytesPerSector,
653  &Event,
654  &IoStatusBlock);
655  if (!Irp)
656  {
659  goto Cleanup;
660  }
661 
662  /* Call the driver to perform reading */
665  if (Status == STATUS_PENDING)
666  {
669  }
670  if (!NT_SUCCESS(Status))
671  {
672  ExFreePool(DriveLayout);
675  continue;
676  }
677 
679 
680  /* Calculate checksum, that's an easy computation, just adds read data */
681  for (i = 0, CheckSum = 0; i < 512 / sizeof(ULONG) ; i++)
682  {
684  }
685 
686  /* Browse each ARC disk */
687  for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
688  NextEntry != &ArcDiskInformation->DiskSignatureListHead;
689  NextEntry = NextEntry->Flink)
690  {
691  ArcDiskSignature = CONTAINING_RECORD(NextEntry,
693  ListEntry);
694 
695  /* If they matches, ie
696  * - There's only one disk for both BIOS and detected/enabled
697  * - Signatures are matching
698  * - Checksums are matching
699  * - This is MBR
700  */
701  if (((SingleDisk && DiskCount == 1) ||
702  (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature) &&
703  (ArcDiskSignature->CheckSum + CheckSum == 0))) &&
704  (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR))
705  {
706  /* Create device name */
707  sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber);
708  RtlInitAnsiString(&DeviceStringA, Buffer);
709  Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
710  if (!NT_SUCCESS(Status))
711  {
712  goto Cleanup;
713  }
714 
715  /* Create ARC name */
716  sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName);
717  RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
718  Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
719  if (!NT_SUCCESS(Status))
720  {
721  RtlFreeUnicodeString(&DeviceStringW);
722  goto Cleanup;
723  }
724 
725  /* Link both */
726  IoAssignArcName(&ArcNameStringW, &DeviceStringW);
727 
728  /* And release resources */
729  RtlFreeUnicodeString(&ArcNameStringW);
730  RtlFreeUnicodeString(&DeviceStringW);
731 
732  /* Now, browse for every partition */
733  for (i = 1; i <= DriveLayout->PartitionCount; i++)
734  {
735  /* Create device name */
736  sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber, i);
737  RtlInitAnsiString(&DeviceStringA, Buffer);
738  Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
739  if (!NT_SUCCESS(Status))
740  {
741  goto Cleanup;
742  }
743 
744  /* Create partial ARC name */
745  sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, i);
746  RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
747 
748  /* Is that boot device? */
749  if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE))
750  {
751  DPRINT("Found boot device\n");
752  *FoundBoot = TRUE;
753  }
754 
755  /* Is that system partition? */
756  if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE))
757  {
758  /* Create HAL path name */
759  RtlInitAnsiString(&HalPathStringA, LoaderBlock->NtHalPathName);
760  Status = RtlAnsiStringToUnicodeString(&HalPathStringW, &HalPathStringA, TRUE);
761  if (!NT_SUCCESS(Status))
762  {
763  RtlFreeUnicodeString(&DeviceStringW);
764  goto Cleanup;
765  }
766 
767  /* Then store those information to registry */
768  IopStoreSystemPartitionInformation(&DeviceStringW, &HalPathStringW);
769  RtlFreeUnicodeString(&HalPathStringW);
770  }
771 
772  /* Create complete ARC name */
773  sprintf(ArcBuffer, "\\ArcName\\%spartition(%lu)", ArcDiskSignature->ArcName, i);
774  RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
775  Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
776  if (!NT_SUCCESS(Status))
777  {
778  RtlFreeUnicodeString(&DeviceStringW);
779  goto Cleanup;
780  }
781 
782  /* Link device name & ARC name */
783  IoAssignArcName(&ArcNameStringW, &DeviceStringW);
784 
785  /* Release strings */
786  RtlFreeUnicodeString(&ArcNameStringW);
787  RtlFreeUnicodeString(&DeviceStringW);
788  }
789  }
790  else
791  {
792  /* In case there's a valid partition, a matching signature,
793  BUT a none matching checksum, or there's a duplicate
794  signature, or even worse a virus played with partition
795  table */
796  if (ArcDiskSignature->Signature == Signature &&
797  (ArcDiskSignature->CheckSum + CheckSum != 0) &&
798  ArcDiskSignature->ValidPartitionTable)
799  {
800  DPRINT("Be careful, or you have a duplicate disk signature, or a virus altered your MBR!\n");
801  }
802  }
803  }
804 
805  /* Release memory before jumping to next item */
806  ExFreePool(DriveLayout);
807  DriveLayout = NULL;
810  }
811 
813 
814 Cleanup:
815  if (SymbolicLinkList)
816  {
818  }
819 
820  if (DriveLayout)
821  {
822  ExFreePool(DriveLayout);
823  }
824 
825  if (PartitionBuffer)
826  {
828  }
829 
830  return Status;
831 }
832 
833 INIT_FUNCTION
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);
849  RtlInitAnsiString(&TargetString, Buffer);
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 */
920  RtlInitAnsiString(&TargetString, Buffer);
922  &LinkName,
924  NULL,
925  NULL);
926  Status = RtlAnsiStringToUnicodeString(&ArcName, &TargetString, TRUE);
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
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:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#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
#define TAG_IO
Definition: tag.h:69
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:282
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
_In_ PIRP Irp
Definition: csq.h:116
PCHAR ArcName
Definition: arc.h:210
uint16_t * PWSTR
Definition: typedefs.h:54
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
char CHAR
Definition: xmlstorage.h:175
LONG NTSTATUS
Definition: precomp.h:26
#define OBJ_PERMANENT
Definition: winternl.h:226
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:381
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
NTSTATUS NTAPI NtMakeTemporaryObject(IN HANDLE ObjectHandle)
Definition: oblife.c:1385
NTSTATUS NTAPI IoReadPartitionTableEx(IN PDEVICE_OBJECT DeviceObject, IN struct _DRIVE_LAYOUT_INFORMATION_EX **DriveLayout)
Definition: fstubex.c:2245
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
INIT_FUNCTION NTSTATUS NTAPI IopReassignSystemRoot(IN PLOADER_PARAMETER_BLOCK LoaderBlock, OUT PANSI_STRING NtBootPath)
Definition: arcname.c:836
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
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define UNICODE_NULL
#define ANSI_NULL
PCHAR IoLoaderArcBootDeviceName
Definition: arcname.c:20
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:435
_In_ ULONG _In_ BOOLEAN _Out_ struct _DRIVE_LAYOUT_INFORMATION ** PartitionBuffer
Definition: iofuncs.h:2048
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_In_ LPGUID _In_ PVOID Data
Definition: classpnp.h:778
NTSYSAPI VOID NTAPI RtlCopyString(PSTRING DestinationString, PSTRING SourceString)
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:132
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
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
USHORT MaximumLength
Definition: env_spec_w32.h:377
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
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
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
* PFILE_OBJECT
Definition: iotypes.h:1955
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#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:3376
WCHAR TargetName[256]
Definition: arping.c:27
Definition: typedefs.h:117
BOOLEAN ValidPartitionTable
Definition: arc.h:212
static const WCHAR Cleanup[]
Definition: register.c:80
Status
Definition: gdiplustypes.h:24
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
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
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
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:39
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:390
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
INIT_FUNCTION NTSTATUS NTAPI IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN BOOLEAN SingleDisk, IN PBOOLEAN FoundBoot)
Definition: arcname.c:414
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:2726
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
ULONG CheckSum
Definition: arc.h:211
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_In_ PCHAR _In_ ULONG DeviceNumber
Definition: classpnp.h:1036
UNICODE_STRING IoArcHalDeviceName
Definition: arcname.c:19
return STATUS_SUCCESS
Definition: btrfs.c:2938
static const WCHAR Signature[]
Definition: parser.c:141
INIT_FUNCTION NTSTATUS NTAPI IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: arcname.c:152
INIT_FUNCTION NTSTATUS NTAPI IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: arcname.c:41
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
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:67