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 /* FUNCTIONS ****************************************************************/
28 DiskQueryRoutine(PWSTR ValueName
,
35 PLIST_ENTRY ListHead
= (PLIST_ENTRY
)Context
;
36 PULONG GlobalDiskCount
= (PULONG
)EntryContext
;
40 if (ValueType
== REG_SZ
&&
41 ValueLength
== 20 * sizeof(WCHAR
))
43 DiskEntry
= ExAllocatePool(PagedPool
, sizeof(DISKENTRY
));
44 if (DiskEntry
== NULL
)
46 return STATUS_NO_MEMORY
;
48 DiskEntry
->DiskNumber
= (*GlobalDiskCount
)++;
50 NameU
.Buffer
= (PWCHAR
)ValueData
;
51 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
52 RtlUnicodeStringToInteger(&NameU
, 16, &DiskEntry
->Checksum
);
54 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
55 RtlUnicodeStringToInteger(&NameU
, 16, &DiskEntry
->Signature
);
57 InsertTailList(ListHead
, &DiskEntry
->ListEntry
);
60 return STATUS_SUCCESS
;
63 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
65 STATIC VOID INIT_FUNCTION
66 IopEnumerateBiosDisks(PLIST_ENTRY ListHead
)
68 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
71 ULONG ControllerCount
;
74 ULONG GlobalDiskCount
=0;
77 memset(QueryTable
, 0, sizeof(QueryTable
));
78 QueryTable
[0].Name
= L
"Identifier";
79 QueryTable
[0].QueryRoutine
= DiskQueryRoutine
;
80 QueryTable
[0].EntryContext
= (PVOID
)&GlobalDiskCount
;
85 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
86 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
91 if (!NT_SUCCESS(Status
))
96 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
97 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
102 if (NT_SUCCESS(Status
))
107 swprintf(Name
, L
"%s\\%lu\\DiskController\\%lu", ROOT_NAME
, AdapterCount
, ControllerCount
);
108 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
113 if (!NT_SUCCESS(Status
))
118 swprintf(Name
, L
"%s\\%lu\\DiskController\\%lu\\DiskPeripheral", ROOT_NAME
, AdapterCount
, ControllerCount
);
119 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
124 if (NT_SUCCESS(Status
))
129 swprintf(Name
, L
"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, ControllerCount
, DiskCount
);
130 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
135 if (!NT_SUCCESS(Status
))
149 STATIC VOID INIT_FUNCTION
150 IopEnumerateDisks(PLIST_ENTRY ListHead
)
153 PDISKENTRY DiskEntry
;
154 DISK_GEOMETRY DiskGeometry
;
157 IO_STATUS_BLOCK StatusBlock
;
158 LARGE_INTEGER PartitionOffset
;
160 WCHAR DeviceNameBuffer
[80];
161 UNICODE_STRING DeviceName
;
163 PDEVICE_OBJECT DeviceObject
;
164 PFILE_OBJECT FileObject
;
165 BOOLEAN IsRemovableMedia
;
166 PPARTITION_SECTOR PartitionBuffer
= NULL
;
167 ULONG PartitionBufferSize
= 0;
170 for (i
= 0; i
< IoGetConfigurationInformation()->DiskCount
; i
++)
173 swprintf(DeviceNameBuffer
,
174 L
"\\Device\\Harddisk%lu\\Partition0",
176 RtlInitUnicodeString(&DeviceName
,
180 Status
= IoGetDeviceObjectPointer(&DeviceName
,
184 if (!NT_SUCCESS(Status
))
188 IsRemovableMedia
= DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
? TRUE
: FALSE
;
189 ObDereferenceObject(FileObject
);
190 if (IsRemovableMedia
)
192 ObDereferenceObject(DeviceObject
);
195 DiskEntry
= ExAllocatePool(PagedPool
, sizeof(DISKENTRY
));
196 if (DiskEntry
== NULL
)
200 DiskEntry
->DiskNumber
= i
;
201 DiskEntry
->DeviceObject
= DeviceObject
;
203 /* determine the sector size */
204 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
205 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
210 sizeof(DISK_GEOMETRY
),
219 Status
= IoCallDriver(DeviceObject
, Irp
);
220 if (Status
== STATUS_PENDING
)
222 KeWaitForSingleObject(&Event
,
227 Status
= StatusBlock
.Status
;
229 if (!NT_SUCCESS(Status
))
233 if (PartitionBuffer
!= NULL
&& PartitionBufferSize
< DiskGeometry
.BytesPerSector
)
235 ExFreePool(PartitionBuffer
);
236 PartitionBuffer
= NULL
;
238 if (PartitionBuffer
== NULL
)
240 PartitionBufferSize
= max(DiskGeometry
.BytesPerSector
, PAGE_SIZE
);
241 PartitionBuffer
= ExAllocatePool(PagedPool
, PartitionBufferSize
);
242 if (PartitionBuffer
== NULL
)
248 /* read the partition sector */
249 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
250 PartitionOffset
.QuadPart
= 0;
251 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
254 DiskGeometry
.BytesPerSector
,
258 Status
= IoCallDriver(DeviceObject
, Irp
);
259 if (Status
== STATUS_PENDING
)
261 KeWaitForSingleObject(&Event
,
266 Status
= StatusBlock
.Status
;
269 if (!NT_SUCCESS(Status
))
274 /* Calculate the MBR checksum */
275 DiskEntry
->Checksum
= 0;
276 Buffer
= (PULONG
)PartitionBuffer
;
277 for (k
= 0; k
< 128; k
++)
279 DiskEntry
->Checksum
+= Buffer
[k
];
281 DiskEntry
->Checksum
= ~DiskEntry
->Checksum
+ 1;
282 DiskEntry
->Signature
= PartitionBuffer
->Signature
;
284 InsertTailList(ListHead
, &DiskEntry
->ListEntry
);
288 ExFreePool(PartitionBuffer
);
292 STATIC NTSTATUS INIT_FUNCTION
293 IopAssignArcNamesToDisk(PDEVICE_OBJECT DeviceObject
, ULONG RDisk
, ULONG DiskNumber
)
295 WCHAR DeviceNameBuffer
[80];
296 WCHAR ArcNameBuffer
[80];
297 UNICODE_STRING DeviceName
;
298 UNICODE_STRING ArcName
;
299 PDRIVE_LAYOUT_INFORMATION LayoutInfo
= NULL
;
304 IO_STATUS_BLOCK StatusBlock
;
305 ULONG PartitionNumber
;
307 swprintf(DeviceNameBuffer
,
308 L
"\\Device\\Harddisk%lu\\Partition0",
310 RtlInitUnicodeString(&DeviceName
,
313 swprintf(ArcNameBuffer
,
314 L
"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
316 RtlInitUnicodeString(&ArcName
,
319 DPRINT("%wZ ==> %wZ\n", &ArcName
, &DeviceName
);
321 Status
= IoAssignArcName(&ArcName
, &DeviceName
);
322 if (!NT_SUCCESS(Status
))
324 DPRINT1("IoAssignArcName failed, status=%lx\n", Status
);
328 LayoutInfo
= ExAllocatePool(PagedPool
, 2 * PAGE_SIZE
);
329 if (LayoutInfo
== NULL
)
331 return STATUS_NO_MEMORY
;
333 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
334 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT
,
345 ExFreePool(LayoutInfo
);
346 return STATUS_INSUFFICIENT_RESOURCES
;
349 Status
= IoCallDriver(DeviceObject
, Irp
);
350 if (Status
== STATUS_PENDING
)
352 KeWaitForSingleObject(&Event
,
357 Status
= StatusBlock
.Status
;
359 if (!NT_SUCCESS(Status
))
361 ExFreePool(LayoutInfo
);
365 DPRINT("Number of partitions: %u\n", LayoutInfo
->PartitionCount
);
368 for (i
= 0; i
< LayoutInfo
->PartitionCount
; i
++)
370 if (!IsContainerPartition(LayoutInfo
->PartitionEntry
[i
].PartitionType
) &&
371 LayoutInfo
->PartitionEntry
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
374 swprintf(DeviceNameBuffer
,
375 L
"\\Device\\Harddisk%lu\\Partition%lu",
378 RtlInitUnicodeString(&DeviceName
, DeviceNameBuffer
);
380 swprintf(ArcNameBuffer
,
381 L
"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(%lu)",
384 RtlInitUnicodeString(&ArcName
, ArcNameBuffer
);
386 DPRINT("%wZ ==> %wZ\n", &ArcName
, &DeviceName
);
388 Status
= IoAssignArcName(&ArcName
, &DeviceName
);
389 if (!NT_SUCCESS(Status
))
391 DPRINT1("IoAssignArcName failed, status=%lx\n", Status
);
392 ExFreePool(LayoutInfo
);
398 ExFreePool(LayoutInfo
);
399 return STATUS_SUCCESS
;
402 NTSTATUS INIT_FUNCTION
403 IoCreateArcNames(VOID
)
405 PCONFIGURATION_INFORMATION ConfigInfo
;
406 WCHAR DeviceNameBuffer
[80];
407 WCHAR ArcNameBuffer
[80];
408 UNICODE_STRING DeviceName
;
409 UNICODE_STRING ArcName
;
410 ULONG i
, RDiskNumber
;
412 LIST_ENTRY BiosDiskListHead
;
413 LIST_ENTRY DiskListHead
;
415 PDISKENTRY BiosDiskEntry
;
416 PDISKENTRY DiskEntry
;
418 DPRINT("IoCreateArcNames() called\n");
420 ConfigInfo
= IoGetConfigurationInformation();
422 /* create ARC names for floppy drives */
423 DPRINT("Floppy drives: %lu\n", ConfigInfo
->FloppyCount
);
424 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
426 swprintf(DeviceNameBuffer
,
427 L
"\\Device\\Floppy%lu",
429 RtlInitUnicodeString(&DeviceName
,
432 swprintf(ArcNameBuffer
,
433 L
"\\ArcName\\multi(0)disk(0)fdisk(%lu)",
435 RtlInitUnicodeString(&ArcName
,
437 DPRINT("%wZ ==> %wZ\n",
441 Status
= IoAssignArcName(&ArcName
,
443 if (!NT_SUCCESS(Status
))
447 /* create ARC names for hard disk drives */
448 InitializeListHead(&BiosDiskListHead
);
449 InitializeListHead(&DiskListHead
);
450 IopEnumerateBiosDisks(&BiosDiskListHead
);
451 IopEnumerateDisks(&DiskListHead
);
454 while (!IsListEmpty(&BiosDiskListHead
))
456 Entry
= RemoveHeadList(&BiosDiskListHead
);
457 BiosDiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
458 Entry
= DiskListHead
.Flink
;
459 while (Entry
!= &DiskListHead
)
461 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
462 if (DiskEntry
->Checksum
== BiosDiskEntry
->Checksum
&&
463 DiskEntry
->Signature
== BiosDiskEntry
->Signature
)
466 Status
= IopAssignArcNamesToDisk(DiskEntry
->DeviceObject
, RDiskNumber
, DiskEntry
->DiskNumber
);
468 RemoveEntryList(&DiskEntry
->ListEntry
);
469 ExFreePool(DiskEntry
);
472 Entry
= Entry
->Flink
;
475 ExFreePool(BiosDiskEntry
);
478 while (!IsListEmpty(&DiskListHead
))
480 Entry
= RemoveHeadList(&DiskListHead
);
481 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
482 ExFreePool(DiskEntry
);
485 /* create ARC names for cdrom drives */
486 DPRINT("CD-ROM drives: %lu\n", ConfigInfo
->CdRomCount
);
487 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
489 swprintf(DeviceNameBuffer
,
490 L
"\\Device\\CdRom%lu",
492 RtlInitUnicodeString(&DeviceName
,
495 swprintf(ArcNameBuffer
,
496 L
"\\ArcName\\multi(0)disk(0)cdrom(%lu)",
498 RtlInitUnicodeString(&ArcName
,
500 DPRINT("%wZ ==> %wZ\n",
504 Status
= IoAssignArcName(&ArcName
,
506 if (!NT_SUCCESS(Status
))
510 DPRINT("IoCreateArcNames() done\n");
512 return(STATUS_SUCCESS
);
516 static NTSTATUS INIT_FUNCTION
517 IopCheckCdromDevices(PULONG DeviceNumber
)
519 PCONFIGURATION_INFORMATION ConfigInfo
;
520 OBJECT_ATTRIBUTES ObjectAttributes
;
521 UNICODE_STRING DeviceName
;
522 WCHAR DeviceNameBuffer
[MAX_PATH
];
526 IO_STATUS_BLOCK IoStatusBlock
;
528 PFILE_FS_VOLUME_INFORMATION FileFsVolume
;
529 USHORT Buffer
[FS_VOLUME_BUFFER_SIZE
];
531 FileFsVolume
= (PFILE_FS_VOLUME_INFORMATION
)Buffer
;
534 ConfigInfo
= IoGetConfigurationInformation();
535 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
538 swprintf(DeviceNameBuffer
,
539 L
"\\Device\\CdRom%lu\\",
541 RtlInitUnicodeString(&DeviceName
,
544 InitializeObjectAttributes(&ObjectAttributes
,
550 Status
= ZwOpenFile(&Handle
,
556 DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i
, Status
);
557 if (NT_SUCCESS(Status
))
559 Status
= ZwQueryVolumeInformationFile(Handle
,
562 FS_VOLUME_BUFFER_SIZE
,
563 FileFsVolumeInformation
);
564 DPRINT("ZwQueryVolumeInformationFile() Status %lx\n", Status
);
565 if (NT_SUCCESS(Status
))
567 DPRINT("VolumeLabel: '%S'\n", FileFsVolume
->VolumeLabel
);
568 if (_wcsicmp(FileFsVolume
->VolumeLabel
, L
"REACTOS") == 0)
572 return(STATUS_SUCCESS
);
580 * Check for 'reactos/ntoskrnl.exe' first...
583 swprintf(DeviceNameBuffer
,
584 L
"\\Device\\CdRom%lu\\reactos\\ntoskrnl.exe",
586 RtlInitUnicodeString(&DeviceName
,
589 InitializeObjectAttributes(&ObjectAttributes
,
595 Status
= ZwOpenFile(&Handle
,
601 DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i
, Status
);
602 if (NT_SUCCESS(Status
))
604 DPRINT("Found ntoskrnl.exe on Cdrom%lu\n", i
);
607 return(STATUS_SUCCESS
);
611 * ...and for 'reactos/system32/ntoskrnl.exe' also.
614 swprintf(DeviceNameBuffer
,
615 L
"\\Device\\CdRom%lu\\reactos\\system32\\ntoskrnl.exe",
617 RtlInitUnicodeString(&DeviceName
,
620 InitializeObjectAttributes(&ObjectAttributes
,
626 Status
= ZwOpenFile(&Handle
,
632 DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i
, Status
);
633 if (NT_SUCCESS(Status
))
635 DPRINT("Found ntoskrnl.exe on Cdrom%lu\n", i
);
638 return(STATUS_SUCCESS
);
642 DPRINT("Could not find ntoskrnl.exe\n");
643 *DeviceNumber
= (ULONG
)-1;
645 return(STATUS_UNSUCCESSFUL
);
649 NTSTATUS INIT_FUNCTION
650 IoCreateSystemRootLink(PCHAR ParameterLine
)
652 OBJECT_ATTRIBUTES ObjectAttributes
;
653 IO_STATUS_BLOCK IoStatusBlock
;
654 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
655 UNICODE_STRING DeviceName
;
656 UNICODE_STRING ArcName
;
657 UNICODE_STRING BootPath
;
659 PWCHAR ArcNameBuffer
;
665 /* Create local parameter line copy */
666 ParamBuffer
= ExAllocatePool(PagedPool
, 256);
667 strcpy(ParamBuffer
, (char *)ParameterLine
);
669 DPRINT("%s\n", ParamBuffer
);
670 /* Format: <arc_name>\<path> [options...] */
672 /* cut options off */
673 p
= strchr(ParamBuffer
, ' ');
676 DPRINT("%s\n", ParamBuffer
);
679 p
= strchr(ParamBuffer
, '\\');
682 DPRINT("Boot path: %s\n", p
);
683 RtlCreateUnicodeStringFromAsciiz(&BootPath
, p
);
688 DPRINT("Boot path: %s\n", "\\");
689 RtlCreateUnicodeStringFromAsciiz(&BootPath
, "\\");
691 DPRINT("ARC name: %s\n", ParamBuffer
);
693 p
= strstr(ParamBuffer
, "cdrom");
698 DPRINT("Booting from CD-ROM!\n");
699 Status
= IopCheckCdromDevices(&DeviceNumber
);
700 if (!NT_SUCCESS(Status
))
702 CPRINT("Failed to find setup disk!\n");
706 sprintf(p
, "cdrom(%lu)", DeviceNumber
);
708 DPRINT("New ARC name: %s\n", ParamBuffer
);
710 /* Adjust original command line */
711 p
= strstr(ParameterLine
, "cdrom");
723 sprintf(p
, "cdrom(%lu)", DeviceNumber
);
729 /* Only arc name left - build full arc name */
730 ArcNameBuffer
= ExAllocatePool(PagedPool
, 256 * sizeof(WCHAR
));
731 swprintf(ArcNameBuffer
,
732 L
"\\ArcName\\%S", ParamBuffer
);
733 RtlInitUnicodeString(&ArcName
, ArcNameBuffer
);
734 DPRINT("Arc name: %wZ\n", &ArcName
);
736 /* free ParamBuffer */
737 ExFreePool(ParamBuffer
);
739 /* allocate device name string */
740 DeviceName
.Length
= 0;
741 DeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
742 DeviceName
.Buffer
= ExAllocatePool(PagedPool
, 256 * sizeof(WCHAR
));
744 InitializeObjectAttributes(&ObjectAttributes
,
750 Status
= ZwOpenSymbolicLinkObject(&Handle
,
751 SYMBOLIC_LINK_ALL_ACCESS
,
753 if (!NT_SUCCESS(Status
))
755 RtlFreeUnicodeString(&BootPath
);
756 ExFreePool(DeviceName
.Buffer
);
757 CPRINT("ZwOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
760 ExFreePool(ArcName
.Buffer
);
764 ExFreePool(ArcName
.Buffer
);
766 Status
= ZwQuerySymbolicLinkObject(Handle
,
770 if (!NT_SUCCESS(Status
))
772 RtlFreeUnicodeString(&BootPath
);
773 ExFreePool(DeviceName
.Buffer
);
774 CPRINT("ZwQuerySymbolicObject() failed (Status %x)\n",
779 DPRINT("Length: %lu DeviceName: %wZ\n", Length
, &DeviceName
);
781 RtlAppendUnicodeStringToString(&DeviceName
,
784 RtlFreeUnicodeString(&BootPath
);
785 DPRINT("DeviceName: %wZ\n", &DeviceName
);
787 /* create the '\SystemRoot' link */
788 Status
= IoCreateSymbolicLink(&LinkName
,
790 ExFreePool(DeviceName
.Buffer
);
791 if (!NT_SUCCESS(Status
))
793 CPRINT("IoCreateSymbolicLink() failed (Status %x)\n",
799 /* Check whether '\SystemRoot'(LinkName) can be opened */
800 InitializeObjectAttributes(&ObjectAttributes
,
806 Status
= ZwOpenFile(&Handle
,
812 if (!NT_SUCCESS(Status
))
814 CPRINT("ZwOpenFile() failed to open '\\SystemRoot' (Status %x)\n",
821 return(STATUS_SUCCESS
);