ReactOS  0.4.13-dev-73-gcfe54aa
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 
22 
23 /* FUNCTIONS *****************************************************************/
24 
25 INIT_FUNCTION
27 NTAPI
29 );
30 
31 INIT_FUNCTION
33 NTAPI
35  IN BOOLEAN SingleDisk,
36  IN PBOOLEAN FoundBoot
37 );
38 
39 INIT_FUNCTION
41 NTAPI
43 {
44  SIZE_T Length;
46  CHAR Buffer[128];
47  BOOLEAN SingleDisk;
48  BOOLEAN FoundBoot = FALSE;
49  UNICODE_STRING SystemDevice, LoaderPathNameW, BootDeviceName;
50  PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation;
51  ANSI_STRING ArcSystemString, ArcString, LanmanRedirector, LoaderPathNameA;
52 
53  /* Check if we only have one disk on the machine */
54  SingleDisk = ArcDiskInfo->DiskSignatureListHead.Flink->Flink ==
55  (&ArcDiskInfo->DiskSignatureListHead);
56 
57  /* Create the global HAL partition name */
58  sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName);
59  RtlInitAnsiString(&ArcString, Buffer);
61 
62  /* Create the global system partition name */
63  sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
64  RtlInitAnsiString(&ArcString, Buffer);
66 
67  /* Allocate memory for the string */
68  Length = strlen(LoaderBlock->ArcBootDeviceName) + sizeof(ANSI_NULL);
70  Length,
71  TAG_IO);
73  {
74  /* Copy the name */
76  LoaderBlock->ArcBootDeviceName,
77  Length);
78  }
79 
80  /* Check if we only found a disk, but we're booting from CD-ROM */
81  if ((SingleDisk) && strstr(LoaderBlock->ArcBootDeviceName, "cdrom"))
82  {
83  /* Then disable single-disk mode, since there's a CD drive out there */
84  SingleDisk = FALSE;
85  }
86 
87  /* Build the boot strings */
88  RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
89 
90  /* If we are doing remote booting */
92  {
93  /* Yes, we have found boot device */
94  FoundBoot = TRUE;
95 
96  /* Get NT device name */
97  RtlInitAnsiString(&LanmanRedirector, "\\Device\\LanmanRedirector");
98  Status = RtlAnsiStringToUnicodeString(&SystemDevice, &LanmanRedirector, TRUE);
99  if (!NT_SUCCESS(Status))
100  {
101  return Status;
102  }
103 
104  /* Get ARC booting device name (in net(0) something) */
105  sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
106  RtlInitAnsiString(&ArcString, Buffer);
107  Status = RtlAnsiStringToUnicodeString(&BootDeviceName, &ArcString, TRUE);
108  if (NT_SUCCESS(Status))
109  {
110  /* Map ARC to NT name */
111  IoAssignArcName(&BootDeviceName, &SystemDevice);
112  RtlFreeUnicodeString(&BootDeviceName);
113 
114  /* Now, get loader path name */
115  RtlInitAnsiString(&LoaderPathNameA, LoaderBlock->NtHalPathName);
116  Status = RtlAnsiStringToUnicodeString(&LoaderPathNameW, &LoaderPathNameA, TRUE);
117  if (!NT_SUCCESS(Status))
118  {
119  RtlFreeUnicodeString(&SystemDevice);
120  return Status;
121  }
122 
123  /* And set it has system partition */
124  IopStoreSystemPartitionInformation(&SystemDevice, &LoaderPathNameW);
125  }
126 
127  RtlFreeUnicodeString(&SystemDevice);
128 
129  /* Don't quit here, even if everything went fine!
130  * We need IopCreateArcNamesDisk to properly map
131  * devices with symlinks.
132  * It will return success if the mapping process went fine
133  * even if it didn't find boot device.
134  * It won't reset boot device finding status as well.
135  */
136  }
137 
138  /* Loop every disk and try to find boot disk */
139  Status = IopCreateArcNamesDisk(LoaderBlock, SingleDisk, &FoundBoot);
140  /* If it succeed but we didn't find boot device, try to browse Cds */
141  if (NT_SUCCESS(Status) && !FoundBoot)
142  {
143  Status = IopCreateArcNamesCd(LoaderBlock);
144  }
145 
146  /* Return success */
147  return Status;
148 }
149 
150 INIT_FUNCTION
151 NTSTATUS
152 NTAPI
154 {
155  PIRP Irp;
156  KEVENT Event;
158  PLIST_ENTRY NextEntry;
164  CHAR Buffer[128], ArcBuffer[128];
165  BOOLEAN NotEnabledPresent = FALSE;
167  ANSI_STRING DeviceStringA, ArcNameStringA;
168  PWSTR SymbolicLinkList, lSymbolicLinkList;
169  PARC_DISK_SIGNATURE ArcDiskSignature = NULL;
170  UNICODE_STRING DeviceStringW, ArcNameStringW;
171  ULONG DiskNumber, CdRomCount, CheckSum, i, EnabledDisks = 0;
172  PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation;
173 
174  /* Get all the Cds present in the system */
176 
177  /* Get enabled Cds and check if result matches
178  * For the record, enabled Cds (or even disk) are Cds/disks
179  * that have been successfully handled by MountMgr driver
180  * and that already own their device name. This is the "new" way
181  * to handle them, that came with NT5.
182  * Currently, Windows 2003 provides an arc names creation based
183  * on both enabled drives and not enabled drives (lack from
184  * the driver).
185  * Given the current ReactOS state, that's good for us.
186  * To sum up, this is NOT a hack or whatsoever.
187  */
189  GUID_DEVINTERFACE_CDROM,
190  CdRomCount,
191  &EnabledDisks);
192  if (!NT_SUCCESS(Status))
193  {
194  NotEnabledPresent = TRUE;
195  }
196  /* Save symbolic link list address in order to free it after */
197  lSymbolicLinkList = SymbolicLinkList;
198  /* For the moment, we won't fail */
200 
201  /* Browse all the ARC devices trying to find the one matching boot device */
202  for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
203  NextEntry != &ArcDiskInformation->DiskSignatureListHead;
204  NextEntry = NextEntry->Flink)
205  {
206  ArcDiskSignature = CONTAINING_RECORD(NextEntry,
208  ListEntry);
209 
210  if (strcmp(LoaderBlock->ArcBootDeviceName, ArcDiskSignature->ArcName) == 0)
211  {
212  break;
213  }
214 
215  ArcDiskSignature = NULL;
216  }
217 
218  /* Not found... Not booting from a Cd */
219  if (!ArcDiskSignature)
220  {
221  DPRINT("Failed finding a cd that could match current boot device\n");
222  goto Cleanup;
223  }
224 
225  /* Allocate needed space for reading Cd */
227  if (!PartitionBuffer)
228  {
229  DPRINT("Failed allocating resources!\n");
230  /* Here, we fail, BUT we return success, some Microsoft joke */
231  goto Cleanup;
232  }
233 
234  /* If we have more enabled Cds, take that into account */
235  if (EnabledDisks > CdRomCount)
236  {
237  CdRomCount = EnabledDisks;
238  }
239 
240  /* If we'll have to browse for none enabled Cds, fix higher count */
241  if (NotEnabledPresent && !EnabledDisks)
242  {
243  CdRomCount += 5;
244  }
245 
246  /* Finally, if in spite of all that work, we still don't have Cds, leave */
247  if (!CdRomCount)
248  {
249  goto Cleanup;
250  }
251 
252  /* Start browsing Cds */
253  for (DiskNumber = 0, EnabledDisks = 0; DiskNumber < CdRomCount; DiskNumber++)
254  {
255  /* Check if we have an enabled disk */
256  if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL)
257  {
258  /* Create its device name using first symbolic link */
259  RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList);
260  /* Then, update symbolic links list */
261  lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR));
262 
263  /* Get its associated device object and file object */
264  Status = IoGetDeviceObjectPointer(&DeviceStringW,
266  &FileObject,
267  &DeviceObject);
268  /* Failure? Good bye! */
269  if (!NT_SUCCESS(Status))
270  {
271  goto Cleanup;
272  }
273 
274  /* Now, we'll ask the device its device number */
276  DeviceObject,
277  NULL,
278  0,
279  &DeviceNumber,
280  sizeof(STORAGE_DEVICE_NUMBER),
281  FALSE,
282  &Event,
283  &IoStatusBlock);
284  /* Failure? Good bye! */
285  if (!Irp)
286  {
287  /* Dereference file object before leaving */
290  goto Cleanup;
291  }
292 
293  /* Call the driver, and wait for it if needed */
296  if (Status == STATUS_PENDING)
297  {
300  }
301  if (!NT_SUCCESS(Status))
302  {
304  goto Cleanup;
305  }
306 
307  /* Finally, build proper device name */
308  sprintf(Buffer, "\\Device\\CdRom%lu", DeviceNumber.DeviceNumber);
309  RtlInitAnsiString(&DeviceStringA, Buffer);
310  Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
311  if (!NT_SUCCESS(Status))
312  {
314  goto Cleanup;
315  }
316  }
317  else
318  {
319  /* Create device name for the cd */
320  sprintf(Buffer, "\\Device\\CdRom%lu", EnabledDisks++);
321  RtlInitAnsiString(&DeviceStringA, Buffer);
322  Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
323  if (!NT_SUCCESS(Status))
324  {
325  goto Cleanup;
326  }
327 
328  /* Get its device object */
329  Status = IoGetDeviceObjectPointer(&DeviceStringW,
331  &FileObject,
332  &DeviceObject);
333  if (!NT_SUCCESS(Status))
334  {
335  RtlFreeUnicodeString(&DeviceStringW);
336  goto Cleanup;
337  }
338  }
339 
340  /* Initiate data for reading cd and compute checksum */
341  StartingOffset.QuadPart = 0x8000;
342  CheckSum = 0;
344  DeviceObject,
346  2048,
348  &Event,
349  &IoStatusBlock);
350  if (Irp)
351  {
352  /* Call the driver, and wait for it if needed */
355  if (Status == STATUS_PENDING)
356  {
359  }
360 
361  /* Reading succeed, compute checksum by adding data, 2048 bytes checksum */
362  if (NT_SUCCESS(Status))
363  {
364  for (i = 0; i < 2048 / sizeof(ULONG); i++)
365  {
367  }
368  }
369  }
370 
371  /* Dereference file object */
373 
374  /* If checksums are matching, we have the proper cd */
375  if (CheckSum + ArcDiskSignature->CheckSum == 0)
376  {
377  /* Create ARC name */
378  sprintf(ArcBuffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
379  RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
380  Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
381  if (NT_SUCCESS(Status))
382  {
383  /* Create symbolic link */
384  IoAssignArcName(&ArcNameStringW, &DeviceStringW);
385  RtlFreeUnicodeString(&ArcNameStringW);
386  DPRINT("Boot device found\n");
387  }
388 
389  /* And quit, whatever happens */
390  RtlFreeUnicodeString(&DeviceStringW);
391  goto Cleanup;
392  }
393 
394  /* Free string before trying another disk */
395  RtlFreeUnicodeString(&DeviceStringW);
396  }
397 
398 Cleanup:
399  if (PartitionBuffer)
400  {
402  }
403 
404  if (SymbolicLinkList)
405  {
407  }
408 
409  return Status;
410 }
411 
412 INIT_FUNCTION
413 NTSTATUS
414 NTAPI
416  IN BOOLEAN SingleDisk,
417  IN PBOOLEAN FoundBoot)
418 {
419  PIRP Irp;
420  PVOID Data;
421  KEVENT Event;
423  PLIST_ENTRY NextEntry;
425  DISK_GEOMETRY DiskGeometry;
430  CHAR Buffer[128], ArcBuffer[128];
431  BOOLEAN NotEnabledPresent = FALSE;
433  PARC_DISK_SIGNATURE ArcDiskSignature;
434  PWSTR SymbolicLinkList, lSymbolicLinkList;
435  PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL;
436  UNICODE_STRING DeviceStringW, ArcNameStringW, HalPathStringW;
437  ULONG DiskNumber, DiskCount, CheckSum, i, Signature, EnabledDisks = 0;
438  PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation;
439  ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA, HalPathStringA;
440 
441  /* Initialise device number */
442  DeviceNumber.DeviceNumber = ULONG_MAX;
443  /* Get all the disks present in the system */
445 
446  /* Get enabled disks and check if result matches */
448  GUID_DEVINTERFACE_DISK,
449  DiskCount,
450  &EnabledDisks);
451  if (!NT_SUCCESS(Status))
452  {
453  NotEnabledPresent = TRUE;
454  }
455 
456  /* Save symbolic link list address in order to free it after */
457  lSymbolicLinkList = SymbolicLinkList;
458 
459  /* Build the boot strings */
460  RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName);
461  RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
462 
463  /* If we have more enabled disks, take that into account */
464  if (EnabledDisks > DiskCount)
465  {
466  DiskCount = EnabledDisks;
467  }
468 
469  /* If we'll have to browse for none enabled disks, fix higher count */
470  if (NotEnabledPresent && !EnabledDisks)
471  {
472  DiskCount += 20;
473  }
474 
475  /* Finally, if in spite of all that work, we still don't have disks, leave */
476  if (!DiskCount)
477  {
478  goto Cleanup;
479  }
480 
481  /* Start browsing disks */
482  for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++)
483  {
484  /* Check if we have an enabled disk */
485  if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL)
486  {
487  /* Create its device name using first symbolic link */
488  RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList);
489  /* Then, update symbolic links list */
490  lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR));
491 
492  /* Get its associated device object and file object */
493  Status = IoGetDeviceObjectPointer(&DeviceStringW,
495  &FileObject,
496  &DeviceObject);
497  if (NT_SUCCESS(Status))
498  {
499  /* Now, we'll ask the device its device number */
501  DeviceObject,
502  NULL,
503  0,
504  &DeviceNumber,
505  sizeof(STORAGE_DEVICE_NUMBER),
506  FALSE,
507  &Event,
508  &IoStatusBlock);
509  /* Missing resources is a shame... No need to go farther */
510  if (!Irp)
511  {
514  goto Cleanup;
515  }
516 
517  /* Call the driver, and wait for it if needed */
520  if (Status == STATUS_PENDING)
521  {
524  }
525 
526  /* If we didn't get the appriopriate data, just skip that disk */
527  if (!NT_SUCCESS(Status))
528  {
530  continue;
531  }
532  }
533 
534  /* End of enabled disks enumeration */
535  if (NotEnabledPresent && *lSymbolicLinkList == UNICODE_NULL)
536  {
537  /* No enabled disk worked, reset field */
538  if (DeviceNumber.DeviceNumber == ULONG_MAX)
539  {
540  DeviceNumber.DeviceNumber = 0;
541  }
542 
543  /* Update disk number to enable the following not enabled disks */
544  if (DeviceNumber.DeviceNumber > DiskNumber)
545  {
546  DiskNumber = DeviceNumber.DeviceNumber;
547  }
548 
549  /* Increase a bit more */
550  DiskCount = DiskNumber + 20;
551  }
552  }
553  else
554  {
555  /* Create device name for the disk */
556  sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber);
557  RtlInitAnsiString(&DeviceStringA, Buffer);
558  Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
559  if (!NT_SUCCESS(Status))
560  {
561  goto Cleanup;
562  }
563 
564  /* Get its device object */
565  Status = IoGetDeviceObjectPointer(&DeviceStringW,
567  &FileObject,
568  &DeviceObject);
569 
570  RtlFreeUnicodeString(&DeviceStringW);
571  /* This is a security measure, to ensure DiskNumber will be used */
572  DeviceNumber.DeviceNumber = ULONG_MAX;
573  }
574 
575  /* Something failed somewhere earlier, just skip the disk */
576  if (!NT_SUCCESS(Status))
577  {
578  continue;
579  }
580 
581  /* Let's ask the disk for its geometry */
583  DeviceObject,
584  NULL,
585  0,
586  &DiskGeometry,
587  sizeof(DISK_GEOMETRY),
588  FALSE,
589  &Event,
590  &IoStatusBlock);
591  /* Missing resources is a shame... No need to go farther */
592  if (!Irp)
593  {
596  goto Cleanup;
597  }
598 
599  /* Call the driver, and wait for it if needed */
602  if (Status == STATUS_PENDING)
603  {
606  }
607  /* Failure, skip disk */
608  if (!NT_SUCCESS(Status))
609  {
611  continue;
612  }
613 
614  /* Read the partition table */
616  &DriveLayout);
617  if (!NT_SUCCESS(Status))
618  {
620  continue;
621  }
622 
623  /* Ensure we have at least 512 bytes per sector */
624  if (DiskGeometry.BytesPerSector < 512)
625  {
626  DiskGeometry.BytesPerSector = 512;
627  }
628 
629  /* Check MBR type against EZ Drive type */
630  StartingOffset.QuadPart = 0;
631  HalExamineMBR(DeviceObject, DiskGeometry.BytesPerSector, 0x55, &Data);
632  if (Data)
633  {
634  /* If MBR is of the EZ Drive type, we'll read after it */
635  StartingOffset.QuadPart = DiskGeometry.BytesPerSector;
636  ExFreePool(Data);
637  }
638 
639  /* Allocate for reading enough data for checksum */
641  if (!PartitionBuffer)
642  {
645  goto Cleanup;
646  }
647 
648  /* Read a sector for computing checksum */
650  DeviceObject,
652  DiskGeometry.BytesPerSector,
654  &Event,
655  &IoStatusBlock);
656  if (!Irp)
657  {
660  goto Cleanup;
661  }
662 
663  /* Call the driver to perform reading */
666  if (Status == STATUS_PENDING)
667  {
670  }
671  if (!NT_SUCCESS(Status))
672  {
673  ExFreePool(DriveLayout);
676  continue;
677  }
678 
680 
681  /* Calculate checksum, that's an easy computation, just adds read data */
682  for (i = 0, CheckSum = 0; i < 512 / sizeof(ULONG) ; i++)
683  {
685  }
686 
687  /* Browse each ARC disk */
688  for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
689  NextEntry != &ArcDiskInformation->DiskSignatureListHead;
690  NextEntry = NextEntry->Flink)
691  {
692  ArcDiskSignature = CONTAINING_RECORD(NextEntry,
694  ListEntry);
695 
696  /* If they matches, ie
697  * - There's only one disk for both BIOS and detected/enabled
698  * - Signatures are matching
699  * - Checksums are matching
700  * - This is MBR
701  */
702  if (((SingleDisk && DiskCount == 1) ||
703  (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature) &&
704  (ArcDiskSignature->CheckSum + CheckSum == 0))) &&
705  (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR))
706  {
707  /* Create device name */
708  sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber);
709  RtlInitAnsiString(&DeviceStringA, Buffer);
710  Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
711  if (!NT_SUCCESS(Status))
712  {
713  goto Cleanup;
714  }
715 
716  /* Create ARC name */
717  sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName);
718  RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
719  Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
720  if (!NT_SUCCESS(Status))
721  {
722  RtlFreeUnicodeString(&DeviceStringW);
723  goto Cleanup;
724  }
725 
726  /* Link both */
727  IoAssignArcName(&ArcNameStringW, &DeviceStringW);
728 
729  /* And release resources */
730  RtlFreeUnicodeString(&ArcNameStringW);
731  RtlFreeUnicodeString(&DeviceStringW);
732 
733  /* Now, browse for every partition */
734  for (i = 1; i <= DriveLayout->PartitionCount; i++)
735  {
736  /* Create device name */
737  sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber, i);
738  RtlInitAnsiString(&DeviceStringA, Buffer);
739  Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
740  if (!NT_SUCCESS(Status))
741  {
742  goto Cleanup;
743  }
744 
745  /* Create partial ARC name */
746  sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, i);
747  RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
748 
749  /* Is that boot device? */
750  if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE))
751  {
752  DPRINT("Found boot device\n");
753  *FoundBoot = TRUE;
754  }
755 
756  /* Is that system partition? */
757  if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE))
758  {
759  /* Create HAL path name */
760  RtlInitAnsiString(&HalPathStringA, LoaderBlock->NtHalPathName);
761  Status = RtlAnsiStringToUnicodeString(&HalPathStringW, &HalPathStringA, TRUE);
762  if (!NT_SUCCESS(Status))
763  {
764  RtlFreeUnicodeString(&DeviceStringW);
765  goto Cleanup;
766  }
767 
768  /* Then store those information to registry */
769  IopStoreSystemPartitionInformation(&DeviceStringW, &HalPathStringW);
770  RtlFreeUnicodeString(&HalPathStringW);
771  }
772 
773  /* Create complete ARC name */
774  sprintf(ArcBuffer, "\\ArcName\\%spartition(%lu)", ArcDiskSignature->ArcName, i);
775  RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
776  Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
777  if (!NT_SUCCESS(Status))
778  {
779  RtlFreeUnicodeString(&DeviceStringW);
780  goto Cleanup;
781  }
782 
783  /* Link device name & ARC name */
784  IoAssignArcName(&ArcNameStringW, &DeviceStringW);
785 
786  /* Release strings */
787  RtlFreeUnicodeString(&ArcNameStringW);
788  RtlFreeUnicodeString(&DeviceStringW);
789  }
790  }
791  else
792  {
793  /* In case there's a valid partition, a matching signature,
794  BUT a none matching checksum, or there's a duplicate
795  signature, or even worse a virus played with partition
796  table */
797  if (ArcDiskSignature->Signature == Signature &&
798  (ArcDiskSignature->CheckSum + CheckSum != 0) &&
799  ArcDiskSignature->ValidPartitionTable)
800  {
801  DPRINT("Be careful, or you have a duplicate disk signature, or a virus altered your MBR!\n");
802  }
803  }
804  }
805 
806  /* Release memory before jumping to next item */
807  ExFreePool(DriveLayout);
808  DriveLayout = NULL;
811  }
812 
814 
815 Cleanup:
816  if (SymbolicLinkList)
817  {
819  }
820 
821  if (DriveLayout)
822  {
823  ExFreePool(DriveLayout);
824  }
825 
826  if (PartitionBuffer)
827  {
829  }
830 
831  return Status;
832 }
833 
834 INIT_FUNCTION
835 NTSTATUS
836 NTAPI
838  OUT PANSI_STRING NtBootPath)
839 {
842  CHAR Buffer[256], AnsiBuffer[256];
843  WCHAR ArcNameBuffer[64];
844  ANSI_STRING TargetString, ArcString, TempString;
845  UNICODE_STRING LinkName, TargetName, ArcName;
846  HANDLE LinkHandle;
847 
848  /* Create the Unicode name for the current ARC boot device */
849  sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
850  RtlInitAnsiString(&TargetString, Buffer);
852  if (!NT_SUCCESS(Status)) return FALSE;
853 
854  /* Initialize the attributes and open the link */
856  &TargetName,
858  NULL,
859  NULL);
860  Status = NtOpenSymbolicLinkObject(&LinkHandle,
863  if (!NT_SUCCESS(Status))
864  {
865  /* We failed, free the string */
867  return FALSE;
868  }
869 
870  /* Query the current \\SystemRoot */
871  ArcName.Buffer = ArcNameBuffer;
872  ArcName.Length = 0;
873  ArcName.MaximumLength = sizeof(ArcNameBuffer);
874  Status = NtQuerySymbolicLinkObject(LinkHandle, &ArcName, NULL);
875  if (!NT_SUCCESS(Status))
876  {
877  /* We failed, free the string */
879  return FALSE;
880  }
881 
882  /* Convert it to Ansi */
883  ArcString.Buffer = AnsiBuffer;
884  ArcString.Length = 0;
885  ArcString.MaximumLength = sizeof(AnsiBuffer);
886  Status = RtlUnicodeStringToAnsiString(&ArcString, &ArcName, FALSE);
887  AnsiBuffer[ArcString.Length] = ANSI_NULL;
888 
889  /* Close the link handle and free the name */
890  ObCloseHandle(LinkHandle, KernelMode);
892 
893  /* Setup the system root name again */
894  RtlInitAnsiString(&TempString, "\\SystemRoot");
895  Status = RtlAnsiStringToUnicodeString(&LinkName, &TempString, TRUE);
896  if (!NT_SUCCESS(Status)) return FALSE;
897 
898  /* Open the symbolic link for it */
900  &LinkName,
902  NULL,
903  NULL);
904  Status = NtOpenSymbolicLinkObject(&LinkHandle,
907  if (!NT_SUCCESS(Status)) return FALSE;
908 
909  /* Destroy it */
910  NtMakeTemporaryObject(LinkHandle);
911  ObCloseHandle(LinkHandle, KernelMode);
912 
913  /* Now create the new name for it */
914  sprintf(Buffer, "%s%s", ArcString.Buffer, LoaderBlock->NtBootPathName);
915 
916  /* Copy it into the passed parameter and null-terminate it */
917  RtlCopyString(NtBootPath, &ArcString);
918  Buffer[strlen(Buffer) - 1] = ANSI_NULL;
919 
920  /* Setup the Unicode-name for the new symbolic link value */
921  RtlInitAnsiString(&TargetString, Buffer);
923  &LinkName,
925  NULL,
926  NULL);
927  Status = RtlAnsiStringToUnicodeString(&ArcName, &TargetString, TRUE);
928  if (!NT_SUCCESS(Status)) return FALSE;
929 
930  /* Create it */
931  Status = NtCreateSymbolicLinkObject(&LinkHandle,
934  &ArcName);
935 
936  /* Free all the strings and close the handle and return success */
937  RtlFreeUnicodeString(&ArcName);
938  RtlFreeUnicodeString(&LinkName);
939  ObCloseHandle(LinkHandle, KernelMode);
940  return TRUE;
941 }
942 
943 BOOLEAN
944 NTAPI
946  IN PARC_DISK_SIGNATURE ArcDiskSignature,
948 {
949  /* First condition: having a valid partition table */
950  if (!ArcDiskSignature->ValidPartitionTable)
951  {
952  return FALSE;
953  }
954 
955  /* If that partition table is the MBR */
956  if (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)
957  {
958  /* Then check MBR signature */
959  if (DriveLayout->Mbr.Signature == ArcDiskSignature->Signature)
960  {
961  /* And return it */
962  if (Signature)
963  {
964  *Signature = DriveLayout->Mbr.Signature;
965  }
966 
967  return TRUE;
968  }
969  }
970  /* If that partition table is the GPT */
971  else if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
972  {
973  /* Check we are using GPT and compare GUID */
974  if (ArcDiskSignature->IsGpt &&
975  (((PULONG)ArcDiskSignature->GptSignature)[0] == DriveLayout->Gpt.DiskId.Data1 &&
976  ((PUSHORT)ArcDiskSignature->GptSignature)[2] == DriveLayout->Gpt.DiskId.Data2 &&
977  ((PUSHORT)ArcDiskSignature->GptSignature)[3] == DriveLayout->Gpt.DiskId.Data3 &&
978  ((PULONGLONG)ArcDiskSignature->GptSignature)[1] == ((PULONGLONG)DriveLayout->Gpt.DiskId.Data4)[0]))
979  {
980  /* There's no signature to give, so we just zero output */
981  if (Signature)
982  {
983  *Signature = 0;
984  }
985  return TRUE;
986  }
987  }
988 
989  /* If we fall here, it means that something went wrong, so return that */
990  return FALSE;
991 }
992 
993 /* 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:1434
ULONG BytesPerSector
Definition: ntdddisk.h:376
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:2247
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:945
#define SYMBOLIC_LINK_ALL_ACCESS
Definition: nt_native.h:1267
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
BOOLEAN IoRemoteBootClient
Definition: init.c:67
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:837
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:434
_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:1954
#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:415
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:2287
#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:2725
static const WCHAR Signature[]
Definition: parser.c:141
INIT_FUNCTION NTSTATUS NTAPI IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: arcname.c:153
INIT_FUNCTION NTSTATUS NTAPI IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: arcname.c:42
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