3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/arcname.c
6 * PURPOSE: Creates ARC names for boot devices
8 * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
12 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
18 /* MACROS *******************************************************************/
20 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
22 /* STRUCTURES ***************************************************************/
24 typedef struct _DISKENTRY
30 PDEVICE_OBJECT DeviceObject
;
31 } DISKENTRY
, *PDISKENTRY
;
33 #define PARTITION_TBL_SIZE 4
37 typedef struct _PARTITION
39 unsigned char BootFlags
; /* bootable? 0=no, 128=yes */
40 unsigned char StartingHead
; /* beginning head number */
41 unsigned char StartingSector
; /* beginning sector number */
42 unsigned char StartingCylinder
; /* 10 bit nmbr, with high 2 bits put in begsect */
43 unsigned char PartitionType
; /* Operating System type indicator code */
44 unsigned char EndingHead
; /* ending head number */
45 unsigned char EndingSector
; /* ending sector number */
46 unsigned char EndingCylinder
; /* also a 10 bit nmbr, with same high 2 bit trick */
47 unsigned int StartingBlock
; /* first sector relative to start of disk */
48 unsigned int SectorCount
; /* number of sectors in partition */
49 } PARTITION
, *PPARTITION
;
51 typedef struct _PARTITION_SECTOR
53 UCHAR BootCode
[440]; /* 0x000 */
54 ULONG Signature
; /* 0x1B8 */
55 UCHAR Reserved
[2]; /* 0x1BC */
56 PARTITION Partition
[PARTITION_TBL_SIZE
]; /* 0x1BE */
57 USHORT Magic
; /* 0x1FE */
58 } PARTITION_SECTOR
, *PPARTITION_SECTOR
;
62 /* FUNCTIONS ****************************************************************/
68 DiskQueryRoutine(PWSTR ValueName
,
75 PLIST_ENTRY ListHead
= (PLIST_ENTRY
)Context
;
76 PULONG GlobalDiskCount
= (PULONG
)EntryContext
;
80 if (ValueType
== REG_SZ
&&
81 ValueLength
== 20 * sizeof(WCHAR
))
83 DiskEntry
= ExAllocatePool(PagedPool
, sizeof(DISKENTRY
));
84 if (DiskEntry
== NULL
)
86 return STATUS_NO_MEMORY
;
88 DiskEntry
->DiskNumber
= (*GlobalDiskCount
)++;
90 NameU
.Buffer
= (PWCHAR
)ValueData
;
91 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
92 RtlUnicodeStringToInteger(&NameU
, 16, &DiskEntry
->Checksum
);
94 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
95 RtlUnicodeStringToInteger(&NameU
, 16, &DiskEntry
->Signature
);
97 InsertTailList(ListHead
, &DiskEntry
->ListEntry
);
100 return STATUS_SUCCESS
;
103 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
105 STATIC VOID INIT_FUNCTION
106 IopEnumerateBiosDisks(PLIST_ENTRY ListHead
)
108 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
111 ULONG ControllerCount
;
114 ULONG GlobalDiskCount
=0;
117 memset(QueryTable
, 0, sizeof(QueryTable
));
118 QueryTable
[0].Name
= L
"Identifier";
119 QueryTable
[0].QueryRoutine
= DiskQueryRoutine
;
120 QueryTable
[0].EntryContext
= (PVOID
)&GlobalDiskCount
;
125 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
126 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
131 if (!NT_SUCCESS(Status
))
136 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
137 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
142 if (NT_SUCCESS(Status
))
147 swprintf(Name
, L
"%s\\%lu\\DiskController\\%lu", ROOT_NAME
, AdapterCount
, ControllerCount
);
148 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
153 if (!NT_SUCCESS(Status
))
158 swprintf(Name
, L
"%s\\%lu\\DiskController\\%lu\\DiskPeripheral", ROOT_NAME
, AdapterCount
, ControllerCount
);
159 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
164 if (NT_SUCCESS(Status
))
169 swprintf(Name
, L
"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, ControllerCount
, DiskCount
);
170 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
175 if (!NT_SUCCESS(Status
))
189 STATIC VOID INIT_FUNCTION
190 IopEnumerateDisks(PLIST_ENTRY ListHead
)
193 PDISKENTRY DiskEntry
;
194 DISK_GEOMETRY DiskGeometry
;
197 IO_STATUS_BLOCK StatusBlock
;
198 LARGE_INTEGER PartitionOffset
;
200 WCHAR DeviceNameBuffer
[80];
201 UNICODE_STRING DeviceName
;
203 PDEVICE_OBJECT DeviceObject
;
204 PFILE_OBJECT FileObject
;
205 BOOLEAN IsRemovableMedia
;
206 PPARTITION_SECTOR PartitionBuffer
= NULL
;
207 ULONG PartitionBufferSize
= 0;
210 for (i
= 0; i
< IoGetConfigurationInformation()->DiskCount
; i
++)
213 swprintf(DeviceNameBuffer
,
214 L
"\\Device\\Harddisk%lu\\Partition0",
216 RtlInitUnicodeString(&DeviceName
,
220 Status
= IoGetDeviceObjectPointer(&DeviceName
,
224 if (!NT_SUCCESS(Status
))
228 IsRemovableMedia
= DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
? TRUE
: FALSE
;
229 ObDereferenceObject(FileObject
);
230 if (IsRemovableMedia
)
232 ObDereferenceObject(DeviceObject
);
235 DiskEntry
= ExAllocatePool(PagedPool
, sizeof(DISKENTRY
));
236 if (DiskEntry
== NULL
)
240 DiskEntry
->DiskNumber
= i
;
241 DiskEntry
->DeviceObject
= DeviceObject
;
243 /* determine the sector size */
244 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
245 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
250 sizeof(DISK_GEOMETRY
),
259 Status
= IoCallDriver(DeviceObject
, Irp
);
260 if (Status
== STATUS_PENDING
)
262 KeWaitForSingleObject(&Event
,
267 Status
= StatusBlock
.Status
;
269 if (!NT_SUCCESS(Status
))
273 if (PartitionBuffer
!= NULL
&& PartitionBufferSize
< DiskGeometry
.BytesPerSector
)
275 ExFreePool(PartitionBuffer
);
276 PartitionBuffer
= NULL
;
278 if (PartitionBuffer
== NULL
)
280 PartitionBufferSize
= max(DiskGeometry
.BytesPerSector
, PAGE_SIZE
);
281 PartitionBuffer
= ExAllocatePool(PagedPool
, PartitionBufferSize
);
282 if (PartitionBuffer
== NULL
)
288 /* read the partition sector */
289 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
290 PartitionOffset
.QuadPart
= 0;
291 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
294 DiskGeometry
.BytesPerSector
,
298 Status
= IoCallDriver(DeviceObject
, Irp
);
299 if (Status
== STATUS_PENDING
)
301 KeWaitForSingleObject(&Event
,
306 Status
= StatusBlock
.Status
;
309 if (!NT_SUCCESS(Status
))
314 /* Calculate the MBR checksum */
315 DiskEntry
->Checksum
= 0;
316 Buffer
= (PULONG
)PartitionBuffer
;
317 for (k
= 0; k
< 128; k
++)
319 DiskEntry
->Checksum
+= Buffer
[k
];
321 DiskEntry
->Checksum
= ~DiskEntry
->Checksum
+ 1;
322 DiskEntry
->Signature
= PartitionBuffer
->Signature
;
324 InsertTailList(ListHead
, &DiskEntry
->ListEntry
);
328 ExFreePool(PartitionBuffer
);
332 STATIC NTSTATUS INIT_FUNCTION
333 IopAssignArcNamesToDisk(PDEVICE_OBJECT DeviceObject
, ULONG RDisk
, ULONG DiskNumber
)
335 WCHAR DeviceNameBuffer
[80];
336 WCHAR ArcNameBuffer
[80];
337 UNICODE_STRING DeviceName
;
338 UNICODE_STRING ArcName
;
339 PDRIVE_LAYOUT_INFORMATION LayoutInfo
= NULL
;
344 IO_STATUS_BLOCK StatusBlock
;
345 ULONG PartitionNumber
;
347 swprintf(DeviceNameBuffer
,
348 L
"\\Device\\Harddisk%lu\\Partition0",
350 RtlInitUnicodeString(&DeviceName
,
353 swprintf(ArcNameBuffer
,
354 L
"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
356 RtlInitUnicodeString(&ArcName
,
359 DPRINT("%wZ ==> %wZ\n", &ArcName
, &DeviceName
);
361 Status
= IoAssignArcName(&ArcName
, &DeviceName
);
362 if (!NT_SUCCESS(Status
))
364 DPRINT1("IoAssignArcName failed, status=%lx\n", Status
);
368 LayoutInfo
= ExAllocatePool(PagedPool
, 2 * PAGE_SIZE
);
369 if (LayoutInfo
== NULL
)
371 return STATUS_NO_MEMORY
;
373 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
374 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT
,
385 ExFreePool(LayoutInfo
);
386 return STATUS_INSUFFICIENT_RESOURCES
;
389 Status
= IoCallDriver(DeviceObject
, Irp
);
390 if (Status
== STATUS_PENDING
)
392 KeWaitForSingleObject(&Event
,
397 Status
= StatusBlock
.Status
;
399 if (!NT_SUCCESS(Status
))
401 ExFreePool(LayoutInfo
);
405 DPRINT("Number of partitions: %u\n", LayoutInfo
->PartitionCount
);
408 for (i
= 0; i
< LayoutInfo
->PartitionCount
; i
++)
410 if (!IsContainerPartition(LayoutInfo
->PartitionEntry
[i
].PartitionType
) &&
411 LayoutInfo
->PartitionEntry
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
414 swprintf(DeviceNameBuffer
,
415 L
"\\Device\\Harddisk%lu\\Partition%lu",
418 RtlInitUnicodeString(&DeviceName
, DeviceNameBuffer
);
420 swprintf(ArcNameBuffer
,
421 L
"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(%lu)",
424 RtlInitUnicodeString(&ArcName
, ArcNameBuffer
);
426 DPRINT("%wZ ==> %wZ\n", &ArcName
, &DeviceName
);
428 Status
= IoAssignArcName(&ArcName
, &DeviceName
);
429 if (!NT_SUCCESS(Status
))
431 DPRINT1("IoAssignArcName failed, status=%lx\n", Status
);
432 ExFreePool(LayoutInfo
);
438 ExFreePool(LayoutInfo
);
439 return STATUS_SUCCESS
;
442 NTSTATUS INIT_FUNCTION
443 IoCreateArcNames(VOID
)
445 PCONFIGURATION_INFORMATION ConfigInfo
;
446 WCHAR DeviceNameBuffer
[80];
447 WCHAR ArcNameBuffer
[80];
448 UNICODE_STRING DeviceName
;
449 UNICODE_STRING ArcName
;
450 ULONG i
, RDiskNumber
;
452 LIST_ENTRY BiosDiskListHead
;
453 LIST_ENTRY DiskListHead
;
455 PDISKENTRY BiosDiskEntry
;
456 PDISKENTRY DiskEntry
;
458 DPRINT("IoCreateArcNames() called\n");
460 ConfigInfo
= IoGetConfigurationInformation();
462 /* create ARC names for floppy drives */
463 DPRINT("Floppy drives: %lu\n", ConfigInfo
->FloppyCount
);
464 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
466 swprintf(DeviceNameBuffer
,
467 L
"\\Device\\Floppy%lu",
469 RtlInitUnicodeString(&DeviceName
,
472 swprintf(ArcNameBuffer
,
473 L
"\\ArcName\\multi(0)disk(0)fdisk(%lu)",
475 RtlInitUnicodeString(&ArcName
,
477 DPRINT("%wZ ==> %wZ\n",
481 Status
= IoAssignArcName(&ArcName
,
483 if (!NT_SUCCESS(Status
))
487 /* create ARC names for hard disk drives */
488 InitializeListHead(&BiosDiskListHead
);
489 InitializeListHead(&DiskListHead
);
490 IopEnumerateBiosDisks(&BiosDiskListHead
);
491 IopEnumerateDisks(&DiskListHead
);
494 while (!IsListEmpty(&BiosDiskListHead
))
496 Entry
= RemoveHeadList(&BiosDiskListHead
);
497 BiosDiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
498 Entry
= DiskListHead
.Flink
;
499 while (Entry
!= &DiskListHead
)
501 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
502 if (DiskEntry
->Checksum
== BiosDiskEntry
->Checksum
&&
503 DiskEntry
->Signature
== BiosDiskEntry
->Signature
)
506 Status
= IopAssignArcNamesToDisk(DiskEntry
->DeviceObject
, RDiskNumber
, DiskEntry
->DiskNumber
);
508 RemoveEntryList(&DiskEntry
->ListEntry
);
509 ExFreePool(DiskEntry
);
512 Entry
= Entry
->Flink
;
515 ExFreePool(BiosDiskEntry
);
518 while (!IsListEmpty(&DiskListHead
))
520 Entry
= RemoveHeadList(&DiskListHead
);
521 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
522 ExFreePool(DiskEntry
);
525 /* create ARC names for cdrom drives */
526 DPRINT("CD-ROM drives: %lu\n", ConfigInfo
->CdRomCount
);
527 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
529 swprintf(DeviceNameBuffer
,
530 L
"\\Device\\CdRom%lu",
532 RtlInitUnicodeString(&DeviceName
,
535 swprintf(ArcNameBuffer
,
536 L
"\\ArcName\\multi(0)disk(0)cdrom(%lu)",
538 RtlInitUnicodeString(&ArcName
,
540 DPRINT("%wZ ==> %wZ\n",
544 Status
= IoAssignArcName(&ArcName
,
546 if (!NT_SUCCESS(Status
))
550 DPRINT("IoCreateArcNames() done\n");
552 return(STATUS_SUCCESS
);
556 static NTSTATUS INIT_FUNCTION
557 IopCheckCdromDevices(PULONG DeviceNumber
)
559 PCONFIGURATION_INFORMATION ConfigInfo
;
560 OBJECT_ATTRIBUTES ObjectAttributes
;
561 UNICODE_STRING DeviceName
;
562 WCHAR DeviceNameBuffer
[MAX_PATH
];
566 IO_STATUS_BLOCK IoStatusBlock
;
568 PFILE_FS_VOLUME_INFORMATION FileFsVolume
;
569 USHORT Buffer
[FS_VOLUME_BUFFER_SIZE
];
571 FileFsVolume
= (PFILE_FS_VOLUME_INFORMATION
)Buffer
;
574 ConfigInfo
= IoGetConfigurationInformation();
575 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
578 swprintf(DeviceNameBuffer
,
579 L
"\\Device\\CdRom%lu\\",
581 RtlInitUnicodeString(&DeviceName
,
584 InitializeObjectAttributes(&ObjectAttributes
,
590 Status
= ZwOpenFile(&Handle
,
596 DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i
, Status
);
597 if (NT_SUCCESS(Status
))
599 Status
= ZwQueryVolumeInformationFile(Handle
,
602 FS_VOLUME_BUFFER_SIZE
,
603 FileFsVolumeInformation
);
604 DPRINT("ZwQueryVolumeInformationFile() Status %lx\n", Status
);
605 if (NT_SUCCESS(Status
))
607 DPRINT("VolumeLabel: '%S'\n", FileFsVolume
->VolumeLabel
);
608 if (_wcsicmp(FileFsVolume
->VolumeLabel
, L
"REACTOS") == 0)
612 return(STATUS_SUCCESS
);
620 * Check for 'reactos/ntoskrnl.exe' first...
623 swprintf(DeviceNameBuffer
,
624 L
"\\Device\\CdRom%lu\\reactos\\ntoskrnl.exe",
626 RtlInitUnicodeString(&DeviceName
,
629 InitializeObjectAttributes(&ObjectAttributes
,
635 Status
= ZwOpenFile(&Handle
,
641 DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i
, Status
);
642 if (NT_SUCCESS(Status
))
644 DPRINT("Found ntoskrnl.exe on Cdrom%lu\n", i
);
647 return(STATUS_SUCCESS
);
651 * ...and for 'reactos/system32/ntoskrnl.exe' also.
654 swprintf(DeviceNameBuffer
,
655 L
"\\Device\\CdRom%lu\\reactos\\system32\\ntoskrnl.exe",
657 RtlInitUnicodeString(&DeviceName
,
660 InitializeObjectAttributes(&ObjectAttributes
,
666 Status
= ZwOpenFile(&Handle
,
672 DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i
, Status
);
673 if (NT_SUCCESS(Status
))
675 DPRINT("Found ntoskrnl.exe on Cdrom%lu\n", i
);
678 return(STATUS_SUCCESS
);
682 DPRINT("Could not find ntoskrnl.exe\n");
683 *DeviceNumber
= (ULONG
)-1;
685 return(STATUS_UNSUCCESSFUL
);
689 NTSTATUS INIT_FUNCTION
690 IoCreateSystemRootLink(PCHAR ParameterLine
)
692 OBJECT_ATTRIBUTES ObjectAttributes
;
693 IO_STATUS_BLOCK IoStatusBlock
;
694 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
695 UNICODE_STRING DeviceName
;
696 UNICODE_STRING ArcName
;
697 UNICODE_STRING BootPath
;
699 PWCHAR ArcNameBuffer
;
705 /* Create local parameter line copy */
706 ParamBuffer
= ExAllocatePool(PagedPool
, 256);
707 strcpy(ParamBuffer
, (char *)ParameterLine
);
709 DPRINT("%s\n", ParamBuffer
);
710 /* Format: <arc_name>\<path> [options...] */
712 /* cut options off */
713 p
= strchr(ParamBuffer
, ' ');
716 DPRINT("%s\n", ParamBuffer
);
719 p
= strchr(ParamBuffer
, '\\');
722 DPRINT("Boot path: %s\n", p
);
723 RtlCreateUnicodeStringFromAsciiz(&BootPath
, p
);
728 DPRINT("Boot path: %s\n", "\\");
729 RtlCreateUnicodeStringFromAsciiz(&BootPath
, "\\");
731 DPRINT("ARC name: %s\n", ParamBuffer
);
733 p
= strstr(ParamBuffer
, "cdrom");
738 DPRINT("Booting from CD-ROM!\n");
739 Status
= IopCheckCdromDevices(&DeviceNumber
);
740 if (!NT_SUCCESS(Status
))
742 CPRINT("Failed to find setup disk!\n");
746 sprintf(p
, "cdrom(%lu)", DeviceNumber
);
748 DPRINT("New ARC name: %s\n", ParamBuffer
);
750 /* Adjust original command line */
751 p
= strstr(ParameterLine
, "cdrom");
763 sprintf(p
, "cdrom(%lu)", DeviceNumber
);
769 /* Only arc name left - build full arc name */
770 ArcNameBuffer
= ExAllocatePool(PagedPool
, 256 * sizeof(WCHAR
));
771 swprintf(ArcNameBuffer
,
772 L
"\\ArcName\\%S", ParamBuffer
);
773 RtlInitUnicodeString(&ArcName
, ArcNameBuffer
);
774 DPRINT("Arc name: %wZ\n", &ArcName
);
776 /* free ParamBuffer */
777 ExFreePool(ParamBuffer
);
779 /* allocate device name string */
780 DeviceName
.Length
= 0;
781 DeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
782 DeviceName
.Buffer
= ExAllocatePool(PagedPool
, 256 * sizeof(WCHAR
));
784 InitializeObjectAttributes(&ObjectAttributes
,
790 Status
= ZwOpenSymbolicLinkObject(&Handle
,
791 SYMBOLIC_LINK_ALL_ACCESS
,
793 if (!NT_SUCCESS(Status
))
795 RtlFreeUnicodeString(&BootPath
);
796 ExFreePool(DeviceName
.Buffer
);
797 CPRINT("ZwOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
800 ExFreePool(ArcName
.Buffer
);
804 ExFreePool(ArcName
.Buffer
);
806 Status
= ZwQuerySymbolicLinkObject(Handle
,
810 if (!NT_SUCCESS(Status
))
812 RtlFreeUnicodeString(&BootPath
);
813 ExFreePool(DeviceName
.Buffer
);
814 CPRINT("ZwQuerySymbolicObject() failed (Status %x)\n",
819 DPRINT("Length: %lu DeviceName: %wZ\n", Length
, &DeviceName
);
821 RtlAppendUnicodeStringToString(&DeviceName
,
824 RtlFreeUnicodeString(&BootPath
);
825 DPRINT("DeviceName: %wZ\n", &DeviceName
);
827 /* create the '\SystemRoot' link */
828 Status
= IoCreateSymbolicLink(&LinkName
,
830 ExFreePool(DeviceName
.Buffer
);
831 if (!NT_SUCCESS(Status
))
833 CPRINT("IoCreateSymbolicLink() failed (Status %x)\n",
839 /* Check whether '\SystemRoot'(LinkName) can be opened */
840 InitializeObjectAttributes(&ObjectAttributes
,
846 Status
= ZwOpenFile(&Handle
,
852 if (!NT_SUCCESS(Status
))
854 CPRINT("ZwOpenFile() failed to open '\\SystemRoot' (Status %x)\n",
861 return(STATUS_SUCCESS
);