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