- Implement RamdiskCreateRamdisk which validates parameters before calling RamdiskCre...
[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 #define NDEBUG
25 #include <debug.h>
26
27 /* GLOBALS ********************************************************************/
28
29 typedef enum _RAMDISK_DEVICE_TYPE
30 {
31 RamdiskFdo,
32 RamdiskPdo
33 } RAMDISK_DEVICE_TYPE;
34
35 typedef enum _RAMDISK_DEVICE_STATE
36 {
37 RamdiskStateUninitialized,
38 RamdiskStateStarted,
39 RamdiskStatePaused,
40 RamdiskStateStopped,
41 RamdiskStateRemoved,
42 RamdiskStateBusRemoved,
43 } RAMDISK_DEVICE_STATE;
44
45 DEFINE_GUID(RamdiskBusInterface,
46 0x5DC52DF0,
47 0x2F8A,
48 0x410F,
49 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
50
51 typedef struct _RAMDISK_EXTENSION
52 {
53 RAMDISK_DEVICE_TYPE Type;
54 RAMDISK_DEVICE_STATE State;
55 PDEVICE_OBJECT DeviceObject;
56 PDEVICE_OBJECT PhysicalDeviceObject;
57 PDEVICE_OBJECT AttachedDevice;
58 IO_REMOVE_LOCK RemoveLock;
59 UNICODE_STRING SymbolicLinkName;
60 FAST_MUTEX DiskListLock;
61 LIST_ENTRY DiskListHead;
62 } RAMDISK_EXTENSION, *PRAMDISK_EXTENSION;
63
64 ULONG MaximumViewLength;
65 ULONG MaximumPerDiskViewLength;
66 ULONG ReportDetectedDevice;
67 ULONG MarkRamdisksAsRemovable;
68 ULONG MinimumViewCount;
69 ULONG DefaultViewCount;
70 ULONG MaximumViewCount;
71 ULONG MinimumViewLength;
72 ULONG DefaultViewLength;
73 UNICODE_STRING DriverRegistryPath;
74 BOOLEAN ExportBootDiskAsCd;
75 BOOLEAN IsWinPEBoot;
76 PDEVICE_OBJECT RamdiskBusFdo;
77
78 /* FUNCTIONS ******************************************************************/
79
80 VOID
81 NTAPI
82 QueryParameters(IN PUNICODE_STRING RegistryPath)
83 {
84 ULONG MinView, DefView, MinViewLength, DefViewLength, MaxViewLength;
85 RTL_QUERY_REGISTRY_TABLE QueryTable[10];
86
87 //
88 // Set defaults
89 //
90 MaximumViewLength = 0x10000000u;
91 MaximumPerDiskViewLength = 0x10000000u;
92 ReportDetectedDevice = 0;
93 MarkRamdisksAsRemovable = 0;
94 MinimumViewCount = 2;
95 DefaultViewCount = 16;
96 MaximumViewCount = 64;
97 MinimumViewLength = 0x10000u;
98 DefaultViewLength = 0x100000u;
99
100 //
101 // Setup the query table and query the registry
102 //
103 RtlZeroMemory(QueryTable, sizeof(QueryTable));
104 QueryTable[0].Flags = 1;
105 QueryTable[0].Name = L"Parameters";
106 QueryTable[1].Flags = 32;
107 QueryTable[1].Name = L"ReportDetectedDevice";
108 QueryTable[1].EntryContext = &ReportDetectedDevice;
109 QueryTable[2].Flags = 32;
110 QueryTable[2].Name = L"MarkRamdisksAsRemovable";
111 QueryTable[2].EntryContext = &MarkRamdisksAsRemovable;
112 QueryTable[3].Flags = 32;
113 QueryTable[3].Name = L"MinimumViewCount";
114 QueryTable[3].EntryContext = &MinimumViewCount;
115 QueryTable[4].Flags = 32;
116 QueryTable[4].Name = L"DefaultViewCount";
117 QueryTable[4].EntryContext = &DefaultViewCount;
118 QueryTable[5].Flags = 32;
119 QueryTable[5].Name = L"MaximumViewCount";
120 QueryTable[5].EntryContext = &MaximumViewCount;
121 QueryTable[6].Flags = 32;
122 QueryTable[6].Name = L"MinimumViewLength";
123 QueryTable[6].EntryContext = &MinimumViewLength;
124 QueryTable[7].Flags = 32;
125 QueryTable[7].Name = L"DefaultViewLength";
126 QueryTable[7].EntryContext = &DefaultViewLength;
127 QueryTable[8].Flags = 32;
128 QueryTable[8].Name = L"MaximumViewLength";
129 QueryTable[8].EntryContext = &MaximumViewLength;
130 QueryTable[9].Flags = 32;
131 QueryTable[9].Name = L"MaximumPerDiskViewLength";
132 QueryTable[9].EntryContext = &MaximumPerDiskViewLength;
133 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL,
134 RegistryPath->Buffer,
135 QueryTable,
136 NULL,
137 NULL);
138
139 //
140 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
141 //
142 MinView = MinimumViewCount;
143 if (MinimumViewCount >= 2)
144 {
145 if (MinimumViewCount > 256) MinView = 256;
146 }
147 else
148 {
149 MinView = 2;
150 }
151 MinimumViewCount = MinView;
152
153 //
154 // Parse default view count, cannot be bigger than 256 or smaller than minimum
155 //
156 DefView = DefaultViewCount;
157 if (DefaultViewCount >= MinView)
158 {
159 if (DefaultViewCount > 256) DefView = 256;
160 }
161 else
162 {
163 DefView = MinView;
164 }
165 DefaultViewCount = DefView;
166
167 //
168 // Parse maximum view count, cannot be bigger than 256 or smaller than default
169 //
170 if (MaximumViewCount >= DefView)
171 {
172 if (MaximumViewCount > 256) MaximumViewCount = 256;
173 }
174 else
175 {
176 MaximumViewCount = DefView;
177 }
178
179 //
180 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
181 //
182 MinViewLength = MinimumViewLength;
183 if (MinimumViewLength >= 0x10000)
184 {
185 if (MinimumViewLength > 0x40000000) MinViewLength = 0x40000000u;
186 }
187 else
188 {
189 MinViewLength = 0x10000u;
190 }
191 MinimumViewLength = MinViewLength;
192
193 //
194 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
195 //
196 DefViewLength = DefaultViewLength;
197 if (DefaultViewLength >= MinViewLength)
198 {
199 if (DefaultViewLength > 0x40000000) DefViewLength = 0x40000000u;
200 }
201 else
202 {
203 DefViewLength = MinViewLength;
204 }
205 DefaultViewLength = DefViewLength;
206
207 //
208 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
209 //
210 MaxViewLength = MaximumViewLength;
211 if (MaximumViewLength >= DefViewLength)
212 {
213 if (MaximumViewLength > 0x40000000) MaxViewLength = 0x40000000u;
214 }
215 else
216 {
217 MaxViewLength = DefViewLength;
218 }
219 MaximumViewLength = MaxViewLength;
220
221 //
222 // Parse maximum view length per disk, cannot be smaller than 16MB
223 //
224 if (MaximumPerDiskViewLength >= 0x1000000)
225 {
226 if (MaxViewLength > 0xFFFFFFFF) MaximumPerDiskViewLength = -1;
227 }
228 else
229 {
230 MaximumPerDiskViewLength = 0x1000000u;
231 }
232 }
233
234 NTSTATUS
235 NTAPI
236 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject,
237 IN PIRP Irp)
238 {
239 //
240 // Complete the IRP
241 //
242 Irp->IoStatus.Information = 1;
243 Irp->IoStatus.Status = STATUS_SUCCESS;
244 IoCompleteRequest(Irp, IO_NO_INCREMENT);
245 return STATUS_SUCCESS;
246 }
247
248 NTSTATUS
249 NTAPI
250 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject,
251 IN PIRP Irp)
252 {
253 UNIMPLEMENTED;
254 while (TRUE);
255 return STATUS_SUCCESS;
256 }
257
258 NTSTATUS
259 NTAPI
260 RamdiskCreateDiskDevice(IN PRAMDISK_EXTENSION DeviceExtension,
261 IN PRAMDISK_CREATE_INPUT Input,
262 IN BOOLEAN ValidateOnly,
263 OUT PDEVICE_OBJECT *DeviceObject)
264 {
265 UNIMPLEMENTED;
266 while (TRUE);
267 return STATUS_SUCCESS;
268 }
269
270 NTSTATUS
271 NTAPI
272 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject,
273 IN PIRP Irp,
274 IN BOOLEAN ValidateOnly)
275 {
276 PRAMDISK_CREATE_INPUT Input;
277 ULONG Length;
278 PRAMDISK_EXTENSION DeviceExtension;
279 ULONG DiskType;
280 PWCHAR FileNameStart, FileNameEnd;
281 NTSTATUS Status;
282 PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
283
284 //
285 // Get the device extension and our input data
286 //
287 DeviceExtension = (PRAMDISK_EXTENSION)DeviceObject->DeviceExtension;
288 Length = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
289 Input = (PRAMDISK_CREATE_INPUT)Irp->AssociatedIrp.SystemBuffer;
290
291 //
292 // Validate input parameters
293 //
294 if ((Length < sizeof(RAMDISK_CREATE_INPUT)) ||
295 (Input->Version != sizeof(RAMDISK_CREATE_INPUT)))
296 {
297 //
298 // Invalid input
299 //
300 return STATUS_INVALID_PARAMETER;
301 }
302
303 //
304 // Validate the disk type
305 //
306 DiskType = Input->DiskType;
307 if (DiskType == FILE_DEVICE_CONTROLLER) return STATUS_INVALID_PARAMETER;
308
309 //
310 // Look at the disk type
311 //
312 if (DiskType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
313 {
314 //
315 // We only allow this as an early-init boot
316 //
317 if (!KeLoaderBlock) return STATUS_INVALID_PARAMETER;
318
319 //
320 // Save command-line flags
321 //
322 if (ExportBootDiskAsCd) Input->Options.ExportAsCd = TRUE;
323 if (IsWinPEBoot) Input->Options.NoDriveLetter = TRUE;
324 }
325
326 //
327 // Validate the disk type
328 //
329 if ((Input->Options.ExportAsCd) && (DiskType != FILE_DEVICE_CD_ROM_FILE_SYSTEM))
330 {
331 //
332 // If the type isn't CDFS, it has to at least be raw CD
333 //
334 if (DiskType != FILE_DEVICE_CD_ROM) return STATUS_INVALID_PARAMETER;
335 }
336
337 //
338 // Check if this is an actual file
339 //
340 if (DiskType <= FILE_DEVICE_CD_ROM)
341 {
342 //
343 // Validate the file name
344 //
345 FileNameStart = (PWCHAR)((ULONG_PTR)Input + Length);
346 FileNameEnd = Input->FileName + 1;
347 while ((FileNameEnd < FileNameStart) && *(FileNameEnd)) FileNameEnd++;
348 if (FileNameEnd == FileNameStart) return STATUS_INVALID_PARAMETER;
349 }
350
351 //
352 // Create the actual device
353 //
354 Status = RamdiskCreateDiskDevice(DeviceExtension,
355 Input,
356 ValidateOnly,
357 &DeviceObject);
358 if (NT_SUCCESS(Status))
359 {
360 //
361 // Invalidate and set success
362 //
363 IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, 0);
364 Irp->IoStatus.Information = STATUS_SUCCESS;
365 }
366
367 //
368 // We're done
369 //
370 return Status;
371 }
372
373 NTSTATUS
374 NTAPI
375 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
376 IN PIRP Irp)
377 {
378 NTSTATUS Status;
379 PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
380 PRAMDISK_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
381 ULONG Information = 0;
382
383 //
384 // Grab the remove lock
385 //
386 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
387 if (!NT_SUCCESS(Status))
388 {
389 //
390 // Fail the IRP
391 //
392 Irp->IoStatus.Information = 0;
393 Irp->IoStatus.Status = Status;
394 IoCompleteRequest(Irp, IO_NO_INCREMENT);
395 return Status;
396 }
397
398 //
399 // Check if this is an FDO or PDO
400 //
401 if (DeviceExtension->Type == RamdiskFdo)
402 {
403 //
404 // Check what the request is
405 //
406 switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
407 {
408 //
409 // Request to create a ramdisk
410 //
411 case FSCTL_CREATE_RAM_DISK:
412
413 //
414 // Do it
415 //
416 Status = RamdiskCreateRamdisk(DeviceObject, Irp, TRUE);
417 if (!NT_SUCCESS(Status)) goto CompleteRequest;
418 break;
419
420 default:
421
422 //
423 // We don't handle anything else yet
424 //
425 ASSERT(FALSE);
426 while (TRUE);
427 }
428 }
429 else
430 {
431 //
432 // PDO code not yet done
433 //
434 ASSERT(FALSE);
435 }
436
437 //
438 // Queue the request to our worker thread
439 //
440 UNIMPLEMENTED;
441 while (TRUE);
442
443 CompleteRequest:
444 //
445 // Release the lock
446 //
447 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
448 if (Status != STATUS_PENDING)
449 {
450 //
451 // Complete the request
452 //
453 Irp->IoStatus.Status = Status;
454 Irp->IoStatus.Information = Information;
455 IoCompleteRequest(Irp, IO_NO_INCREMENT);
456 }
457
458 //
459 // Return status
460 //
461 return Status;
462 }
463
464 NTSTATUS
465 NTAPI
466 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
467 IN PIRP Irp)
468 {
469 PIO_STACK_LOCATION IoStackLocation;
470 PRAMDISK_EXTENSION DeviceExtension;
471 NTSTATUS Status;
472 UCHAR Minor;
473
474 //
475 // Get the device extension and stack location
476 //
477 DeviceExtension = DeviceObject->DeviceExtension;
478 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
479 Minor = IoStackLocation->MinorFunction;
480
481 //
482 // Check if the bus is removed
483 //
484 if (DeviceExtension->State == RamdiskStateBusRemoved)
485 {
486 //
487 // Only remove-device and query-id are allowed
488 //
489 if ((Minor != IRP_MN_REMOVE_DEVICE) || (Minor != IRP_MN_QUERY_ID))
490 {
491 //
492 // Fail anything else
493 //
494 Status = STATUS_NO_SUCH_DEVICE;
495 Irp->IoStatus.Status = Status;
496 IoCompleteRequest(Irp, IO_NO_INCREMENT);
497 return Status;
498 }
499 }
500
501 //
502 // Acquire the remove lock
503 //
504 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
505 if (!NT_SUCCESS(Status))
506 {
507 //
508 // Fail the IRP
509 //
510 Irp->IoStatus.Information = 0;
511 Irp->IoStatus.Status = Status;
512 IoCompleteRequest(Irp, IO_NO_INCREMENT);
513 return Status;
514 }
515
516 //
517 // Query the IRP type
518 //
519 switch (Minor)
520 {
521 case IRP_MN_START_DEVICE:
522
523 DPRINT1("PnP IRP: %lx\n", Minor);
524 while (TRUE);
525 break;
526
527 case IRP_MN_QUERY_STOP_DEVICE:
528
529 DPRINT1("PnP IRP: %lx\n", Minor);
530 while (TRUE);
531 break;
532
533 case IRP_MN_CANCEL_STOP_DEVICE:
534
535 DPRINT1("PnP IRP: %lx\n", Minor);
536 while (TRUE);
537 break;
538
539 case IRP_MN_STOP_DEVICE:
540
541 DPRINT1("PnP IRP: %lx\n", Minor);
542 while (TRUE);
543 break;
544
545 case IRP_MN_QUERY_REMOVE_DEVICE:
546
547 DPRINT1("PnP IRP: %lx\n", Minor);
548 while (TRUE);
549 break;
550
551 case IRP_MN_CANCEL_REMOVE_DEVICE:
552
553 DPRINT1("PnP IRP: %lx\n", Minor);
554 while (TRUE);
555 break;
556
557 case IRP_MN_REMOVE_DEVICE:
558
559 DPRINT1("PnP IRP: %lx\n", Minor);
560 while (TRUE);
561 break;
562
563 case IRP_MN_SURPRISE_REMOVAL:
564
565 DPRINT1("PnP IRP: %lx\n", Minor);
566 while (TRUE);
567 break;
568
569 case IRP_MN_QUERY_ID:
570
571 //
572 // Are we a PDO?
573 //
574 if (DeviceExtension->Type == RamdiskPdo)
575 {
576 DPRINT1("PnP IRP: %lx\n", Minor);
577 while (TRUE);
578 }
579 break;
580
581 case IRP_MN_QUERY_BUS_INFORMATION:
582
583 //
584 // Are we a PDO?
585 //
586 if (DeviceExtension->Type == RamdiskPdo)
587 {
588 DPRINT1("PnP IRP: %lx\n", Minor);
589 while (TRUE);
590 }
591 break;
592
593 case IRP_MN_EJECT:
594
595 DPRINT1("PnP IRP: %lx\n", Minor);
596 while (TRUE);
597 break;
598
599 case IRP_MN_QUERY_DEVICE_TEXT:
600
601 //
602 // Are we a PDO?
603 //
604 if (DeviceExtension->Type == RamdiskPdo)
605 {
606 DPRINT1("PnP IRP: %lx\n", Minor);
607 while (TRUE);
608 }
609 break;
610
611 case IRP_MN_QUERY_DEVICE_RELATIONS:
612
613 DPRINT1("PnP IRP: %lx\n", Minor);
614 while (TRUE);
615 break;
616
617 case IRP_MN_QUERY_CAPABILITIES:
618
619 //
620 // Are we a PDO?
621 //
622 if (DeviceExtension->Type == RamdiskPdo)
623 {
624 DPRINT1("PnP IRP: %lx\n", Minor);
625 while (TRUE);
626 }
627 break;
628
629 case IRP_MN_QUERY_RESOURCES:
630 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
631
632 //
633 // Complete immediately without touching it
634 //
635 IoCompleteRequest(Irp, IO_NO_INCREMENT);
636 goto ReleaseAndReturn;
637
638 default:
639
640 DPRINT1("Illegal IRP: %lx\n", Minor);
641 break;
642 }
643
644 //
645 // Are we an FDO?
646 //
647 if (DeviceExtension->Type == RamdiskFdo)
648 {
649 //
650 // Do we have an attached device?
651 //
652 if (DeviceExtension->AttachedDevice)
653 {
654 //
655 // Forward the IRP
656 //
657 IoSkipCurrentIrpStackLocation(Irp);
658 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
659 }
660 }
661
662 //
663 // Release the lock and return status
664 //
665 ReleaseAndReturn:
666 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
667 return Status;
668 }
669
670 NTSTATUS
671 NTAPI
672 RamdiskPower(IN PDEVICE_OBJECT DeviceObject,
673 IN PIRP Irp)
674 {
675 UNIMPLEMENTED;
676 while (TRUE);
677 return STATUS_SUCCESS;
678 }
679
680 NTSTATUS
681 NTAPI
682 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject,
683 IN PIRP Irp)
684 {
685 UNIMPLEMENTED;
686 while (TRUE);
687 return STATUS_SUCCESS;
688 }
689
690 NTSTATUS
691 NTAPI
692 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject,
693 IN PIRP Irp)
694 {
695 UNIMPLEMENTED;
696 while (TRUE);
697 return STATUS_SUCCESS;
698 }
699
700 NTSTATUS
701 NTAPI
702 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
703 IN PIRP Irp)
704 {
705 UNIMPLEMENTED;
706 while (TRUE);
707 return STATUS_SUCCESS;
708 }
709
710 VOID
711 NTAPI
712 RamdiskUnload(IN PDRIVER_OBJECT DriverObject)
713 {
714 UNIMPLEMENTED;
715 while (TRUE);
716 }
717
718 NTSTATUS
719 NTAPI
720 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject,
721 IN PDEVICE_OBJECT PhysicalDeviceObject)
722 {
723 PRAMDISK_EXTENSION DeviceExtension;
724 PDEVICE_OBJECT AttachedDevice;
725 NTSTATUS Status;
726 UNICODE_STRING DeviceName;
727 PDEVICE_OBJECT DeviceObject;
728
729 //
730 // Only create the FDO once
731 //
732 if (RamdiskBusFdo) return STATUS_DEVICE_ALREADY_ATTACHED;
733
734 //
735 // Create the FDO
736 //
737 RtlInitUnicodeString(&DeviceName, L"\\Device\\Ramdisk");
738 Status = IoCreateDevice(DriverObject,
739 sizeof(RAMDISK_EXTENSION),
740 &DeviceName,
741 FILE_DEVICE_BUS_EXTENDER,
742 FILE_DEVICE_SECURE_OPEN,
743 0,
744 &DeviceObject);
745 if (NT_SUCCESS(Status))
746 {
747 //
748 // Initialize the FDO extension
749 //
750 DeviceExtension = (PRAMDISK_EXTENSION)DeviceObject->DeviceExtension;
751 RtlZeroMemory(DeviceObject->DeviceExtension, sizeof(RAMDISK_EXTENSION));
752
753 //
754 // Set FDO flags
755 //
756 DeviceObject->Flags |= DO_POWER_PAGABLE | DO_DIRECT_IO;
757
758 //
759 // Setup the FDO extension
760 //
761 DeviceExtension->Type = RamdiskFdo;
762 ExInitializeFastMutex(&DeviceExtension->DiskListLock);
763 IoInitializeRemoveLock(&DeviceExtension->RemoveLock,
764 TAG('R', 'a', 'm', 'd'),
765 0,
766 1);
767 InitializeListHead(&DeviceExtension->DiskListHead);
768 DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
769 DeviceExtension->DeviceObject = DeviceObject;
770
771 //
772 // Register the RAM disk device interface
773 //
774 Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
775 &RamdiskBusInterface,
776 NULL,
777 &DeviceExtension->SymbolicLinkName);
778 if (!NT_SUCCESS(Status))
779 {
780 //
781 // Fail
782 //
783 IoDeleteDevice(DeviceObject);
784 return Status;
785 }
786
787 //
788 // Attach us to the device stack
789 //
790 AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject,
791 PhysicalDeviceObject);
792 DeviceExtension->AttachedDevice = AttachedDevice;
793 if (!AttachedDevice)
794 {
795 //
796 // Fail
797 //
798 IoSetDeviceInterfaceState(&DeviceExtension->SymbolicLinkName, 0);
799 RtlFreeUnicodeString(&DeviceExtension->SymbolicLinkName);
800 IoDeleteDevice(DeviceObject);
801 return STATUS_NO_SUCH_DEVICE;
802 }
803
804 //
805 // FDO is initialized
806 //
807 RamdiskBusFdo = DeviceObject;
808
809 //
810 // Loop for loader block
811 //
812 if (KeLoaderBlock)
813 {
814 //
815 // Are we being booted from setup? Not yet supported
816 //
817 ASSERT (!KeLoaderBlock->SetupLdrBlock);
818 }
819
820 //
821 // All done
822 //
823 DeviceObject->Flags &= DO_DEVICE_INITIALIZING;
824 Status = STATUS_SUCCESS;
825 }
826
827 //
828 // Return status
829 //
830 return Status;
831 }
832
833 NTSTATUS
834 NTAPI
835 DriverEntry(IN PDRIVER_OBJECT DriverObject,
836 IN PUNICODE_STRING RegistryPath)
837 {
838 PCHAR BootDeviceName, CommandLine;
839 PDEVICE_OBJECT PhysicalDeviceObject = NULL;
840 NTSTATUS Status;
841
842 //
843 // Query ramdisk parameters
844 //
845 QueryParameters(RegistryPath);
846
847 //
848 // Save the registry path
849 //
850 DriverRegistryPath = *RegistryPath;
851 DriverRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
852 RegistryPath->Length +
853 sizeof(WCHAR),
854 TAG('R', 'a', 'm', 'd'));
855 if (!DriverRegistryPath.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
856 RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath);
857
858 //
859 // Set device routines
860 //
861 DriverObject->MajorFunction[IRP_MJ_CREATE] = RamdiskOpenClose;
862 DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamdiskOpenClose;
863 DriverObject->MajorFunction[IRP_MJ_READ] = RamdiskReadWrite;
864 DriverObject->MajorFunction[IRP_MJ_WRITE] = RamdiskReadWrite;
865 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamdiskDeviceControl;
866 DriverObject->MajorFunction[IRP_MJ_PNP] = RamdiskPnp;
867 DriverObject->MajorFunction[IRP_MJ_POWER] = RamdiskPower;
868 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamdiskSystemControl;
869 DriverObject->MajorFunction[IRP_MJ_SCSI] = RamdiskScsi;
870 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = RamdiskFlushBuffers;
871 DriverObject->DriverExtension->AddDevice = RamdiskAddDevice;
872 DriverObject->DriverUnload = RamdiskUnload;
873
874 //
875 // Check for a loader block
876 //
877 if (KeLoaderBlock)
878 {
879 //
880 // Get the boot device name
881 //
882 BootDeviceName = KeLoaderBlock->ArcBootDeviceName;
883 if (BootDeviceName)
884 {
885 //
886 // Check if we're booting from ramdisk
887 //
888 if ((strlen(BootDeviceName) >= 10) &&
889 !(_strnicmp(BootDeviceName, "ramdisk(0)", 10)))
890 {
891 //
892 // We'll have to tell the PnP Manager
893 //
894 ReportDetectedDevice = TRUE;
895
896 //
897 // Check for a command line
898 //
899 CommandLine = KeLoaderBlock->LoadOptions;
900 if (CommandLine)
901 {
902 //
903 // Check if this is an ISO boot
904 //
905 if (strstr(CommandLine, "RDEXPORTASCD"))
906 {
907 //
908 // Remember for later
909 //
910 ExportBootDiskAsCd = TRUE;
911 }
912
913 //
914 // Check if this is PE boot
915 //
916 if (strstr(CommandLine, "MININT"))
917 {
918 //
919 // Remember for later
920 //
921 IsWinPEBoot = TRUE;
922 }
923 }
924 }
925
926 }
927 }
928
929 //
930 // Installing from Ramdisk isn't supported yet
931 //
932 ASSERT(!KeLoaderBlock->SetupLdrBlock);
933
934 //
935 // Are we reporting the device
936 //
937 if (ReportDetectedDevice)
938 {
939 //
940 // Do it
941 //
942 Status = IoReportDetectedDevice(DriverObject,
943 InterfaceTypeUndefined,
944 0xFFFFFFFF,
945 0xFFFFFFFF,
946 NULL,
947 NULL,
948 0,
949 &PhysicalDeviceObject);
950 if (NT_SUCCESS(Status))
951 {
952 //
953 // ReactOS Fix
954 // The ReactOS Plug and Play Manager is broken and does not create
955 // the required keys when reporting a detected device.
956 // We hack around this ourselves.
957 //
958 RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode->InstancePath,
959 L"Root\\UNKNOWN\\0000");
960
961 //
962 // Create the device object
963 //
964 Status = RamdiskAddDevice(DriverObject, PhysicalDeviceObject);
965 if (NT_SUCCESS(Status))
966 {
967 //
968 // We're done
969 //
970 PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
971 Status = STATUS_SUCCESS;
972 }
973 }
974 }
975 else
976 {
977 //
978 // Done
979 //
980 Status = STATUS_SUCCESS;
981 }
982
983 //
984 // Done
985 //
986 return Status;
987 }