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