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>
20 DiskQueryRoutine(PWSTR ValueName
,
27 static VOID INIT_FUNCTION
28 IopEnumerateBiosDisks(PLIST_ENTRY ListHead
);
30 static VOID INIT_FUNCTION
31 IopEnumerateDisks(PLIST_ENTRY ListHead
);
33 static NTSTATUS INIT_FUNCTION
34 IopAssignArcNamesToDisk(PDEVICE_OBJECT DeviceObject
, ULONG RDisk
, ULONG DiskNumber
);
36 static NTSTATUS INIT_FUNCTION
37 IopCheckCdromDevices(PULONG DeviceNumber
);
39 #if defined (ALLOC_PRAGMA)
40 #pragma alloc_text(INIT, DiskQueryRoutine)
41 #pragma alloc_text(INIT, IopEnumerateBiosDisks)
42 #pragma alloc_text(INIT, IopEnumerateDisks)
43 #pragma alloc_text(INIT, IopAssignArcNamesToDisk)
44 #pragma alloc_text(INIT, IoCreateArcNames)
45 #pragma alloc_text(INIT, IopCheckCdromDevices)
46 #pragma alloc_text(INIT, IoCreateSystemRootLink)
50 /* MACROS *******************************************************************/
52 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
54 /* FUNCTIONS ****************************************************************/
60 DiskQueryRoutine(PWSTR ValueName
,
67 PLIST_ENTRY ListHead
= (PLIST_ENTRY
)Context
;
68 PULONG GlobalDiskCount
= (PULONG
)EntryContext
;
72 if (ValueType
== REG_SZ
&&
73 ValueLength
== 20 * sizeof(WCHAR
))
75 DiskEntry
= ExAllocatePool(PagedPool
, sizeof(DISKENTRY
));
76 if (DiskEntry
== NULL
)
78 return STATUS_NO_MEMORY
;
80 DiskEntry
->DiskNumber
= (*GlobalDiskCount
)++;
82 NameU
.Buffer
= (PWCHAR
)ValueData
;
83 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
84 RtlUnicodeStringToInteger(&NameU
, 16, &DiskEntry
->Checksum
);
86 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
87 RtlUnicodeStringToInteger(&NameU
, 16, &DiskEntry
->Signature
);
89 InsertTailList(ListHead
, &DiskEntry
->ListEntry
);
92 return STATUS_SUCCESS
;
95 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
97 STATIC VOID INIT_FUNCTION
98 IopEnumerateBiosDisks(PLIST_ENTRY ListHead
)
100 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
103 ULONG ControllerCount
;
106 ULONG GlobalDiskCount
=0;
109 memset(QueryTable
, 0, sizeof(QueryTable
));
110 QueryTable
[0].Name
= L
"Identifier";
111 QueryTable
[0].QueryRoutine
= DiskQueryRoutine
;
112 QueryTable
[0].EntryContext
= (PVOID
)&GlobalDiskCount
;
117 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
118 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
123 if (!NT_SUCCESS(Status
))
128 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
129 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
134 if (NT_SUCCESS(Status
))
139 swprintf(Name
, L
"%s\\%lu\\DiskController\\%lu", ROOT_NAME
, AdapterCount
, ControllerCount
);
140 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
145 if (!NT_SUCCESS(Status
))
150 swprintf(Name
, L
"%s\\%lu\\DiskController\\%lu\\DiskPeripheral", ROOT_NAME
, AdapterCount
, ControllerCount
);
151 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
156 if (NT_SUCCESS(Status
))
161 swprintf(Name
, L
"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, ControllerCount
, DiskCount
);
162 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
167 if (!NT_SUCCESS(Status
))
181 STATIC VOID INIT_FUNCTION
182 IopEnumerateDisks(PLIST_ENTRY ListHead
)
185 PDISKENTRY DiskEntry
;
186 DISK_GEOMETRY DiskGeometry
;
189 IO_STATUS_BLOCK StatusBlock
;
190 LARGE_INTEGER PartitionOffset
;
192 WCHAR DeviceNameBuffer
[80];
193 UNICODE_STRING DeviceName
;
195 PDEVICE_OBJECT DeviceObject
;
196 PFILE_OBJECT FileObject
;
197 BOOLEAN IsRemovableMedia
;
198 PPARTITION_SECTOR PartitionBuffer
= NULL
;
199 ULONG PartitionBufferSize
= 0;
202 for (i
= 0; i
< IoGetConfigurationInformation()->DiskCount
; i
++)
205 swprintf(DeviceNameBuffer
,
206 L
"\\Device\\Harddisk%lu\\Partition0",
208 RtlInitUnicodeString(&DeviceName
,
212 Status
= IoGetDeviceObjectPointer(&DeviceName
,
216 if (!NT_SUCCESS(Status
))
220 IsRemovableMedia
= DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
? TRUE
: FALSE
;
221 ObDereferenceObject(FileObject
);
222 if (IsRemovableMedia
)
224 ObDereferenceObject(DeviceObject
);
227 DiskEntry
= ExAllocatePool(PagedPool
, sizeof(DISKENTRY
));
228 if (DiskEntry
== NULL
)
232 DiskEntry
->DiskNumber
= i
;
233 DiskEntry
->DeviceObject
= DeviceObject
;
235 /* determine the sector size */
236 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
237 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
242 sizeof(DISK_GEOMETRY
),
251 Status
= IoCallDriver(DeviceObject
, Irp
);
252 if (Status
== STATUS_PENDING
)
254 KeWaitForSingleObject(&Event
,
259 Status
= StatusBlock
.Status
;
261 if (!NT_SUCCESS(Status
))
265 if (PartitionBuffer
!= NULL
&& PartitionBufferSize
< DiskGeometry
.BytesPerSector
)
267 ExFreePool(PartitionBuffer
);
268 PartitionBuffer
= NULL
;
270 if (PartitionBuffer
== NULL
)
272 PartitionBufferSize
= max(DiskGeometry
.BytesPerSector
, PAGE_SIZE
);
273 PartitionBuffer
= ExAllocatePool(PagedPool
, PartitionBufferSize
);
274 if (PartitionBuffer
== NULL
)
280 /* read the partition sector */
281 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
282 PartitionOffset
.QuadPart
= 0;
283 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
286 DiskGeometry
.BytesPerSector
,
290 Status
= IoCallDriver(DeviceObject
, Irp
);
291 if (Status
== STATUS_PENDING
)
293 KeWaitForSingleObject(&Event
,
298 Status
= StatusBlock
.Status
;
301 if (!NT_SUCCESS(Status
))
306 /* Calculate the MBR checksum */
307 DiskEntry
->Checksum
= 0;
308 Buffer
= (PULONG
)PartitionBuffer
;
309 for (k
= 0; k
< 128; k
++)
311 DiskEntry
->Checksum
+= Buffer
[k
];
313 DiskEntry
->Checksum
= ~DiskEntry
->Checksum
+ 1;
314 DiskEntry
->Signature
= PartitionBuffer
->Signature
;
316 InsertTailList(ListHead
, &DiskEntry
->ListEntry
);
320 ExFreePool(PartitionBuffer
);
324 STATIC NTSTATUS INIT_FUNCTION
325 IopAssignArcNamesToDisk(PDEVICE_OBJECT DeviceObject
, ULONG RDisk
, ULONG DiskNumber
)
327 WCHAR DeviceNameBuffer
[80];
328 WCHAR ArcNameBuffer
[80];
329 UNICODE_STRING DeviceName
;
330 UNICODE_STRING ArcName
;
331 PDRIVE_LAYOUT_INFORMATION LayoutInfo
= NULL
;
336 IO_STATUS_BLOCK StatusBlock
;
337 ULONG PartitionNumber
;
339 swprintf(DeviceNameBuffer
,
340 L
"\\Device\\Harddisk%lu\\Partition0",
342 RtlInitUnicodeString(&DeviceName
,
345 swprintf(ArcNameBuffer
,
346 L
"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
348 RtlInitUnicodeString(&ArcName
,
351 DPRINT("%wZ ==> %wZ\n", &ArcName
, &DeviceName
);
353 Status
= IoAssignArcName(&ArcName
, &DeviceName
);
354 if (!NT_SUCCESS(Status
))
356 DPRINT1("IoAssignArcName failed, status=%lx\n", Status
);
360 LayoutInfo
= ExAllocatePool(PagedPool
, 2 * PAGE_SIZE
);
361 if (LayoutInfo
== NULL
)
363 return STATUS_NO_MEMORY
;
365 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
366 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT
,
377 ExFreePool(LayoutInfo
);
378 return STATUS_INSUFFICIENT_RESOURCES
;
381 Status
= IoCallDriver(DeviceObject
, Irp
);
382 if (Status
== STATUS_PENDING
)
384 KeWaitForSingleObject(&Event
,
389 Status
= StatusBlock
.Status
;
391 if (!NT_SUCCESS(Status
))
393 ExFreePool(LayoutInfo
);
397 DPRINT("Number of partitions: %u\n", LayoutInfo
->PartitionCount
);
400 for (i
= 0; i
< LayoutInfo
->PartitionCount
; i
++)
402 if (!IsContainerPartition(LayoutInfo
->PartitionEntry
[i
].PartitionType
) &&
403 LayoutInfo
->PartitionEntry
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
406 swprintf(DeviceNameBuffer
,
407 L
"\\Device\\Harddisk%lu\\Partition%lu",
410 RtlInitUnicodeString(&DeviceName
, DeviceNameBuffer
);
412 swprintf(ArcNameBuffer
,
413 L
"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(%lu)",
416 RtlInitUnicodeString(&ArcName
, ArcNameBuffer
);
418 DPRINT("%wZ ==> %wZ\n", &ArcName
, &DeviceName
);
420 Status
= IoAssignArcName(&ArcName
, &DeviceName
);
421 if (!NT_SUCCESS(Status
))
423 DPRINT1("IoAssignArcName failed, status=%lx\n", Status
);
424 ExFreePool(LayoutInfo
);
430 ExFreePool(LayoutInfo
);
431 return STATUS_SUCCESS
;
434 NTSTATUS INIT_FUNCTION
435 IoCreateArcNames(VOID
)
437 PCONFIGURATION_INFORMATION ConfigInfo
;
438 WCHAR DeviceNameBuffer
[80];
439 WCHAR ArcNameBuffer
[80];
440 UNICODE_STRING DeviceName
;
441 UNICODE_STRING ArcName
;
442 ULONG i
, RDiskNumber
;
444 LIST_ENTRY BiosDiskListHead
;
445 LIST_ENTRY DiskListHead
;
447 PDISKENTRY BiosDiskEntry
;
448 PDISKENTRY DiskEntry
;
450 DPRINT("IoCreateArcNames() called\n");
452 ConfigInfo
= IoGetConfigurationInformation();
454 /* create ARC names for floppy drives */
455 DPRINT("Floppy drives: %lu\n", ConfigInfo
->FloppyCount
);
456 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
458 swprintf(DeviceNameBuffer
,
459 L
"\\Device\\Floppy%lu",
461 RtlInitUnicodeString(&DeviceName
,
464 swprintf(ArcNameBuffer
,
465 L
"\\ArcName\\multi(0)disk(0)fdisk(%lu)",
467 RtlInitUnicodeString(&ArcName
,
469 DPRINT("%wZ ==> %wZ\n",
473 Status
= IoAssignArcName(&ArcName
,
475 if (!NT_SUCCESS(Status
))
479 /* create ARC names for hard disk drives */
480 InitializeListHead(&BiosDiskListHead
);
481 InitializeListHead(&DiskListHead
);
482 IopEnumerateBiosDisks(&BiosDiskListHead
);
483 IopEnumerateDisks(&DiskListHead
);
486 while (!IsListEmpty(&BiosDiskListHead
))
488 Entry
= RemoveHeadList(&BiosDiskListHead
);
489 BiosDiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
490 Entry
= DiskListHead
.Flink
;
491 while (Entry
!= &DiskListHead
)
493 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
494 if (DiskEntry
->Checksum
== BiosDiskEntry
->Checksum
&&
495 DiskEntry
->Signature
== BiosDiskEntry
->Signature
)
498 Status
= IopAssignArcNamesToDisk(DiskEntry
->DeviceObject
, RDiskNumber
, DiskEntry
->DiskNumber
);
500 RemoveEntryList(&DiskEntry
->ListEntry
);
501 ExFreePool(DiskEntry
);
504 Entry
= Entry
->Flink
;
507 ExFreePool(BiosDiskEntry
);
510 while (!IsListEmpty(&DiskListHead
))
512 Entry
= RemoveHeadList(&DiskListHead
);
513 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
514 ExFreePool(DiskEntry
);
517 /* create ARC names for cdrom drives */
518 DPRINT("CD-ROM drives: %lu\n", ConfigInfo
->CdRomCount
);
519 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
521 swprintf(DeviceNameBuffer
,
522 L
"\\Device\\CdRom%lu",
524 RtlInitUnicodeString(&DeviceName
,
527 swprintf(ArcNameBuffer
,
528 L
"\\ArcName\\multi(0)disk(0)cdrom(%lu)",
530 RtlInitUnicodeString(&ArcName
,
532 DPRINT("%wZ ==> %wZ\n",
536 Status
= IoAssignArcName(&ArcName
,
538 if (!NT_SUCCESS(Status
))
542 DPRINT("IoCreateArcNames() done\n");
544 return(STATUS_SUCCESS
);
548 static NTSTATUS INIT_FUNCTION
549 IopCheckCdromDevices(PULONG DeviceNumber
)
551 PCONFIGURATION_INFORMATION ConfigInfo
;
552 OBJECT_ATTRIBUTES ObjectAttributes
;
553 UNICODE_STRING DeviceName
;
554 WCHAR DeviceNameBuffer
[MAX_PATH
];
558 IO_STATUS_BLOCK IoStatusBlock
;
560 PFILE_FS_VOLUME_INFORMATION FileFsVolume
;
561 USHORT Buffer
[FS_VOLUME_BUFFER_SIZE
];
563 FileFsVolume
= (PFILE_FS_VOLUME_INFORMATION
)Buffer
;
566 ConfigInfo
= IoGetConfigurationInformation();
567 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
570 swprintf(DeviceNameBuffer
,
571 L
"\\Device\\CdRom%lu\\",
573 RtlInitUnicodeString(&DeviceName
,
576 InitializeObjectAttributes(&ObjectAttributes
,
582 Status
= ZwOpenFile(&Handle
,
588 DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i
, Status
);
589 if (NT_SUCCESS(Status
))
591 Status
= ZwQueryVolumeInformationFile(Handle
,
594 FS_VOLUME_BUFFER_SIZE
,
595 FileFsVolumeInformation
);
596 DPRINT("ZwQueryVolumeInformationFile() Status %lx\n", Status
);
597 if (NT_SUCCESS(Status
))
599 DPRINT("VolumeLabel: '%S'\n", FileFsVolume
->VolumeLabel
);
600 if (_wcsicmp(FileFsVolume
->VolumeLabel
, L
"REACTOS") == 0)
604 return(STATUS_SUCCESS
);
612 * Check for 'reactos/ntoskrnl.exe' first...
615 swprintf(DeviceNameBuffer
,
616 L
"\\Device\\CdRom%lu\\reactos\\ntoskrnl.exe",
618 RtlInitUnicodeString(&DeviceName
,
621 InitializeObjectAttributes(&ObjectAttributes
,
627 Status
= ZwOpenFile(&Handle
,
633 DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i
, Status
);
634 if (NT_SUCCESS(Status
))
636 DPRINT("Found ntoskrnl.exe on Cdrom%lu\n", i
);
639 return(STATUS_SUCCESS
);
643 * ...and for 'reactos/system32/ntoskrnl.exe' also.
646 swprintf(DeviceNameBuffer
,
647 L
"\\Device\\CdRom%lu\\reactos\\system32\\ntoskrnl.exe",
649 RtlInitUnicodeString(&DeviceName
,
652 InitializeObjectAttributes(&ObjectAttributes
,
658 Status
= ZwOpenFile(&Handle
,
664 DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i
, Status
);
665 if (NT_SUCCESS(Status
))
667 DPRINT("Found ntoskrnl.exe on Cdrom%lu\n", i
);
670 return(STATUS_SUCCESS
);
674 DPRINT("Could not find ntoskrnl.exe\n");
675 *DeviceNumber
= (ULONG
)-1;
677 return(STATUS_UNSUCCESSFUL
);
681 NTSTATUS INIT_FUNCTION
682 IoCreateSystemRootLink(PCHAR ParameterLine
)
684 OBJECT_ATTRIBUTES ObjectAttributes
;
685 IO_STATUS_BLOCK IoStatusBlock
;
686 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
687 UNICODE_STRING DeviceName
;
688 UNICODE_STRING ArcName
;
689 UNICODE_STRING BootPath
;
691 PWCHAR ArcNameBuffer
;
697 /* Create local parameter line copy */
698 ParamBuffer
= ExAllocatePool(PagedPool
, 256);
699 strcpy(ParamBuffer
, (char *)ParameterLine
);
701 DPRINT("%s\n", ParamBuffer
);
702 /* Format: <arc_name>\<path> [options...] */
704 /* cut options off */
705 p
= strchr(ParamBuffer
, ' ');
708 DPRINT("%s\n", ParamBuffer
);
711 p
= strchr(ParamBuffer
, '\\');
714 DPRINT("Boot path: %s\n", p
);
715 RtlCreateUnicodeStringFromAsciiz(&BootPath
, p
);
720 DPRINT("Boot path: %s\n", "\\");
721 RtlCreateUnicodeStringFromAsciiz(&BootPath
, "\\");
723 DPRINT("ARC name: %s\n", ParamBuffer
);
725 p
= strstr(ParamBuffer
, "cdrom");
730 DPRINT("Booting from CD-ROM!\n");
731 Status
= IopCheckCdromDevices(&DeviceNumber
);
732 if (!NT_SUCCESS(Status
))
734 CPRINT("Failed to find setup disk!\n");
738 sprintf(p
, "cdrom(%lu)", DeviceNumber
);
740 DPRINT("New ARC name: %s\n", ParamBuffer
);
742 /* Adjust original command line */
743 p
= strstr(ParameterLine
, "cdrom");
755 sprintf(p
, "cdrom(%lu)", DeviceNumber
);
761 /* Only arc name left - build full arc name */
762 ArcNameBuffer
= ExAllocatePool(PagedPool
, 256 * sizeof(WCHAR
));
763 swprintf(ArcNameBuffer
,
764 L
"\\ArcName\\%S", ParamBuffer
);
765 RtlInitUnicodeString(&ArcName
, ArcNameBuffer
);
766 DPRINT("Arc name: %wZ\n", &ArcName
);
768 /* free ParamBuffer */
769 ExFreePool(ParamBuffer
);
771 /* allocate device name string */
772 DeviceName
.Length
= 0;
773 DeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
774 DeviceName
.Buffer
= ExAllocatePool(PagedPool
, 256 * sizeof(WCHAR
));
776 InitializeObjectAttributes(&ObjectAttributes
,
782 Status
= ZwOpenSymbolicLinkObject(&Handle
,
783 SYMBOLIC_LINK_ALL_ACCESS
,
785 if (!NT_SUCCESS(Status
))
787 RtlFreeUnicodeString(&BootPath
);
788 ExFreePool(DeviceName
.Buffer
);
789 CPRINT("ZwOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
792 ExFreePool(ArcName
.Buffer
);
796 ExFreePool(ArcName
.Buffer
);
798 Status
= ZwQuerySymbolicLinkObject(Handle
,
802 if (!NT_SUCCESS(Status
))
804 RtlFreeUnicodeString(&BootPath
);
805 ExFreePool(DeviceName
.Buffer
);
806 CPRINT("ZwQuerySymbolicObject() failed (Status %x)\n",
811 DPRINT("Length: %lu DeviceName: %wZ\n", Length
, &DeviceName
);
813 RtlAppendUnicodeStringToString(&DeviceName
,
816 RtlFreeUnicodeString(&BootPath
);
817 DPRINT("DeviceName: %wZ\n", &DeviceName
);
819 /* create the '\SystemRoot' link */
820 Status
= IoCreateSymbolicLink(&LinkName
,
822 ExFreePool(DeviceName
.Buffer
);
823 if (!NT_SUCCESS(Status
))
825 CPRINT("IoCreateSymbolicLink() failed (Status %x)\n",
831 /* Check whether '\SystemRoot'(LinkName) can be opened */
832 InitializeObjectAttributes(&ObjectAttributes
,
838 Status
= ZwOpenFile(&Handle
,
844 if (!NT_SUCCESS(Status
))
846 CPRINT("ZwOpenFile() failed to open '\\SystemRoot' (Status %x)\n",
853 return(STATUS_SUCCESS
);