Copy i8042prt driver from 0.3.1 branch to trunk
[reactos.git] / reactos / ntoskrnl / io / iomgr / arcname.c
1 /* $Id$
2 *
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
7 *
8 * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
9 */
10
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 static NTSTATUS
19 STDCALL INIT_FUNCTION
20 DiskQueryRoutine(PWSTR ValueName,
21 ULONG ValueType,
22 PVOID ValueData,
23 ULONG ValueLength,
24 PVOID Context,
25 PVOID EntryContext);
26
27 static VOID INIT_FUNCTION
28 IopEnumerateBiosDisks(PLIST_ENTRY ListHead);
29
30 static VOID INIT_FUNCTION
31 IopEnumerateDisks(PLIST_ENTRY ListHead);
32
33 static NTSTATUS INIT_FUNCTION
34 IopAssignArcNamesToDisk(PDEVICE_OBJECT DeviceObject, ULONG RDisk, ULONG DiskNumber);
35
36 static NTSTATUS INIT_FUNCTION
37 IopCheckCdromDevices(PULONG DeviceNumber);
38
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)
47 #endif
48
49
50 /* MACROS *******************************************************************/
51
52 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
53
54 /* FUNCTIONS ****************************************************************/
55
56 static
57 NTSTATUS
58 STDCALL
59 INIT_FUNCTION
60 DiskQueryRoutine(PWSTR ValueName,
61 ULONG ValueType,
62 PVOID ValueData,
63 ULONG ValueLength,
64 PVOID Context,
65 PVOID EntryContext)
66 {
67 PLIST_ENTRY ListHead = (PLIST_ENTRY)Context;
68 PULONG GlobalDiskCount = (PULONG)EntryContext;
69 PDISKENTRY DiskEntry;
70 UNICODE_STRING NameU;
71
72 if (ValueType == REG_SZ &&
73 ValueLength == 20 * sizeof(WCHAR))
74 {
75 DiskEntry = ExAllocatePool(PagedPool, sizeof(DISKENTRY));
76 if (DiskEntry == NULL)
77 {
78 return STATUS_NO_MEMORY;
79 }
80 DiskEntry->DiskNumber = (*GlobalDiskCount)++;
81
82 NameU.Buffer = (PWCHAR)ValueData;
83 NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
84 RtlUnicodeStringToInteger(&NameU, 16, &DiskEntry->Checksum);
85
86 NameU.Buffer = (PWCHAR)ValueData + 9;
87 RtlUnicodeStringToInteger(&NameU, 16, &DiskEntry->Signature);
88
89 InsertTailList(ListHead, &DiskEntry->ListEntry);
90 }
91
92 return STATUS_SUCCESS;
93 }
94
95 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
96
97 static VOID INIT_FUNCTION
98 IopEnumerateBiosDisks(PLIST_ENTRY ListHead)
99 {
100 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
101 WCHAR Name[255];
102 ULONG AdapterCount;
103 ULONG ControllerCount;
104 ULONG DiskCount;
105 NTSTATUS Status;
106 ULONG GlobalDiskCount=0;
107
108
109 memset(QueryTable, 0, sizeof(QueryTable));
110 QueryTable[0].Name = L"Identifier";
111 QueryTable[0].QueryRoutine = DiskQueryRoutine;
112 QueryTable[0].EntryContext = (PVOID)&GlobalDiskCount;
113
114 AdapterCount = 0;
115 while (1)
116 {
117 swprintf(Name, L"%s\\%lu", ROOT_NAME, AdapterCount);
118 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
119 Name,
120 &QueryTable[1],
121 NULL,
122 NULL);
123 if (!NT_SUCCESS(Status))
124 {
125 break;
126 }
127
128 swprintf(Name, L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
129 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
130 Name,
131 &QueryTable[1],
132 NULL,
133 NULL);
134 if (NT_SUCCESS(Status))
135 {
136 ControllerCount = 0;
137 while (1)
138 {
139 swprintf(Name, L"%s\\%lu\\DiskController\\%lu", ROOT_NAME, AdapterCount, ControllerCount);
140 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
141 Name,
142 &QueryTable[1],
143 NULL,
144 NULL);
145 if (!NT_SUCCESS(Status))
146 {
147 break;
148 }
149
150 swprintf(Name, L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral", ROOT_NAME, AdapterCount, ControllerCount);
151 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
152 Name,
153 &QueryTable[1],
154 NULL,
155 NULL);
156 if (NT_SUCCESS(Status))
157 {
158 DiskCount = 0;
159 while (1)
160 {
161 swprintf(Name, L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, ControllerCount, DiskCount);
162 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
163 Name,
164 QueryTable,
165 (PVOID)ListHead,
166 NULL);
167 if (!NT_SUCCESS(Status))
168 {
169 break;
170 }
171 DiskCount++;
172 }
173 }
174 ControllerCount++;
175 }
176 }
177 AdapterCount++;
178 }
179 }
180
181 static VOID INIT_FUNCTION
182 IopEnumerateDisks(PLIST_ENTRY ListHead)
183 {
184 ULONG i, k;
185 PDISKENTRY DiskEntry;
186 DISK_GEOMETRY DiskGeometry;
187 KEVENT Event;
188 PIRP Irp;
189 IO_STATUS_BLOCK StatusBlock;
190 LARGE_INTEGER PartitionOffset;
191 PULONG Buffer;
192 WCHAR DeviceNameBuffer[80];
193 UNICODE_STRING DeviceName;
194 NTSTATUS Status;
195 PDEVICE_OBJECT DeviceObject;
196 PFILE_OBJECT FileObject;
197 BOOLEAN IsRemovableMedia;
198 PPARTITION_SECTOR PartitionBuffer = NULL;
199 ULONG PartitionBufferSize = 0;
200
201
202 for (i = 0; i < IoGetConfigurationInformation()->DiskCount; i++)
203 {
204
205 swprintf(DeviceNameBuffer,
206 L"\\Device\\Harddisk%lu\\Partition0",
207 i);
208 RtlInitUnicodeString(&DeviceName,
209 DeviceNameBuffer);
210
211
212 Status = IoGetDeviceObjectPointer(&DeviceName,
213 FILE_READ_DATA,
214 &FileObject,
215 &DeviceObject);
216 if (!NT_SUCCESS(Status))
217 {
218 continue;
219 }
220 IsRemovableMedia = DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA ? TRUE : FALSE;
221 ObDereferenceObject(FileObject);
222 if (IsRemovableMedia)
223 {
224 ObDereferenceObject(DeviceObject);
225 continue;
226 }
227 DiskEntry = ExAllocatePool(PagedPool, sizeof(DISKENTRY));
228 if (DiskEntry == NULL)
229 {
230 KEBUGCHECK(0);
231 }
232 DiskEntry->DiskNumber = i;
233 DiskEntry->DeviceObject = DeviceObject;
234
235 /* determine the sector size */
236 KeInitializeEvent(&Event, NotificationEvent, FALSE);
237 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
238 DeviceObject,
239 NULL,
240 0,
241 &DiskGeometry,
242 sizeof(DISK_GEOMETRY),
243 FALSE,
244 &Event,
245 &StatusBlock);
246 if (Irp == NULL)
247 {
248 KEBUGCHECK(0);
249 }
250
251 Status = IoCallDriver(DeviceObject, Irp);
252 if (Status == STATUS_PENDING)
253 {
254 KeWaitForSingleObject(&Event,
255 Executive,
256 KernelMode,
257 FALSE,
258 NULL);
259 Status = StatusBlock.Status;
260 }
261 if (!NT_SUCCESS(Status))
262 {
263 KEBUGCHECK(0);
264 }
265 if (PartitionBuffer != NULL && PartitionBufferSize < DiskGeometry.BytesPerSector)
266 {
267 ExFreePool(PartitionBuffer);
268 PartitionBuffer = NULL;
269 }
270 if (PartitionBuffer == NULL)
271 {
272 PartitionBufferSize = max(DiskGeometry.BytesPerSector, PAGE_SIZE);
273 PartitionBuffer = ExAllocatePool(PagedPool, PartitionBufferSize);
274 if (PartitionBuffer == NULL)
275 {
276 KEBUGCHECK(0);
277 }
278 }
279
280 /* read the partition sector */
281 KeInitializeEvent(&Event, NotificationEvent, FALSE);
282 PartitionOffset.QuadPart = 0;
283 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
284 DeviceObject,
285 PartitionBuffer,
286 DiskGeometry.BytesPerSector,
287 &PartitionOffset,
288 &Event,
289 &StatusBlock);
290 Status = IoCallDriver(DeviceObject, Irp);
291 if (Status == STATUS_PENDING)
292 {
293 KeWaitForSingleObject(&Event,
294 Executive,
295 KernelMode,
296 FALSE,
297 NULL);
298 Status = StatusBlock.Status;
299 }
300
301 if (!NT_SUCCESS(Status))
302 {
303 KEBUGCHECK(0);
304 }
305
306 /* Calculate the MBR checksum */
307 DiskEntry->Checksum = 0;
308 Buffer = (PULONG)PartitionBuffer;
309 for (k = 0; k < 128; k++)
310 {
311 DiskEntry->Checksum += Buffer[k];
312 }
313 DiskEntry->Checksum = ~DiskEntry->Checksum + 1;
314 DiskEntry->Signature = PartitionBuffer->Signature;
315
316 InsertTailList(ListHead, &DiskEntry->ListEntry);
317 }
318 if (PartitionBuffer)
319 {
320 ExFreePool(PartitionBuffer);
321 }
322 }
323
324 static NTSTATUS INIT_FUNCTION
325 IopAssignArcNamesToDisk(PDEVICE_OBJECT DeviceObject, ULONG RDisk, ULONG DiskNumber)
326 {
327 WCHAR DeviceNameBuffer[80];
328 WCHAR ArcNameBuffer[80];
329 UNICODE_STRING DeviceName;
330 UNICODE_STRING ArcName;
331 PDRIVE_LAYOUT_INFORMATION LayoutInfo = NULL;
332 NTSTATUS Status;
333 ULONG i;
334 KEVENT Event;
335 PIRP Irp;
336 IO_STATUS_BLOCK StatusBlock;
337 ULONG PartitionNumber;
338
339 swprintf(DeviceNameBuffer,
340 L"\\Device\\Harddisk%lu\\Partition0",
341 DiskNumber);
342 RtlInitUnicodeString(&DeviceName,
343 DeviceNameBuffer);
344
345 swprintf(ArcNameBuffer,
346 L"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
347 RDisk);
348 RtlInitUnicodeString(&ArcName,
349 ArcNameBuffer);
350
351 DPRINT("%wZ ==> %wZ\n", &ArcName, &DeviceName);
352
353 Status = IoAssignArcName(&ArcName, &DeviceName);
354 if (!NT_SUCCESS(Status))
355 {
356 DPRINT1("IoAssignArcName failed, status=%lx\n", Status);
357 return(Status);
358 }
359
360 LayoutInfo = ExAllocatePool(PagedPool, 2 * PAGE_SIZE);
361 if (LayoutInfo == NULL)
362 {
363 return STATUS_NO_MEMORY;
364 }
365 KeInitializeEvent(&Event, NotificationEvent, FALSE);
366 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT,
367 DeviceObject,
368 NULL,
369 0,
370 LayoutInfo,
371 2 * PAGE_SIZE,
372 FALSE,
373 &Event,
374 &StatusBlock);
375 if (Irp == NULL)
376 {
377 ExFreePool(LayoutInfo);
378 return STATUS_INSUFFICIENT_RESOURCES;
379 }
380
381 Status = IoCallDriver(DeviceObject, Irp);
382 if (Status == STATUS_PENDING)
383 {
384 KeWaitForSingleObject(&Event,
385 Executive,
386 KernelMode,
387 FALSE,
388 NULL);
389 Status = StatusBlock.Status;
390 }
391 if (!NT_SUCCESS(Status))
392 {
393 ExFreePool(LayoutInfo);
394 return Status;
395 }
396
397 DPRINT("Number of partitions: %u\n", LayoutInfo->PartitionCount);
398
399 PartitionNumber = 1;
400 for (i = 0; i < LayoutInfo->PartitionCount; i++)
401 {
402 if (!IsContainerPartition(LayoutInfo->PartitionEntry[i].PartitionType) &&
403 LayoutInfo->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED)
404 {
405
406 swprintf(DeviceNameBuffer,
407 L"\\Device\\Harddisk%lu\\Partition%lu",
408 DiskNumber,
409 PartitionNumber);
410 RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
411
412 swprintf(ArcNameBuffer,
413 L"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(%lu)",
414 RDisk,
415 PartitionNumber);
416 RtlInitUnicodeString(&ArcName, ArcNameBuffer);
417
418 DPRINT("%wZ ==> %wZ\n", &ArcName, &DeviceName);
419
420 Status = IoAssignArcName(&ArcName, &DeviceName);
421 if (!NT_SUCCESS(Status))
422 {
423 DPRINT1("IoAssignArcName failed, status=%lx\n", Status);
424 ExFreePool(LayoutInfo);
425 return(Status);
426 }
427 PartitionNumber++;
428 }
429 }
430 ExFreePool(LayoutInfo);
431 return STATUS_SUCCESS;
432 }
433
434 NTSTATUS INIT_FUNCTION
435 IoCreateArcNames(VOID)
436 {
437 PCONFIGURATION_INFORMATION ConfigInfo;
438 WCHAR DeviceNameBuffer[80];
439 WCHAR ArcNameBuffer[80];
440 UNICODE_STRING DeviceName;
441 UNICODE_STRING ArcName;
442 ULONG i, RDiskNumber;
443 NTSTATUS Status;
444 LIST_ENTRY BiosDiskListHead;
445 LIST_ENTRY DiskListHead;
446 PLIST_ENTRY Entry;
447 PDISKENTRY BiosDiskEntry;
448 PDISKENTRY DiskEntry;
449
450 DPRINT("IoCreateArcNames() called\n");
451
452 ConfigInfo = IoGetConfigurationInformation();
453
454 /* create ARC names for floppy drives */
455 DPRINT("Floppy drives: %lu\n", ConfigInfo->FloppyCount);
456 for (i = 0; i < ConfigInfo->FloppyCount; i++)
457 {
458 swprintf(DeviceNameBuffer,
459 L"\\Device\\Floppy%lu",
460 i);
461 RtlInitUnicodeString(&DeviceName,
462 DeviceNameBuffer);
463
464 swprintf(ArcNameBuffer,
465 L"\\ArcName\\multi(0)disk(0)fdisk(%lu)",
466 i);
467 RtlInitUnicodeString(&ArcName,
468 ArcNameBuffer);
469 DPRINT("%wZ ==> %wZ\n",
470 &ArcName,
471 &DeviceName);
472
473 Status = IoAssignArcName(&ArcName,
474 &DeviceName);
475 if (!NT_SUCCESS(Status))
476 return(Status);
477 }
478
479 /* create ARC names for hard disk drives */
480 InitializeListHead(&BiosDiskListHead);
481 InitializeListHead(&DiskListHead);
482 IopEnumerateBiosDisks(&BiosDiskListHead);
483 IopEnumerateDisks(&DiskListHead);
484
485 RDiskNumber = 0;
486 while (!IsListEmpty(&BiosDiskListHead))
487 {
488 Entry = RemoveHeadList(&BiosDiskListHead);
489 BiosDiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
490 Entry = DiskListHead.Flink;
491 while (Entry != &DiskListHead)
492 {
493 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
494 if (DiskEntry->Checksum == BiosDiskEntry->Checksum &&
495 DiskEntry->Signature == BiosDiskEntry->Signature)
496 {
497
498 Status = IopAssignArcNamesToDisk(DiskEntry->DeviceObject, RDiskNumber, DiskEntry->DiskNumber);
499
500 RemoveEntryList(&DiskEntry->ListEntry);
501 ExFreePool(DiskEntry);
502 break;
503 }
504 Entry = Entry->Flink;
505 }
506 RDiskNumber++;
507 ExFreePool(BiosDiskEntry);
508 }
509
510 while (!IsListEmpty(&DiskListHead))
511 {
512 Entry = RemoveHeadList(&DiskListHead);
513 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
514 ExFreePool(DiskEntry);
515 }
516
517 /* create ARC names for cdrom drives */
518 DPRINT("CD-ROM drives: %lu\n", ConfigInfo->CdRomCount);
519 for (i = 0; i < ConfigInfo->CdRomCount; i++)
520 {
521 swprintf(DeviceNameBuffer,
522 L"\\Device\\CdRom%lu",
523 i);
524 RtlInitUnicodeString(&DeviceName,
525 DeviceNameBuffer);
526
527 swprintf(ArcNameBuffer,
528 L"\\ArcName\\multi(0)disk(0)cdrom(%lu)",
529 i);
530 RtlInitUnicodeString(&ArcName,
531 ArcNameBuffer);
532 DPRINT("%wZ ==> %wZ\n",
533 &ArcName,
534 &DeviceName);
535
536 Status = IoAssignArcName(&ArcName,
537 &DeviceName);
538 if (!NT_SUCCESS(Status))
539 return(Status);
540 }
541
542 DPRINT("IoCreateArcNames() done\n");
543
544 return(STATUS_SUCCESS);
545 }
546
547
548 static NTSTATUS INIT_FUNCTION
549 IopCheckCdromDevices(PULONG DeviceNumber)
550 {
551 PCONFIGURATION_INFORMATION ConfigInfo;
552 OBJECT_ATTRIBUTES ObjectAttributes;
553 UNICODE_STRING DeviceName;
554 WCHAR DeviceNameBuffer[MAX_PATH];
555 HANDLE Handle;
556 ULONG i;
557 NTSTATUS Status;
558 IO_STATUS_BLOCK IoStatusBlock;
559 #if 0
560 PFILE_FS_VOLUME_INFORMATION FileFsVolume;
561 USHORT Buffer[FS_VOLUME_BUFFER_SIZE];
562
563 FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer;
564 #endif
565
566 ConfigInfo = IoGetConfigurationInformation();
567 for (i = 0; i < ConfigInfo->CdRomCount; i++)
568 {
569 #if 0
570 swprintf(DeviceNameBuffer,
571 L"\\Device\\CdRom%lu\\",
572 i);
573 RtlInitUnicodeString(&DeviceName,
574 DeviceNameBuffer);
575
576 InitializeObjectAttributes(&ObjectAttributes,
577 &DeviceName,
578 0,
579 NULL,
580 NULL);
581
582 Status = ZwOpenFile(&Handle,
583 FILE_ALL_ACCESS,
584 &ObjectAttributes,
585 &IoStatusBlock,
586 0,
587 0);
588 DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i, Status);
589 if (NT_SUCCESS(Status))
590 {
591 Status = ZwQueryVolumeInformationFile(Handle,
592 &IoStatusBlock,
593 FileFsVolume,
594 FS_VOLUME_BUFFER_SIZE,
595 FileFsVolumeInformation);
596 DPRINT("ZwQueryVolumeInformationFile() Status %lx\n", Status);
597 if (NT_SUCCESS(Status))
598 {
599 DPRINT("VolumeLabel: '%S'\n", FileFsVolume->VolumeLabel);
600 if (_wcsicmp(FileFsVolume->VolumeLabel, L"REACTOS") == 0)
601 {
602 ZwClose(Handle);
603 *DeviceNumber = i;
604 return(STATUS_SUCCESS);
605 }
606 }
607 ZwClose(Handle);
608 }
609 #endif
610
611 /*
612 * Check for 'reactos/ntoskrnl.exe' first...
613 */
614
615 swprintf(DeviceNameBuffer,
616 L"\\Device\\CdRom%lu\\reactos\\ntoskrnl.exe",
617 i);
618 RtlInitUnicodeString(&DeviceName,
619 DeviceNameBuffer);
620
621 InitializeObjectAttributes(&ObjectAttributes,
622 &DeviceName,
623 0,
624 NULL,
625 NULL);
626
627 Status = ZwOpenFile(&Handle,
628 FILE_ALL_ACCESS,
629 &ObjectAttributes,
630 &IoStatusBlock,
631 0,
632 0);
633 DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i, Status);
634 if (NT_SUCCESS(Status))
635 {
636 DPRINT("Found ntoskrnl.exe on Cdrom%lu\n", i);
637 ZwClose(Handle);
638 *DeviceNumber = i;
639 return(STATUS_SUCCESS);
640 }
641
642 /*
643 * ...and for 'reactos/system32/ntoskrnl.exe' also.
644 */
645
646 swprintf(DeviceNameBuffer,
647 L"\\Device\\CdRom%lu\\reactos\\system32\\ntoskrnl.exe",
648 i);
649 RtlInitUnicodeString(&DeviceName,
650 DeviceNameBuffer);
651
652 InitializeObjectAttributes(&ObjectAttributes,
653 &DeviceName,
654 0,
655 NULL,
656 NULL);
657
658 Status = ZwOpenFile(&Handle,
659 FILE_ALL_ACCESS,
660 &ObjectAttributes,
661 &IoStatusBlock,
662 0,
663 0);
664 DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i, Status);
665 if (NT_SUCCESS(Status))
666 {
667 DPRINT("Found ntoskrnl.exe on Cdrom%lu\n", i);
668 ZwClose(Handle);
669 *DeviceNumber = i;
670 return(STATUS_SUCCESS);
671 }
672 }
673
674 DPRINT("Could not find ntoskrnl.exe\n");
675 *DeviceNumber = (ULONG)-1;
676
677 return(STATUS_UNSUCCESSFUL);
678 }
679
680
681 NTSTATUS INIT_FUNCTION
682 IoCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
683 {
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;
690 PCHAR ParamBuffer;
691 PWCHAR ArcNameBuffer;
692 PCHAR p;
693 NTSTATUS Status;
694 ULONG Length;
695 HANDLE Handle;
696
697 RtlCreateUnicodeStringFromAsciiz(&BootPath, LoaderBlock->NtBootPathName);
698
699 /* Remove the trailing backslash */
700 BootPath.Length -= sizeof(WCHAR);
701 BootPath.MaximumLength -= sizeof(WCHAR);
702
703 /* Only ARC Name left - Build full ARC Name */
704 ParamBuffer = LoaderBlock->ArcBootDeviceName;
705
706 p = strstr(ParamBuffer, "cdrom");
707 if (p != NULL)
708 {
709 ULONG DeviceNumber;
710
711 DPRINT("Booting from CD-ROM!\n");
712 Status = IopCheckCdromDevices(&DeviceNumber);
713 if (!NT_SUCCESS(Status))
714 {
715 CPRINT("Failed to find setup disk!\n");
716 return(Status);
717 }
718
719 sprintf(p, "cdrom(%lu)", DeviceNumber);
720
721 DPRINT("New ARC name: %s\n", ParamBuffer);
722
723 /* Adjust original command line */
724 p = strstr(LoaderBlock->ArcBootDeviceName, "cdrom");
725 if (p != NULL);
726 {
727 char temp[256];
728 char *q;
729
730 q = strchr(p, ')');
731 if (q != NULL)
732 {
733
734 q++;
735 strcpy(temp, q);
736 sprintf(p, "cdrom(%lu)", DeviceNumber);
737 strcat(p, temp);
738 }
739 }
740 }
741
742 /* Only arc name left - build full arc name */
743 ArcNameBuffer = ExAllocatePool(PagedPool, 256 * sizeof(WCHAR));
744 swprintf(ArcNameBuffer,
745 L"\\ArcName\\%S", ParamBuffer);
746 RtlInitUnicodeString(&ArcName, ArcNameBuffer);
747
748 /* allocate device name string */
749 DeviceName.Length = 0;
750 DeviceName.MaximumLength = 256 * sizeof(WCHAR);
751 DeviceName.Buffer = ExAllocatePool(PagedPool, 256 * sizeof(WCHAR));
752
753 InitializeObjectAttributes(&ObjectAttributes,
754 &ArcName,
755 OBJ_OPENLINK,
756 NULL,
757 NULL);
758
759 Status = ZwOpenSymbolicLinkObject(&Handle,
760 SYMBOLIC_LINK_ALL_ACCESS,
761 &ObjectAttributes);
762 if (!NT_SUCCESS(Status))
763 {
764 RtlFreeUnicodeString(&BootPath);
765 ExFreePool(DeviceName.Buffer);
766 CPRINT("ZwOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
767 &ArcName,
768 Status);
769 ExFreePool(ArcName.Buffer);
770
771 return(Status);
772 }
773 ExFreePool(ArcName.Buffer);
774
775 Status = ZwQuerySymbolicLinkObject(Handle,
776 &DeviceName,
777 &Length);
778 ZwClose (Handle);
779 if (!NT_SUCCESS(Status))
780 {
781 RtlFreeUnicodeString(&BootPath);
782 ExFreePool(DeviceName.Buffer);
783 CPRINT("ZwQuerySymbolicObject() failed (Status %x)\n",
784 Status);
785
786 return(Status);
787 }
788
789 RtlAppendUnicodeStringToString(&DeviceName,
790 &BootPath);
791
792 RtlFreeUnicodeString(&BootPath);
793
794 /* create the '\SystemRoot' link */
795 Status = IoCreateSymbolicLink(&LinkName,
796 &DeviceName);
797 ExFreePool(DeviceName.Buffer);
798 if (!NT_SUCCESS(Status))
799 {
800 CPRINT("IoCreateSymbolicLink() failed (Status %x)\n",
801 Status);
802
803 return(Status);
804 }
805
806 /* Check whether '\SystemRoot'(LinkName) can be opened */
807 InitializeObjectAttributes(&ObjectAttributes,
808 &LinkName,
809 0,
810 NULL,
811 NULL);
812
813 Status = ZwOpenFile(&Handle,
814 FILE_ALL_ACCESS,
815 &ObjectAttributes,
816 &IoStatusBlock,
817 0,
818 0);
819 if (!NT_SUCCESS(Status))
820 {
821 CPRINT("ZwOpenFile() failed to open '\\SystemRoot' (Status %x)\n",
822 Status);
823 return(Status);
824 }
825
826 ZwClose(Handle);
827
828 return(STATUS_SUCCESS);
829 }
830
831 /* EOF */