- Fixup some more structure and prototype details to make more sense.
[reactos.git] / reactos / drivers / storage / class / ramdisk / ramdisk.c
1 /*
2 * PROJECT: Ramdisk Class Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/storage/class/ramdisk/ramdisk.c
5 * PURPOSE: Main Driver Routines
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <initguid.h>
12 #include <ntddk.h>
13 #include <ntdddisk.h>
14 #include <scsi.h>
15 #include <ntddscsi.h>
16 #include <mountdev.h>
17 #include <mountmgr.h>
18 #include <helper.h>
19 #include <ketypes.h>
20 #include <iotypes.h>
21 #include <rtlfuncs.h>
22 #include <arc/arc.h>
23 #include <reactos/drivers/ntddrdsk.h>
24 #include <stdio.h>
25 #define NDEBUG
26 #include <debug.h>
27
28 /* GLOBALS ********************************************************************/
29
30 typedef enum _RAMDISK_DEVICE_TYPE
31 {
32 RamdiskBus,
33 RamdiskDrive
34 } RAMDISK_DEVICE_TYPE;
35
36 typedef enum _RAMDISK_DEVICE_STATE
37 {
38 RamdiskStateUninitialized,
39 RamdiskStateStarted,
40 RamdiskStatePaused,
41 RamdiskStateStopped,
42 RamdiskStateRemoved,
43 RamdiskStateBusRemoved,
44 RamdiskStateEnumerated,
45 } RAMDISK_DEVICE_STATE;
46
47 DEFINE_GUID(RamdiskBusInterface,
48 0x5DC52DF0,
49 0x2F8A,
50 0x410F,
51 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
52
53 //
54 // GCC does not seem to support anonymous structures
55 //
56 #define RAMDISK_EXTENSION \
57 RAMDISK_DEVICE_TYPE Type; \
58 RAMDISK_DEVICE_STATE State; \
59 PDEVICE_OBJECT DeviceObject; \
60 PDEVICE_OBJECT PhysicalDeviceObject; \
61 PDEVICE_OBJECT AttachedDevice; \
62 IO_REMOVE_LOCK RemoveLock; \
63 UNICODE_STRING DriveDeviceName; \
64 UNICODE_STRING BusDeviceName; \
65 FAST_MUTEX DiskListLock; \
66 LIST_ENTRY DiskList;
67
68 typedef struct _RAMDISK_BUS_EXTENSION
69 {
70 RAMDISK_EXTENSION;
71 } RAMDISK_BUS_EXTENSION, *PRAMDISK_BUS_EXTENSION;
72
73 typedef struct _RAMDISK_DRIVE_EXTENSION
74 {
75 RAMDISK_EXTENSION;
76 GUID DiskGuid;
77 UNICODE_STRING GuidString;
78 UNICODE_STRING SymbolicLinkName;
79 ULONG DiskType;
80 RAMDISK_CREATE_OPTIONS DiskOptions;
81 LONGLONG DiskLength;
82 LONG DiskOffset;
83 WCHAR DriveLetter;
84 } RAMDISK_DRIVE_EXTENSION, *PRAMDISK_DRIVE_EXTENSION;
85
86 ULONG MaximumViewLength;
87 ULONG MaximumPerDiskViewLength;
88 ULONG ReportDetectedDevice;
89 ULONG MarkRamdisksAsRemovable;
90 ULONG MinimumViewCount;
91 ULONG DefaultViewCount;
92 ULONG MaximumViewCount;
93 ULONG MinimumViewLength;
94 ULONG DefaultViewLength;
95 UNICODE_STRING DriverRegistryPath;
96 BOOLEAN ExportBootDiskAsCd;
97 BOOLEAN IsWinPEBoot;
98 PDEVICE_OBJECT RamdiskBusFdo;
99
100 /* FUNCTIONS ******************************************************************/
101
102 VOID
103 NTAPI
104 QueryParameters(IN PUNICODE_STRING RegistryPath)
105 {
106 ULONG MinView, DefView, MinViewLength, DefViewLength, MaxViewLength;
107 RTL_QUERY_REGISTRY_TABLE QueryTable[10];
108
109 //
110 // Set defaults
111 //
112 MaximumViewLength = 0x10000000u;
113 MaximumPerDiskViewLength = 0x10000000u;
114 ReportDetectedDevice = 0;
115 MarkRamdisksAsRemovable = 0;
116 MinimumViewCount = 2;
117 DefaultViewCount = 16;
118 MaximumViewCount = 64;
119 MinimumViewLength = 0x10000u;
120 DefaultViewLength = 0x100000u;
121
122 //
123 // Setup the query table and query the registry
124 //
125 RtlZeroMemory(QueryTable, sizeof(QueryTable));
126 QueryTable[0].Flags = 1;
127 QueryTable[0].Name = L"Parameters";
128 QueryTable[1].Flags = 32;
129 QueryTable[1].Name = L"ReportDetectedDevice";
130 QueryTable[1].EntryContext = &ReportDetectedDevice;
131 QueryTable[2].Flags = 32;
132 QueryTable[2].Name = L"MarkRamdisksAsRemovable";
133 QueryTable[2].EntryContext = &MarkRamdisksAsRemovable;
134 QueryTable[3].Flags = 32;
135 QueryTable[3].Name = L"MinimumViewCount";
136 QueryTable[3].EntryContext = &MinimumViewCount;
137 QueryTable[4].Flags = 32;
138 QueryTable[4].Name = L"DefaultViewCount";
139 QueryTable[4].EntryContext = &DefaultViewCount;
140 QueryTable[5].Flags = 32;
141 QueryTable[5].Name = L"MaximumViewCount";
142 QueryTable[5].EntryContext = &MaximumViewCount;
143 QueryTable[6].Flags = 32;
144 QueryTable[6].Name = L"MinimumViewLength";
145 QueryTable[6].EntryContext = &MinimumViewLength;
146 QueryTable[7].Flags = 32;
147 QueryTable[7].Name = L"DefaultViewLength";
148 QueryTable[7].EntryContext = &DefaultViewLength;
149 QueryTable[8].Flags = 32;
150 QueryTable[8].Name = L"MaximumViewLength";
151 QueryTable[8].EntryContext = &MaximumViewLength;
152 QueryTable[9].Flags = 32;
153 QueryTable[9].Name = L"MaximumPerDiskViewLength";
154 QueryTable[9].EntryContext = &MaximumPerDiskViewLength;
155 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL,
156 RegistryPath->Buffer,
157 QueryTable,
158 NULL,
159 NULL);
160
161 //
162 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
163 //
164 MinView = MinimumViewCount;
165 if (MinimumViewCount >= 2)
166 {
167 if (MinimumViewCount > 256) MinView = 256;
168 }
169 else
170 {
171 MinView = 2;
172 }
173 MinimumViewCount = MinView;
174
175 //
176 // Parse default view count, cannot be bigger than 256 or smaller than minimum
177 //
178 DefView = DefaultViewCount;
179 if (DefaultViewCount >= MinView)
180 {
181 if (DefaultViewCount > 256) DefView = 256;
182 }
183 else
184 {
185 DefView = MinView;
186 }
187 DefaultViewCount = DefView;
188
189 //
190 // Parse maximum view count, cannot be bigger than 256 or smaller than default
191 //
192 if (MaximumViewCount >= DefView)
193 {
194 if (MaximumViewCount > 256) MaximumViewCount = 256;
195 }
196 else
197 {
198 MaximumViewCount = DefView;
199 }
200
201 //
202 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
203 //
204 MinViewLength = MinimumViewLength;
205 if (MinimumViewLength >= 0x10000)
206 {
207 if (MinimumViewLength > 0x40000000) MinViewLength = 0x40000000u;
208 }
209 else
210 {
211 MinViewLength = 0x10000u;
212 }
213 MinimumViewLength = MinViewLength;
214
215 //
216 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
217 //
218 DefViewLength = DefaultViewLength;
219 if (DefaultViewLength >= MinViewLength)
220 {
221 if (DefaultViewLength > 0x40000000) DefViewLength = 0x40000000u;
222 }
223 else
224 {
225 DefViewLength = MinViewLength;
226 }
227 DefaultViewLength = DefViewLength;
228
229 //
230 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
231 //
232 MaxViewLength = MaximumViewLength;
233 if (MaximumViewLength >= DefViewLength)
234 {
235 if (MaximumViewLength > 0x40000000) MaxViewLength = 0x40000000u;
236 }
237 else
238 {
239 MaxViewLength = DefViewLength;
240 }
241 MaximumViewLength = MaxViewLength;
242
243 //
244 // Parse maximum view length per disk, cannot be smaller than 16MB
245 //
246 if (MaximumPerDiskViewLength >= 0x1000000)
247 {
248 if (MaxViewLength > 0xFFFFFFFF) MaximumPerDiskViewLength = -1;
249 }
250 else
251 {
252 MaximumPerDiskViewLength = 0x1000000u;
253 }
254 }
255
256 NTSTATUS
257 NTAPI
258 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension,
259 IN PRAMDISK_CREATE_INPUT Input,
260 IN BOOLEAN ValidateOnly,
261 OUT PRAMDISK_DRIVE_EXTENSION *NewDriveExtension)
262 {
263 ULONG BasePage, ViewCount, DiskType, Length;
264 NTSTATUS Status;
265 PDEVICE_OBJECT DeviceObject;
266 PRAMDISK_DRIVE_EXTENSION DriveExtension;
267 PVOID Buffer;
268 WCHAR LocalBuffer[16];
269 UNICODE_STRING SymbolicLinkName, DriveString, GuidString, DeviceName;
270
271 //
272 // Check if we're a CDROM-type RAM disk
273 //
274 DiskType = Input->DiskType;
275 if (DiskType > FILE_DEVICE_CD_ROM)
276 {
277 //
278 // Check if we're an ISO
279 //
280 if (DiskType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
281 {
282 //
283 // NTLDR mounted us somewhere
284 //
285 BasePage = Input->BasePage;
286 if (!BasePage) return STATUS_INVALID_PARAMETER;
287
288 //
289 // Sanitize disk options
290 //
291 Input->Options.Fixed = TRUE;
292 Input->Options.Readonly = Input->Options.ExportAsCd |
293 Input->Options.Readonly;
294 Input->Options.Hidden = FALSE;
295 Input->Options.NoDosDevice = FALSE;
296 Input->Options.NoDriveLetter = IsWinPEBoot ? TRUE : FALSE;
297 }
298 else
299 {
300 //
301 // The only other possibility is a controller
302 //
303 if (DiskType != FILE_DEVICE_CONTROLLER)
304 return STATUS_INVALID_PARAMETER;
305
306 //
307 // Read the view count instead
308 //
309 ViewCount = Input->ViewCount;
310
311 //
312 // Sanitize disk options
313 //
314 Input->Options.Hidden = FALSE;
315 Input->Options.NoDosDevice = FALSE;
316 Input->Options.Readonly = FALSE;
317 Input->Options.NoDriveLetter = TRUE;
318 Input->Options.Fixed = TRUE;
319 }
320
321 //
322 // Are we just validating and returning to the user?
323 //
324 if (ValidateOnly) return STATUS_SUCCESS;
325
326 //
327 // Build the GUID string
328 //
329 Status = RtlStringFromGUID(&Input->DiskGuid, &GuidString);
330 if (!(NT_SUCCESS(Status)) || !(GuidString.Buffer))
331 {
332 //
333 // Fail
334 //
335 Status = STATUS_INSUFFICIENT_RESOURCES;
336 goto FailCreate;
337 }
338
339 //
340 // Allocate our device name
341 //
342 Length = GuidString.Length + 32;
343 Buffer = ExAllocatePoolWithTag(NonPagedPool,
344 Length,
345 TAG('R', 'a', 'm', 'd'));
346 if (!Buffer)
347 {
348 //
349 // Fail
350 //
351 Status = STATUS_INSUFFICIENT_RESOURCES;
352 goto FailCreate;
353 }
354
355 //
356 // Build the device name string
357 //
358 DeviceName.Buffer = Buffer;
359 DeviceName.Length = Length - 2;
360 DeviceName.MaximumLength = Length;
361 wcsncpy(Buffer, L"\\Device\\Ramdisk", Length / sizeof(WCHAR));
362 wcsncat(Buffer, GuidString.Buffer, Length / sizeof(WCHAR));
363 DPRINT1("Creating device: %wZ\n", &DeviceName);
364
365 //
366 // Create the drive device
367 //
368 Status = IoCreateDevice(DeviceExtension->DeviceObject->DriverObject,
369 sizeof(RAMDISK_DRIVE_EXTENSION),
370 &DeviceName,
371 FILE_DEVICE_DISK_FILE_SYSTEM, // FIXME: DISK
372 FILE_READ_ONLY_DEVICE, // FIXME: Not always
373 0,
374 &DeviceObject);
375 if (!NT_SUCCESS(Status)) goto FailCreate;
376
377 //
378 // Grab the drive extension
379 //
380 DriveExtension = DeviceObject->DeviceExtension;
381
382 //
383 // Check if we need a DOS device
384 //
385 if (!Input->Options.NoDosDevice)
386 {
387 //
388 // Build the symbolic link name
389 //
390 SymbolicLinkName.MaximumLength = GuidString.Length + 36;
391 SymbolicLinkName.Length = GuidString.Length + 34;
392 Buffer = ExAllocatePoolWithTag(NonPagedPool,
393 SymbolicLinkName.MaximumLength,
394 TAG('R', 'a', 'm', 'd'));
395 SymbolicLinkName.Buffer = Buffer;
396 if (Buffer)
397 {
398 //
399 // Create it
400 //
401 wcsncpy(Buffer,
402 L"\\GLOBAL??\\Ramdisk",
403 SymbolicLinkName.MaximumLength / sizeof(WCHAR));
404 wcsncat(Buffer,
405 GuidString.Buffer,
406 SymbolicLinkName.MaximumLength / sizeof(WCHAR));
407 DPRINT1("Creating symbolic link: %wZ to %wZ \n",
408 &SymbolicLinkName, &DeviceName);
409 Status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
410 if (!NT_SUCCESS(Status))
411 {
412 //
413 // Nevermind...
414 //
415 Input->Options.NoDosDevice = TRUE;
416 ExFreePool(Buffer);
417 SymbolicLinkName.Buffer = NULL;
418 }
419 }
420 else
421 {
422 //
423 // No DOS device
424 //
425 Input->Options.NoDosDevice = TRUE;
426 }
427
428 //
429 // It this an ISO boot ramdisk?
430 //
431 if (Input->DiskType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
432 {
433 //
434 // Does it need a drive letter?
435 //
436 if (!Input->Options.NoDriveLetter)
437 {
438 //
439 // Build it and take over the existing symbolic link
440 //
441 _snwprintf(LocalBuffer,
442 30,
443 L"\\DosDevices\\%wc:",
444 Input->DriveLetter);
445 RtlInitUnicodeString(&DriveString, LocalBuffer);
446 DPRINT1("Creating symbolic link: %wZ to %wZ\n",
447 &DriveString, &DeviceName);
448 IoDeleteSymbolicLink(&DriveString);
449 IoCreateSymbolicLink(&DriveString, &DeviceName);
450
451 //
452 // Save the drive letter
453 //
454 DriveExtension->DriveLetter = Input->DriveLetter;
455 }
456 }
457
458 }
459
460 //
461 // Setup the device object flags
462 //
463 DeviceObject->Flags |= (DO_XIP | DO_POWER_PAGABLE | DO_DIRECT_IO);
464 DeviceObject->AlignmentRequirement = 1;
465
466 //
467 // Build the drive FDO
468 //
469 *NewDriveExtension = DriveExtension;
470 DriveExtension->Type = RamdiskDrive;
471 ExInitializeFastMutex(&DriveExtension->DiskListLock);
472 IoInitializeRemoveLock(&DriveExtension->RemoveLock,
473 TAG('R', 'a', 'm', 'd'),
474 0,
475 1);
476 DriveExtension->DriveDeviceName = DeviceName;
477 DriveExtension->SymbolicLinkName = SymbolicLinkName;
478 DriveExtension->GuidString = GuidString;
479 DriveExtension->DiskGuid = Input->DiskGuid;
480 DriveExtension->PhysicalDeviceObject = DeviceObject;
481 DriveExtension->DeviceObject = RamdiskBusFdo;
482 DriveExtension->AttachedDevice = RamdiskBusFdo;
483 DriveExtension->DiskType = Input->DiskType;
484 DriveExtension->DiskOptions = Input->Options;
485 DriveExtension->DiskLength = Input->DiskLength;
486 DriveExtension->DiskOffset = Input->DiskOffset;
487
488 //
489 // Make sure we don't free it later
490 //
491 DeviceName.Buffer = NULL;
492 SymbolicLinkName.Buffer = NULL;
493 GuidString.Buffer = NULL;
494 }
495
496 FailCreate:
497 UNIMPLEMENTED;
498 while (TRUE);
499 return STATUS_SUCCESS;
500 }
501
502 NTSTATUS
503 NTAPI
504 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject,
505 IN PIRP Irp,
506 IN BOOLEAN ValidateOnly)
507 {
508 PRAMDISK_CREATE_INPUT Input;
509 ULONG Length;
510 PRAMDISK_BUS_EXTENSION DeviceExtension;
511 PRAMDISK_DRIVE_EXTENSION DriveExtension;
512 ULONG DiskType;
513 PWCHAR FileNameStart, FileNameEnd;
514 NTSTATUS Status;
515 PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
516
517 //
518 // Get the device extension and our input data
519 //
520 DeviceExtension = DeviceObject->DeviceExtension;
521 Length = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
522 Input = (PRAMDISK_CREATE_INPUT)Irp->AssociatedIrp.SystemBuffer;
523
524 //
525 // Validate input parameters
526 //
527 if ((Length < sizeof(RAMDISK_CREATE_INPUT)) ||
528 (Input->Version != sizeof(RAMDISK_CREATE_INPUT)))
529 {
530 //
531 // Invalid input
532 //
533 return STATUS_INVALID_PARAMETER;
534 }
535
536 //
537 // Validate the disk type
538 //
539 DiskType = Input->DiskType;
540 if (DiskType == FILE_DEVICE_CONTROLLER) return STATUS_INVALID_PARAMETER;
541
542 //
543 // Look at the disk type
544 //
545 if (DiskType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
546 {
547 //
548 // We only allow this as an early-init boot
549 //
550 if (!KeLoaderBlock) return STATUS_INVALID_PARAMETER;
551
552 //
553 // Save command-line flags
554 //
555 if (ExportBootDiskAsCd) Input->Options.ExportAsCd = TRUE;
556 if (IsWinPEBoot) Input->Options.NoDriveLetter = TRUE;
557 }
558
559 //
560 // Validate the disk type
561 //
562 if ((Input->Options.ExportAsCd) &&
563 (DiskType != FILE_DEVICE_CD_ROM_FILE_SYSTEM))
564 {
565 //
566 // If the type isn't CDFS, it has to at least be raw CD
567 //
568 if (DiskType != FILE_DEVICE_CD_ROM) return STATUS_INVALID_PARAMETER;
569 }
570
571 //
572 // Check if this is an actual file
573 //
574 if (DiskType <= FILE_DEVICE_CD_ROM)
575 {
576 //
577 // Validate the file name
578 //
579 FileNameStart = (PWCHAR)((ULONG_PTR)Input + Length);
580 FileNameEnd = Input->FileName + 1;
581 while ((FileNameEnd < FileNameStart) && *(FileNameEnd)) FileNameEnd++;
582 if (FileNameEnd == FileNameStart) return STATUS_INVALID_PARAMETER;
583 }
584
585 //
586 // Create the actual device
587 //
588 Status = RamdiskCreateDiskDevice(DeviceExtension,
589 Input,
590 ValidateOnly,
591 &DriveExtension);
592 if (NT_SUCCESS(Status))
593 {
594 //
595 // Invalidate and set success
596 //
597 IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, 0);
598 Irp->IoStatus.Information = STATUS_SUCCESS;
599 }
600
601 //
602 // We're done
603 //
604 return Status;
605 }
606
607 VOID
608 NTAPI
609 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject,
610 IN PVOID Context)
611 {
612 PRAMDISK_BUS_EXTENSION DeviceExtension;
613 NTSTATUS Status;
614 PIO_STACK_LOCATION IoStackLocation;
615 PIRP Irp = Context;
616
617 //
618 // Get the stack location
619 //
620 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
621
622 //
623 // Free the work item
624 //
625 IoFreeWorkItem(Irp->Tail.Overlay.DriverContext[0]);
626
627 //
628 // Grab the device extension and lock it
629 //
630 DeviceExtension = DeviceObject->DeviceExtension;
631 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
632 if (NT_SUCCESS(Status))
633 {
634 //
635 // Discriminate by major code
636 //
637 switch (IoStackLocation->MajorFunction)
638 {
639 //
640 // Device control
641 //
642 case IRP_MJ_DEVICE_CONTROL:
643
644 //
645 // Let's take a look at the IOCTL
646 //
647 switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
648 {
649 //
650 // Ramdisk create request
651 //
652 case FSCTL_CREATE_RAM_DISK:
653
654 //
655 // This time we'll do it for real
656 //
657 Status = RamdiskCreateRamdisk(DeviceObject, Irp, FALSE);
658 break;
659
660 case IOCTL_DISK_SET_PARTITION_INFO:
661
662 DPRINT1("Set partition info request\n");
663 UNIMPLEMENTED;
664 while (TRUE);
665 break;
666
667 case IOCTL_DISK_GET_DRIVE_LAYOUT:
668
669 DPRINT1("Get drive layout request\n");
670 UNIMPLEMENTED;
671 while (TRUE);
672 break;
673
674 case IOCTL_DISK_GET_PARTITION_INFO:
675
676 DPRINT1("Get partitinon info request\n");
677 UNIMPLEMENTED;
678 while (TRUE);
679 break;
680
681 default:
682
683 DPRINT1("Invalid request\n");
684 UNIMPLEMENTED;
685 while (TRUE);
686 break;
687 }
688
689 //
690 // We're here
691 //
692 break;
693
694 //
695 // Read or write request
696 //
697 case IRP_MJ_READ:
698 case IRP_MJ_WRITE:
699
700 DPRINT1("Read/Write request\n");
701 UNIMPLEMENTED;
702 while (TRUE);
703 break;
704
705 //
706 // Internal request (SCSI?)
707 //
708 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
709
710 DPRINT1("SCSI request\n");
711 UNIMPLEMENTED;
712 while (TRUE);
713 break;
714
715 //
716 // Flush request
717 //
718 case IRP_MJ_FLUSH_BUFFERS:
719
720 DPRINT1("Flush request\n");
721 UNIMPLEMENTED;
722 while (TRUE);
723 break;
724
725 //
726 // Anything else
727 //
728 default:
729
730 DPRINT1("Invalid request: %lx\n", IoStackLocation->MajorFunction);
731 UNIMPLEMENTED;
732 while (TRUE);
733 break;
734 }
735
736 //
737 // Complete the I/O
738 //
739 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
740 Irp->IoStatus.Status = Status;
741 Irp->IoStatus.Information = 0;
742 return IoCompleteRequest(Irp, IO_DISK_INCREMENT);
743 }
744
745 //
746 // Fail the I/O
747 //
748 Irp->IoStatus.Status = Status;
749 Irp->IoStatus.Information = 0;
750 return IoCompleteRequest(Irp, IO_NO_INCREMENT);
751 }
752
753 NTSTATUS
754 NTAPI
755 SendIrpToThread(IN PDEVICE_OBJECT DeviceObject,
756 IN PIRP Irp)
757 {
758 PIO_WORKITEM WorkItem;
759
760 //
761 // Mark the IRP pending
762 //
763 IoMarkIrpPending(Irp);
764
765 //
766 // Allocate a work item
767 //
768 WorkItem = IoAllocateWorkItem(DeviceObject);
769 if (WorkItem)
770 {
771 //
772 // Queue it up
773 //
774 Irp->Tail.Overlay.DriverContext[0] = WorkItem;
775 IoQueueWorkItem(WorkItem, RamdiskWorkerThread, DelayedWorkQueue, Irp);
776 return STATUS_PENDING;
777 }
778 else
779 {
780 //
781 // Fail
782 //
783 return STATUS_INSUFFICIENT_RESOURCES;
784 }
785 }
786
787 NTSTATUS
788 NTAPI
789 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject,
790 IN PIRP Irp)
791 {
792 //
793 // Complete the IRP
794 //
795 Irp->IoStatus.Information = 1;
796 Irp->IoStatus.Status = STATUS_SUCCESS;
797 IoCompleteRequest(Irp, IO_NO_INCREMENT);
798 return STATUS_SUCCESS;
799 }
800
801 NTSTATUS
802 NTAPI
803 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject,
804 IN PIRP Irp)
805 {
806 UNIMPLEMENTED;
807 while (TRUE);
808 return STATUS_SUCCESS;
809 }
810
811 NTSTATUS
812 NTAPI
813 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
814 IN PIRP Irp)
815 {
816 NTSTATUS Status;
817 PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
818 PRAMDISK_BUS_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
819 ULONG Information = 0;
820
821 //
822 // Grab the remove lock
823 //
824 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
825 if (!NT_SUCCESS(Status))
826 {
827 //
828 // Fail the IRP
829 //
830 Irp->IoStatus.Information = 0;
831 Irp->IoStatus.Status = Status;
832 IoCompleteRequest(Irp, IO_NO_INCREMENT);
833 return Status;
834 }
835
836 //
837 // Check if this is an bus device or the drive
838 //
839 if (DeviceExtension->Type == RamdiskBus)
840 {
841 //
842 // Check what the request is
843 //
844 switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
845 {
846 //
847 // Request to create a ramdisk
848 //
849 case FSCTL_CREATE_RAM_DISK:
850
851 //
852 // Do it
853 //
854 Status = RamdiskCreateRamdisk(DeviceObject, Irp, TRUE);
855 if (!NT_SUCCESS(Status)) goto CompleteRequest;
856 break;
857
858 default:
859
860 //
861 // We don't handle anything else yet
862 //
863 ASSERT(FALSE);
864 while (TRUE);
865 }
866 }
867 else
868 {
869 //
870 // Drive code not yet done
871 //
872 ASSERT(FALSE);
873 }
874
875 //
876 // Queue the request to our worker thread
877 //
878 Status = SendIrpToThread(DeviceObject, Irp);
879
880 CompleteRequest:
881 //
882 // Release the lock
883 //
884 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
885 if (Status != STATUS_PENDING)
886 {
887 //
888 // Complete the request
889 //
890 Irp->IoStatus.Status = Status;
891 Irp->IoStatus.Information = Information;
892 IoCompleteRequest(Irp, IO_NO_INCREMENT);
893 }
894
895 //
896 // Return status
897 //
898 return Status;
899 }
900
901 NTSTATUS
902 NTAPI
903 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type,
904 IN PDEVICE_OBJECT DeviceObject,
905 IN PIRP Irp)
906 {
907 PRAMDISK_BUS_EXTENSION DeviceExtension;
908 PRAMDISK_DRIVE_EXTENSION DriveExtension;
909 PDEVICE_RELATIONS DeviceRelations, OurDeviceRelations;
910 ULONG Count, DiskCount, FinalCount;
911 PLIST_ENTRY ListHead, NextEntry;
912 PDEVICE_OBJECT* DriveDeviceObject;
913 RAMDISK_DEVICE_STATE State;
914
915 //
916 // Get the device extension and check if this is a drive
917 //
918 DeviceExtension = DeviceObject->DeviceExtension;
919 if (DeviceExtension->Type == RamdiskDrive)
920 {
921 //
922 // FIXME: TODO
923 //
924 UNIMPLEMENTED;
925 while (TRUE);
926 }
927
928 //
929 // Anything but bus relations, we don't handle
930 //
931 if (Type) goto PassToNext;
932
933 //
934 // Acquire the disk list lock
935 //
936 KeEnterCriticalRegion();
937 ExAcquireFastMutex(&DeviceExtension->DiskListLock);
938
939 //
940 // Did a device already fill relations?
941 //
942 DeviceRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
943 if (DeviceRelations)
944 {
945 //
946 // Use the data
947 //
948 Count = DeviceRelations->Count;
949 }
950 else
951 {
952 //
953 // We're the first
954 //
955 Count = 0;
956 }
957
958 //
959 // Now loop our drives
960 //
961 DiskCount = 0;
962 ListHead = &DeviceExtension->DiskList;
963 NextEntry = ListHead->Flink;
964 while (NextEntry != ListHead)
965 {
966 //
967 // As long as it wasn't removed, count it in
968 //
969 DriveExtension = CONTAINING_RECORD(NextEntry,
970 RAMDISK_DRIVE_EXTENSION,
971 DiskList);
972 if (DriveExtension->State < RamdiskStateBusRemoved) DiskCount++;
973
974 //
975 // Move to the next one
976 //
977 NextEntry = NextEntry->Flink;
978 }
979
980 //
981 // Now we know our final count
982 //
983 FinalCount = Count + DiskCount;
984
985 //
986 // Allocate the structure
987 //
988 OurDeviceRelations = ExAllocatePoolWithTag(PagedPool,
989 FIELD_OFFSET(DEVICE_RELATIONS,
990 Objects) +
991 FinalCount *
992 sizeof(PDEVICE_OBJECT),
993 TAG('R', 'a', 'm', 'd'));
994 if (!OurDeviceRelations)
995 {
996 //
997 // Fail
998 //
999 ExReleaseFastMutex(&DeviceExtension->DiskListLock);
1000 KeLeaveCriticalRegion();
1001 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1002 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1003 return STATUS_INSUFFICIENT_RESOURCES;
1004 }
1005
1006 //
1007 // Check if we already had some relations
1008 //
1009 if (Count)
1010 {
1011 //
1012 // Copy them in
1013 //
1014 RtlCopyMemory(OurDeviceRelations->Objects,
1015 DeviceRelations->Objects,
1016 Count * sizeof(PDEVICE_OBJECT));
1017 }
1018
1019 //
1020 // Save the count
1021 //
1022 OurDeviceRelations->Count = FinalCount;
1023
1024 //
1025 // Now loop our drives again
1026 //
1027 ListHead = &DeviceExtension->DiskList;
1028 NextEntry = ListHead->Flink;
1029 while (NextEntry != ListHead)
1030 {
1031 //
1032 // Go to the end of the list
1033 //
1034 DriveDeviceObject = &OurDeviceRelations->Objects[Count];
1035
1036 //
1037 // Get the drive state
1038 //
1039 DriveExtension = CONTAINING_RECORD(NextEntry,
1040 RAMDISK_DRIVE_EXTENSION,
1041 DiskList);
1042 State = DriveExtension->State;
1043
1044 //
1045 // If it was removed or enumerated, we don't touch the device object
1046 //
1047 if (State >= RamdiskStateBusRemoved)
1048 {
1049 //
1050 // If it was removed, we still have to keep track of this though
1051 //
1052 if (State == RamdiskStateBusRemoved)
1053 {
1054 //
1055 // Mark it as enumerated now, but don't actually reference it
1056 //
1057 DriveExtension->State = RamdiskStateEnumerated;
1058 }
1059 }
1060 else
1061 {
1062 //
1063 // First time it's enumerated, reference the device object
1064 //
1065 ObReferenceObject(DriveExtension->DeviceObject);
1066
1067 //
1068 // Save the object pointer, and move on
1069 //
1070 *DriveDeviceObject++ = DriveExtension->DeviceObject;
1071 }
1072
1073 if (DriveExtension->State < RamdiskStateBusRemoved) DiskCount++;
1074
1075 //
1076 // Move to the next one
1077 //
1078 NextEntry = NextEntry->Flink;
1079 }
1080
1081 //
1082 // Release the lock
1083 //
1084 ExReleaseFastMutex(&DeviceExtension->DiskListLock);
1085 KeLeaveCriticalRegion();
1086
1087 //
1088 // Cleanup old relations
1089 //
1090 if (DeviceRelations) ExFreePool(DeviceRelations);
1091
1092 //
1093 // Complete our IRP
1094 //
1095 Irp->IoStatus.Information = (ULONG_PTR)OurDeviceRelations;
1096 Irp->IoStatus.Status = STATUS_SUCCESS;
1097
1098 //
1099 // Pass to the next driver
1100 //
1101 PassToNext:
1102 IoCopyCurrentIrpStackLocationToNext(Irp);
1103 return IoCallDriver(DeviceExtension->AttachedDevice, Irp);
1104 }
1105
1106 NTSTATUS
1107 NTAPI
1108 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
1109 IN PIRP Irp)
1110 {
1111 PIO_STACK_LOCATION IoStackLocation;
1112 PRAMDISK_BUS_EXTENSION DeviceExtension;
1113 NTSTATUS Status;
1114 UCHAR Minor;
1115
1116 //
1117 // Get the device extension and stack location
1118 //
1119 DeviceExtension = DeviceObject->DeviceExtension;
1120 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1121 Minor = IoStackLocation->MinorFunction;
1122
1123 //
1124 // Check if the bus is removed
1125 //
1126 if (DeviceExtension->State == RamdiskStateBusRemoved)
1127 {
1128 //
1129 // Only remove-device and query-id are allowed
1130 //
1131 if ((Minor != IRP_MN_REMOVE_DEVICE) || (Minor != IRP_MN_QUERY_ID))
1132 {
1133 //
1134 // Fail anything else
1135 //
1136 Status = STATUS_NO_SUCH_DEVICE;
1137 Irp->IoStatus.Status = Status;
1138 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1139 return Status;
1140 }
1141 }
1142
1143 //
1144 // Acquire the remove lock
1145 //
1146 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
1147 if (!NT_SUCCESS(Status))
1148 {
1149 //
1150 // Fail the IRP
1151 //
1152 Irp->IoStatus.Information = 0;
1153 Irp->IoStatus.Status = Status;
1154 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1155 return Status;
1156 }
1157
1158 //
1159 // Query the IRP type
1160 //
1161 switch (Minor)
1162 {
1163 case IRP_MN_START_DEVICE:
1164
1165 DPRINT1("PnP IRP: %lx\n", Minor);
1166 while (TRUE);
1167 break;
1168
1169 case IRP_MN_QUERY_STOP_DEVICE:
1170
1171 DPRINT1("PnP IRP: %lx\n", Minor);
1172 while (TRUE);
1173 break;
1174
1175 case IRP_MN_CANCEL_STOP_DEVICE:
1176
1177 DPRINT1("PnP IRP: %lx\n", Minor);
1178 while (TRUE);
1179 break;
1180
1181 case IRP_MN_STOP_DEVICE:
1182
1183 DPRINT1("PnP IRP: %lx\n", Minor);
1184 while (TRUE);
1185 break;
1186
1187 case IRP_MN_QUERY_REMOVE_DEVICE:
1188
1189 DPRINT1("PnP IRP: %lx\n", Minor);
1190 while (TRUE);
1191 break;
1192
1193 case IRP_MN_CANCEL_REMOVE_DEVICE:
1194
1195 DPRINT1("PnP IRP: %lx\n", Minor);
1196 while (TRUE);
1197 break;
1198
1199 case IRP_MN_REMOVE_DEVICE:
1200
1201 DPRINT1("PnP IRP: %lx\n", Minor);
1202 while (TRUE);
1203 break;
1204
1205 case IRP_MN_SURPRISE_REMOVAL:
1206
1207 DPRINT1("PnP IRP: %lx\n", Minor);
1208 while (TRUE);
1209 break;
1210
1211 case IRP_MN_QUERY_ID:
1212
1213 //
1214 // Are we a drive?
1215 //
1216 if (DeviceExtension->Type == RamdiskDrive)
1217 {
1218 DPRINT1("PnP IRP: %lx\n", Minor);
1219 while (TRUE);
1220 }
1221 break;
1222
1223 case IRP_MN_QUERY_BUS_INFORMATION:
1224
1225 //
1226 // Are we a drive?
1227 //
1228 if (DeviceExtension->Type == RamdiskDrive)
1229 {
1230 DPRINT1("PnP IRP: %lx\n", Minor);
1231 while (TRUE);
1232 }
1233 break;
1234
1235 case IRP_MN_EJECT:
1236
1237 DPRINT1("PnP IRP: %lx\n", Minor);
1238 while (TRUE);
1239 break;
1240
1241 case IRP_MN_QUERY_DEVICE_TEXT:
1242
1243 //
1244 // Are we a drive?
1245 //
1246 if (DeviceExtension->Type == RamdiskDrive)
1247 {
1248 DPRINT1("PnP IRP: %lx\n", Minor);
1249 while (TRUE);
1250 }
1251 break;
1252
1253 case IRP_MN_QUERY_DEVICE_RELATIONS:
1254
1255 //
1256 // Call our main routine
1257 //
1258 Status = RamdiskQueryDeviceRelations(IoStackLocation->
1259 Parameters.
1260 QueryDeviceRelations.Type,
1261 DeviceObject,
1262 Irp);
1263 goto ReleaseAndReturn;
1264
1265 case IRP_MN_QUERY_CAPABILITIES:
1266
1267 //
1268 // Are we a drive?
1269 //
1270 if (DeviceExtension->Type == RamdiskDrive)
1271 {
1272 DPRINT1("PnP IRP: %lx\n", Minor);
1273 while (TRUE);
1274 }
1275 break;
1276
1277 case IRP_MN_QUERY_RESOURCES:
1278 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1279
1280 //
1281 // Complete immediately without touching it
1282 //
1283 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1284 goto ReleaseAndReturn;
1285
1286 default:
1287
1288 DPRINT1("Illegal IRP: %lx\n", Minor);
1289 break;
1290 }
1291
1292 //
1293 // Are we the bus?
1294 //
1295 if (DeviceExtension->Type == RamdiskBus)
1296 {
1297 //
1298 // Do we have an attached device?
1299 //
1300 if (DeviceExtension->AttachedDevice)
1301 {
1302 //
1303 // Forward the IRP
1304 //
1305 IoSkipCurrentIrpStackLocation(Irp);
1306 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
1307 }
1308 }
1309
1310 //
1311 // Release the lock and return status
1312 //
1313 ReleaseAndReturn:
1314 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
1315 return Status;
1316 }
1317
1318 NTSTATUS
1319 NTAPI
1320 RamdiskPower(IN PDEVICE_OBJECT DeviceObject,
1321 IN PIRP Irp)
1322 {
1323 UNIMPLEMENTED;
1324 while (TRUE);
1325 return STATUS_SUCCESS;
1326 }
1327
1328 NTSTATUS
1329 NTAPI
1330 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject,
1331 IN PIRP Irp)
1332 {
1333 UNIMPLEMENTED;
1334 while (TRUE);
1335 return STATUS_SUCCESS;
1336 }
1337
1338 NTSTATUS
1339 NTAPI
1340 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject,
1341 IN PIRP Irp)
1342 {
1343 UNIMPLEMENTED;
1344 while (TRUE);
1345 return STATUS_SUCCESS;
1346 }
1347
1348 NTSTATUS
1349 NTAPI
1350 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
1351 IN PIRP Irp)
1352 {
1353 UNIMPLEMENTED;
1354 while (TRUE);
1355 return STATUS_SUCCESS;
1356 }
1357
1358 VOID
1359 NTAPI
1360 RamdiskUnload(IN PDRIVER_OBJECT DriverObject)
1361 {
1362 UNIMPLEMENTED;
1363 while (TRUE);
1364 }
1365
1366 NTSTATUS
1367 NTAPI
1368 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject,
1369 IN PDEVICE_OBJECT PhysicalDeviceObject)
1370 {
1371 PRAMDISK_BUS_EXTENSION DeviceExtension;
1372 PDEVICE_OBJECT AttachedDevice;
1373 NTSTATUS Status;
1374 UNICODE_STRING DeviceName;
1375 PDEVICE_OBJECT DeviceObject;
1376
1377 //
1378 // Only create the bus FDO once
1379 //
1380 if (RamdiskBusFdo) return STATUS_DEVICE_ALREADY_ATTACHED;
1381
1382 //
1383 // Create the bus FDO
1384 //
1385 RtlInitUnicodeString(&DeviceName, L"\\Device\\Ramdisk");
1386 Status = IoCreateDevice(DriverObject,
1387 sizeof(RAMDISK_BUS_EXTENSION),
1388 &DeviceName,
1389 FILE_DEVICE_BUS_EXTENDER,
1390 FILE_DEVICE_SECURE_OPEN,
1391 0,
1392 &DeviceObject);
1393 if (NT_SUCCESS(Status))
1394 {
1395 //
1396 // Initialize the bus FDO extension
1397 //
1398 DeviceExtension = DeviceObject->DeviceExtension;
1399 RtlZeroMemory(DeviceObject->DeviceExtension,
1400 sizeof(RAMDISK_BUS_EXTENSION));
1401
1402 //
1403 // Set bus FDO flags
1404 //
1405 DeviceObject->Flags |= DO_POWER_PAGABLE | DO_DIRECT_IO;
1406
1407 //
1408 // Setup the bus FDO extension
1409 //
1410 DeviceExtension->Type = RamdiskBus;
1411 ExInitializeFastMutex(&DeviceExtension->DiskListLock);
1412 IoInitializeRemoveLock(&DeviceExtension->RemoveLock,
1413 TAG('R', 'a', 'm', 'd'),
1414 0,
1415 1);
1416 InitializeListHead(&DeviceExtension->DiskList);
1417 DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
1418 DeviceExtension->DeviceObject = DeviceObject;
1419
1420 //
1421 // Register the RAM disk device interface
1422 //
1423 Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
1424 &RamdiskBusInterface,
1425 NULL,
1426 &DeviceExtension->BusDeviceName);
1427 if (!NT_SUCCESS(Status))
1428 {
1429 //
1430 // Fail
1431 //
1432 IoDeleteDevice(DeviceObject);
1433 return Status;
1434 }
1435
1436 //
1437 // Attach us to the device stack
1438 //
1439 AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject,
1440 PhysicalDeviceObject);
1441 DeviceExtension->AttachedDevice = AttachedDevice;
1442 if (!AttachedDevice)
1443 {
1444 //
1445 // Fail
1446 //
1447 IoSetDeviceInterfaceState(&DeviceExtension->BusDeviceName, 0);
1448 RtlFreeUnicodeString(&DeviceExtension->BusDeviceName);
1449 IoDeleteDevice(DeviceObject);
1450 return STATUS_NO_SUCH_DEVICE;
1451 }
1452
1453 //
1454 // Bus FDO is initialized
1455 //
1456 RamdiskBusFdo = DeviceObject;
1457
1458 //
1459 // Loop for loader block
1460 //
1461 if (KeLoaderBlock)
1462 {
1463 //
1464 // Are we being booted from setup? Not yet supported
1465 //
1466 ASSERT (!KeLoaderBlock->SetupLdrBlock);
1467 }
1468
1469 //
1470 // All done
1471 //
1472 DeviceObject->Flags &= DO_DEVICE_INITIALIZING;
1473 Status = STATUS_SUCCESS;
1474 }
1475
1476 //
1477 // Return status
1478 //
1479 return Status;
1480 }
1481
1482 NTSTATUS
1483 NTAPI
1484 DriverEntry(IN PDRIVER_OBJECT DriverObject,
1485 IN PUNICODE_STRING RegistryPath)
1486 {
1487 PCHAR BootDeviceName, CommandLine;
1488 PDEVICE_OBJECT PhysicalDeviceObject = NULL;
1489 NTSTATUS Status;
1490
1491 //
1492 // Query ramdisk parameters
1493 //
1494 QueryParameters(RegistryPath);
1495
1496 //
1497 // Save the registry path
1498 //
1499 DriverRegistryPath = *RegistryPath;
1500 DriverRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
1501 RegistryPath->Length +
1502 sizeof(WCHAR),
1503 TAG('R', 'a', 'm', 'd'));
1504 if (!DriverRegistryPath.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
1505 RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath);
1506
1507 //
1508 // Set device routines
1509 //
1510 DriverObject->MajorFunction[IRP_MJ_CREATE] = RamdiskOpenClose;
1511 DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamdiskOpenClose;
1512 DriverObject->MajorFunction[IRP_MJ_READ] = RamdiskReadWrite;
1513 DriverObject->MajorFunction[IRP_MJ_WRITE] = RamdiskReadWrite;
1514 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamdiskDeviceControl;
1515 DriverObject->MajorFunction[IRP_MJ_PNP] = RamdiskPnp;
1516 DriverObject->MajorFunction[IRP_MJ_POWER] = RamdiskPower;
1517 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamdiskSystemControl;
1518 DriverObject->MajorFunction[IRP_MJ_SCSI] = RamdiskScsi;
1519 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = RamdiskFlushBuffers;
1520 DriverObject->DriverExtension->AddDevice = RamdiskAddDevice;
1521 DriverObject->DriverUnload = RamdiskUnload;
1522
1523 //
1524 // Check for a loader block
1525 //
1526 if (KeLoaderBlock)
1527 {
1528 //
1529 // Get the boot device name
1530 //
1531 BootDeviceName = KeLoaderBlock->ArcBootDeviceName;
1532 if (BootDeviceName)
1533 {
1534 //
1535 // Check if we're booting from ramdisk
1536 //
1537 if ((strlen(BootDeviceName) >= 10) &&
1538 !(_strnicmp(BootDeviceName, "ramdisk(0)", 10)))
1539 {
1540 //
1541 // We'll have to tell the PnP Manager
1542 //
1543 ReportDetectedDevice = TRUE;
1544
1545 //
1546 // Check for a command line
1547 //
1548 CommandLine = KeLoaderBlock->LoadOptions;
1549 if (CommandLine)
1550 {
1551 //
1552 // Check if this is an ISO boot
1553 //
1554 if (strstr(CommandLine, "RDEXPORTASCD"))
1555 {
1556 //
1557 // Remember for later
1558 //
1559 ExportBootDiskAsCd = TRUE;
1560 }
1561
1562 //
1563 // Check if this is PE boot
1564 //
1565 if (strstr(CommandLine, "MININT"))
1566 {
1567 //
1568 // Remember for later
1569 //
1570 IsWinPEBoot = TRUE;
1571 }
1572 }
1573 }
1574
1575 }
1576 }
1577
1578 //
1579 // Installing from Ramdisk isn't supported yet
1580 //
1581 ASSERT(!KeLoaderBlock->SetupLdrBlock);
1582
1583 //
1584 // Are we reporting the device
1585 //
1586 if (ReportDetectedDevice)
1587 {
1588 //
1589 // Do it
1590 //
1591 Status = IoReportDetectedDevice(DriverObject,
1592 InterfaceTypeUndefined,
1593 0xFFFFFFFF,
1594 0xFFFFFFFF,
1595 NULL,
1596 NULL,
1597 0,
1598 &PhysicalDeviceObject);
1599 if (NT_SUCCESS(Status))
1600 {
1601 //
1602 // ReactOS Fix
1603 // The ReactOS Plug and Play Manager is broken and does not create
1604 // the required keys when reporting a detected device.
1605 // We hack around this ourselves.
1606 //
1607 RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION)
1608 PhysicalDeviceObject->DeviceObjectExtension)
1609 ->DeviceNode->InstancePath,
1610 L"Root\\UNKNOWN\\0000");
1611
1612 //
1613 // Create the device object
1614 //
1615 Status = RamdiskAddDevice(DriverObject, PhysicalDeviceObject);
1616 if (NT_SUCCESS(Status))
1617 {
1618 //
1619 // We're done
1620 //
1621 PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1622 Status = STATUS_SUCCESS;
1623 }
1624 }
1625 }
1626 else
1627 {
1628 //
1629 // Done
1630 //
1631 Status = STATUS_SUCCESS;
1632 }
1633
1634 //
1635 // Done
1636 //
1637 return Status;
1638 }