c56c7918d29c57d230007b5191a1556f9c35564d
[reactos.git] / 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 <ntifs.h>
14 #include <ntdddisk.h>
15 #include <ntddcdrm.h>
16 #include <scsi.h>
17 #include <ntddscsi.h>
18 #include <ntddvol.h>
19 #include <mountdev.h>
20 #include <mountmgr.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 "../../../filesystems/fs_rec/fs_rec.h"
27 #include <stdio.h>
28 #define NDEBUG
29 #include <debug.h>
30
31 /* GLOBALS ********************************************************************/
32
33 #define RAMDISK_SESSION_SIZE \
34 FIELD_OFFSET(CDROM_TOC, TrackData) + sizeof(TRACK_DATA)
35
36 #define RAMDISK_TOC_SIZE \
37 FIELD_OFFSET(CDROM_TOC, TrackData) + 2 * sizeof(TRACK_DATA)
38
39 #define TOC_DATA_TRACK (0x04)
40
41 typedef enum _RAMDISK_DEVICE_TYPE
42 {
43 RamdiskBus,
44 RamdiskDrive
45 } RAMDISK_DEVICE_TYPE;
46
47 typedef enum _RAMDISK_DEVICE_STATE
48 {
49 RamdiskStateUninitialized,
50 RamdiskStateStarted,
51 RamdiskStatePaused,
52 RamdiskStateStopped,
53 RamdiskStateRemoved,
54 RamdiskStateBusRemoved,
55 RamdiskStateEnumerated,
56 } RAMDISK_DEVICE_STATE;
57
58 DEFINE_GUID(RamdiskBusInterface,
59 0x5DC52DF0,
60 0x2F8A,
61 0x410F,
62 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
63
64 typedef struct _RAMDISK_EXTENSION
65 {
66 RAMDISK_DEVICE_TYPE Type;
67 RAMDISK_DEVICE_STATE State;
68 PDEVICE_OBJECT DeviceObject;
69 PDEVICE_OBJECT PhysicalDeviceObject;
70 PDEVICE_OBJECT AttachedDevice;
71 IO_REMOVE_LOCK RemoveLock;
72 UNICODE_STRING DriveDeviceName;
73 UNICODE_STRING BusDeviceName;
74 FAST_MUTEX DiskListLock;
75 LIST_ENTRY DiskList;
76 } RAMDISK_EXTENSION, *PRAMDISK_EXTENSION;
77
78 typedef struct _RAMDISK_BUS_EXTENSION
79 {
80 RAMDISK_EXTENSION;
81 } RAMDISK_BUS_EXTENSION, *PRAMDISK_BUS_EXTENSION;
82
83 typedef struct _RAMDISK_DRIVE_EXTENSION
84 {
85 //
86 // Inherited base class
87 //
88 RAMDISK_EXTENSION;
89
90 //
91 // Data we get from the creator
92 //
93 GUID DiskGuid;
94 UNICODE_STRING GuidString;
95 UNICODE_STRING SymbolicLinkName;
96 ULONG DiskType;
97 RAMDISK_CREATE_OPTIONS DiskOptions;
98 LARGE_INTEGER DiskLength;
99 LONG DiskOffset;
100 WCHAR DriveLetter;
101 ULONG BasePage;
102
103 //
104 // Data we get from the disk
105 //
106 ULONG BytesPerSector;
107 ULONG SectorsPerTrack;
108 ULONG NumberOfHeads;
109 ULONG Cylinders;
110 ULONG HiddenSectors;
111 } RAMDISK_DRIVE_EXTENSION, *PRAMDISK_DRIVE_EXTENSION;
112
113 ULONG MaximumViewLength;
114 ULONG MaximumPerDiskViewLength;
115 ULONG ReportDetectedDevice;
116 ULONG MarkRamdisksAsRemovable;
117 ULONG MinimumViewCount;
118 ULONG DefaultViewCount;
119 ULONG MaximumViewCount;
120 ULONG MinimumViewLength;
121 ULONG DefaultViewLength;
122 UNICODE_STRING DriverRegistryPath;
123 BOOLEAN ExportBootDiskAsCd;
124 BOOLEAN IsWinPEBoot;
125 PDEVICE_OBJECT RamdiskBusFdo;
126
127 /* FUNCTIONS ******************************************************************/
128
129 VOID
130 NTAPI
131 QueryParameters(IN PUNICODE_STRING RegistryPath)
132 {
133 ULONG MinView, DefView, MinViewLength, DefViewLength, MaxViewLength;
134 RTL_QUERY_REGISTRY_TABLE QueryTable[10];
135
136 //
137 // Set defaults
138 //
139 MaximumViewLength = 0x10000000u;
140 MaximumPerDiskViewLength = 0x10000000u;
141 ReportDetectedDevice = 0;
142 MarkRamdisksAsRemovable = 0;
143 MinimumViewCount = 2;
144 DefaultViewCount = 16;
145 MaximumViewCount = 64;
146 MinimumViewLength = 0x10000u;
147 DefaultViewLength = 0x100000u;
148
149 //
150 // Setup the query table and query the registry
151 //
152 RtlZeroMemory(QueryTable, sizeof(QueryTable));
153 QueryTable[0].Flags = 1;
154 QueryTable[0].Name = L"Parameters";
155 QueryTable[1].Flags = 32;
156 QueryTable[1].Name = L"ReportDetectedDevice";
157 QueryTable[1].EntryContext = &ReportDetectedDevice;
158 QueryTable[2].Flags = 32;
159 QueryTable[2].Name = L"MarkRamdisksAsRemovable";
160 QueryTable[2].EntryContext = &MarkRamdisksAsRemovable;
161 QueryTable[3].Flags = 32;
162 QueryTable[3].Name = L"MinimumViewCount";
163 QueryTable[3].EntryContext = &MinimumViewCount;
164 QueryTable[4].Flags = 32;
165 QueryTable[4].Name = L"DefaultViewCount";
166 QueryTable[4].EntryContext = &DefaultViewCount;
167 QueryTable[5].Flags = 32;
168 QueryTable[5].Name = L"MaximumViewCount";
169 QueryTable[5].EntryContext = &MaximumViewCount;
170 QueryTable[6].Flags = 32;
171 QueryTable[6].Name = L"MinimumViewLength";
172 QueryTable[6].EntryContext = &MinimumViewLength;
173 QueryTable[7].Flags = 32;
174 QueryTable[7].Name = L"DefaultViewLength";
175 QueryTable[7].EntryContext = &DefaultViewLength;
176 QueryTable[8].Flags = 32;
177 QueryTable[8].Name = L"MaximumViewLength";
178 QueryTable[8].EntryContext = &MaximumViewLength;
179 QueryTable[9].Flags = 32;
180 QueryTable[9].Name = L"MaximumPerDiskViewLength";
181 QueryTable[9].EntryContext = &MaximumPerDiskViewLength;
182 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL,
183 RegistryPath->Buffer,
184 QueryTable,
185 NULL,
186 NULL);
187
188 //
189 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
190 //
191 MinView = MinimumViewCount;
192 if (MinimumViewCount >= 2)
193 {
194 if (MinimumViewCount > 256) MinView = 256;
195 }
196 else
197 {
198 MinView = 2;
199 }
200 MinimumViewCount = MinView;
201
202 //
203 // Parse default view count, cannot be bigger than 256 or smaller than minimum
204 //
205 DefView = DefaultViewCount;
206 if (DefaultViewCount >= MinView)
207 {
208 if (DefaultViewCount > 256) DefView = 256;
209 }
210 else
211 {
212 DefView = MinView;
213 }
214 DefaultViewCount = DefView;
215
216 //
217 // Parse maximum view count, cannot be bigger than 256 or smaller than default
218 //
219 if (MaximumViewCount >= DefView)
220 {
221 if (MaximumViewCount > 256) MaximumViewCount = 256;
222 }
223 else
224 {
225 MaximumViewCount = DefView;
226 }
227
228 //
229 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
230 //
231 MinViewLength = MinimumViewLength;
232 if (MinimumViewLength >= 0x10000)
233 {
234 if (MinimumViewLength > 0x40000000) MinViewLength = 0x40000000u;
235 }
236 else
237 {
238 MinViewLength = 0x10000u;
239 }
240 MinimumViewLength = MinViewLength;
241
242 //
243 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
244 //
245 DefViewLength = DefaultViewLength;
246 if (DefaultViewLength >= MinViewLength)
247 {
248 if (DefaultViewLength > 0x40000000) DefViewLength = 0x40000000u;
249 }
250 else
251 {
252 DefViewLength = MinViewLength;
253 }
254 DefaultViewLength = DefViewLength;
255
256 //
257 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
258 //
259 MaxViewLength = MaximumViewLength;
260 if (MaximumViewLength >= DefViewLength)
261 {
262 if (MaximumViewLength > 0x40000000) MaxViewLength = 0x40000000u;
263 }
264 else
265 {
266 MaxViewLength = DefViewLength;
267 }
268 MaximumViewLength = MaxViewLength;
269
270 //
271 // Parse maximum view length per disk, cannot be smaller than 16MB
272 //
273 if (MaximumPerDiskViewLength >= 0x1000000)
274 {
275 if (MaxViewLength > 0xFFFFFFFF) MaximumPerDiskViewLength = -1;
276 }
277 else
278 {
279 MaximumPerDiskViewLength = 0x1000000u;
280 }
281 }
282
283 PVOID
284 NTAPI
285 RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
286 IN LARGE_INTEGER Offset,
287 IN ULONG Length,
288 OUT PULONG OutputLength)
289 {
290 PHYSICAL_ADDRESS PhysicalAddress;
291 PVOID MappedBase;
292 ULONG PageOffset;
293 SIZE_T ActualLength;
294 LARGE_INTEGER ActualOffset;
295 LARGE_INTEGER ActualPages;
296
297 //
298 // We only support boot disks for now
299 //
300 ASSERT(DeviceExtension->DiskType == RAMDISK_BOOT_DISK);
301
302 //
303 // Calculate the actual offset in the drive
304 //
305 ActualOffset.QuadPart = DeviceExtension->DiskOffset + Offset.QuadPart;
306
307 //
308 // Convert to pages
309 //
310 ActualPages.QuadPart = ActualOffset.QuadPart >> PAGE_SHIFT;
311
312 //
313 // Now add the base page
314 //
315 ActualPages.QuadPart = DeviceExtension->BasePage + ActualPages.QuadPart;
316
317 //
318 // Calculate final amount of bytes
319 //
320 PhysicalAddress.QuadPart = ActualPages.QuadPart << PAGE_SHIFT;
321
322 //
323 // Calculate pages spanned for the mapping
324 //
325 ActualLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset.QuadPart, Length);
326
327 //
328 // And convert this back to bytes
329 //
330 ActualLength <<= PAGE_SHIFT;
331
332 //
333 // Get the offset within the page
334 //
335 PageOffset = BYTE_OFFSET(ActualOffset.QuadPart);
336
337 //
338 // Map the I/O Space from the loader
339 //
340 MappedBase = MmMapIoSpace(PhysicalAddress, ActualLength, MmCached);
341
342 //
343 // Return actual offset within the page as well as the length
344 //
345 if (MappedBase) MappedBase = (PVOID)((ULONG_PTR)MappedBase + PageOffset);
346 *OutputLength = Length;
347 return MappedBase;
348 }
349
350 VOID
351 NTAPI
352 RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
353 IN PVOID BaseAddress,
354 IN LARGE_INTEGER Offset,
355 IN ULONG Length)
356 {
357 LARGE_INTEGER ActualOffset;
358 SIZE_T ActualLength;
359 ULONG PageOffset;
360
361 //
362 // We only support boot disks for now
363 //
364 ASSERT(DeviceExtension->DiskType == RAMDISK_BOOT_DISK);
365
366 //
367 // Calculate the actual offset in the drive
368 //
369 ActualOffset.QuadPart = DeviceExtension->DiskOffset + Offset.QuadPart;
370
371 //
372 // Calculate pages spanned for the mapping
373 //
374 ActualLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset.QuadPart, Length);
375
376 //
377 // And convert this back to bytes
378 //
379 ActualLength <<= PAGE_SHIFT;
380
381 //
382 // Get the offset within the page
383 //
384 PageOffset = BYTE_OFFSET(ActualOffset.QuadPart);
385
386 //
387 // Calculate actual base address where we mapped this
388 //
389 BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - PageOffset);
390
391 //
392 // Unmap the I/O space we got from the loader
393 //
394 MmUnmapIoSpace(BaseAddress, ActualLength);
395 }
396
397 NTSTATUS
398 NTAPI
399 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension,
400 IN PRAMDISK_CREATE_INPUT Input,
401 IN BOOLEAN ValidateOnly,
402 OUT PRAMDISK_DRIVE_EXTENSION *NewDriveExtension)
403 {
404 ULONG BasePage, ViewCount, DiskType, Length;
405 NTSTATUS Status;
406 PDEVICE_OBJECT DeviceObject;
407 PRAMDISK_DRIVE_EXTENSION DriveExtension;
408 PVOID Buffer;
409 WCHAR LocalBuffer[16];
410 UNICODE_STRING SymbolicLinkName, DriveString, GuidString, DeviceName;
411 PPACKED_BOOT_SECTOR BootSector;
412 BIOS_PARAMETER_BLOCK BiosBlock;
413 ULONG BytesPerSector, SectorsPerTrack, Heads, BytesRead;
414 PVOID BaseAddress;
415 LARGE_INTEGER CurrentOffset, CylinderSize, DiskLength;
416 ULONG CylinderCount, SizeByCylinders;
417
418 //
419 // Check if we're a boot RAM disk
420 //
421 DiskType = Input->DiskType;
422 if (DiskType >= RAMDISK_BOOT_DISK)
423 {
424 //
425 // Check if we're an ISO
426 //
427 if (DiskType == RAMDISK_BOOT_DISK)
428 {
429 //
430 // NTLDR mounted us somewhere
431 //
432 BasePage = Input->BasePage;
433 if (!BasePage) return STATUS_INVALID_PARAMETER;
434
435 //
436 // Sanitize disk options
437 //
438 Input->Options.Fixed = TRUE;
439 Input->Options.Readonly = Input->Options.ExportAsCd |
440 Input->Options.Readonly;
441 Input->Options.Hidden = FALSE;
442 Input->Options.NoDosDevice = FALSE;
443 Input->Options.NoDriveLetter = IsWinPEBoot ? TRUE : FALSE;
444 }
445 else
446 {
447 //
448 // The only other possibility is a WIM disk
449 //
450 if (DiskType != RAMDISK_WIM_DISK)
451 {
452 //
453 // Fail
454 //
455 return STATUS_INVALID_PARAMETER;
456 }
457
458 //
459 // Read the view count instead
460 //
461 ViewCount = Input->ViewCount;
462
463 //
464 // Sanitize disk options
465 //
466 Input->Options.Hidden = FALSE;
467 Input->Options.NoDosDevice = FALSE;
468 Input->Options.Readonly = FALSE;
469 Input->Options.NoDriveLetter = TRUE;
470 Input->Options.Fixed = TRUE;
471 }
472
473 //
474 // Are we just validating and returning to the user?
475 //
476 if (ValidateOnly) return STATUS_SUCCESS;
477
478 //
479 // Build the GUID string
480 //
481 Status = RtlStringFromGUID(&Input->DiskGuid, &GuidString);
482 if (!(NT_SUCCESS(Status)) || !(GuidString.Buffer))
483 {
484 //
485 // Fail
486 //
487 Status = STATUS_INSUFFICIENT_RESOURCES;
488 goto FailCreate;
489 }
490
491 //
492 // Allocate our device name
493 //
494 Length = GuidString.Length + 32;
495 Buffer = ExAllocatePoolWithTag(NonPagedPool,
496 Length,
497 'dmaR');
498 if (!Buffer)
499 {
500 //
501 // Fail
502 //
503 Status = STATUS_INSUFFICIENT_RESOURCES;
504 goto FailCreate;
505 }
506
507 //
508 // Build the device name string
509 //
510 DeviceName.Buffer = Buffer;
511 DeviceName.Length = Length - 2;
512 DeviceName.MaximumLength = Length;
513 wcsncpy(Buffer, L"\\Device\\Ramdisk", Length / sizeof(WCHAR));
514 wcsncat(Buffer, GuidString.Buffer, Length / sizeof(WCHAR));
515
516 //
517 // Create the drive device
518 //
519 Status = IoCreateDevice(DeviceExtension->DeviceObject->DriverObject,
520 sizeof(RAMDISK_DRIVE_EXTENSION),
521 &DeviceName,
522 (Input->Options.ExportAsCd) ?
523 FILE_DEVICE_CD_ROM : FILE_DEVICE_DISK,
524 0,
525 0,
526 &DeviceObject);
527 if (!NT_SUCCESS(Status)) goto FailCreate;
528
529 //
530 // Grab the drive extension
531 //
532 DriveExtension = DeviceObject->DeviceExtension;
533
534 //
535 // Check if we need a DOS device
536 //
537 if (!Input->Options.NoDosDevice)
538 {
539 //
540 // Build the symbolic link name
541 //
542 SymbolicLinkName.MaximumLength = GuidString.Length + 36;
543 SymbolicLinkName.Length = GuidString.Length + 34;
544 Buffer = ExAllocatePoolWithTag(NonPagedPool,
545 SymbolicLinkName.MaximumLength,
546 'dmaR');
547 SymbolicLinkName.Buffer = Buffer;
548 if (Buffer)
549 {
550 //
551 // Create it
552 //
553 wcsncpy(Buffer,
554 L"\\GLOBAL??\\Ramdisk",
555 SymbolicLinkName.MaximumLength / sizeof(WCHAR));
556 wcsncat(Buffer,
557 GuidString.Buffer,
558 SymbolicLinkName.MaximumLength / sizeof(WCHAR));
559 Status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
560 if (!NT_SUCCESS(Status))
561 {
562 //
563 // Nevermind...
564 //
565 Input->Options.NoDosDevice = TRUE;
566 ExFreePool(Buffer);
567 SymbolicLinkName.Buffer = NULL;
568 }
569 }
570 else
571 {
572 //
573 // No DOS device
574 //
575 Input->Options.NoDosDevice = TRUE;
576 }
577
578 //
579 // It this an ISO boot ramdisk?
580 //
581 if (Input->DiskType == RAMDISK_BOOT_DISK)
582 {
583 //
584 // Does it need a drive letter?
585 //
586 if (!Input->Options.NoDriveLetter)
587 {
588 //
589 // Build it and take over the existing symbolic link
590 //
591 _snwprintf(LocalBuffer,
592 30,
593 L"\\DosDevices\\%wc:",
594 Input->DriveLetter);
595 RtlInitUnicodeString(&DriveString, LocalBuffer);
596 IoDeleteSymbolicLink(&DriveString);
597 IoCreateSymbolicLink(&DriveString, &DeviceName);
598
599 //
600 // Save the drive letter
601 //
602 DriveExtension->DriveLetter = Input->DriveLetter;
603 }
604 }
605
606 }
607
608 //
609 // Setup the device object flags
610 //
611 DeviceObject->Flags |= (DO_XIP | DO_POWER_PAGABLE | DO_DIRECT_IO);
612 DeviceObject->AlignmentRequirement = 1;
613
614 //
615 // Build the drive FDO
616 //
617 *NewDriveExtension = DriveExtension;
618 DriveExtension->Type = RamdiskDrive;
619 DiskLength = Input->DiskLength;
620 ExInitializeFastMutex(&DriveExtension->DiskListLock);
621 IoInitializeRemoveLock(&DriveExtension->RemoveLock,
622 'dmaR',
623 0,
624 1);
625 DriveExtension->DriveDeviceName = DeviceName;
626 DriveExtension->SymbolicLinkName = SymbolicLinkName;
627 DriveExtension->GuidString = GuidString;
628 DriveExtension->DiskGuid = Input->DiskGuid;
629 DriveExtension->PhysicalDeviceObject = DeviceObject;
630 DriveExtension->DeviceObject = RamdiskBusFdo;
631 DriveExtension->AttachedDevice = RamdiskBusFdo;
632 DriveExtension->DiskType = Input->DiskType;
633 DriveExtension->DiskOptions = Input->Options;
634 DriveExtension->DiskLength = DiskLength;
635 DriveExtension->DiskOffset = Input->DiskOffset;
636 DriveExtension->BasePage = Input->BasePage;
637 DriveExtension->BytesPerSector = 0;
638 DriveExtension->SectorsPerTrack = 0;
639 DriveExtension->NumberOfHeads = 0;
640
641 //
642 // Make sure we don't free it later
643 //
644 DeviceName.Buffer = NULL;
645 SymbolicLinkName.Buffer = NULL;
646 GuidString.Buffer = NULL;
647
648 //
649 // Check if this is an boot disk, or a registry ram drive
650 //
651 if (!(Input->Options.ExportAsCd) &&
652 (Input->DiskType == RAMDISK_BOOT_DISK))
653 {
654 //
655 // Not an ISO boot, but it's a boot FS -- map it to figure out the
656 // drive settings
657 //
658 CurrentOffset.QuadPart = 0;
659 BaseAddress = RamdiskMapPages(DriveExtension,
660 CurrentOffset,
661 PAGE_SIZE,
662 &BytesRead);
663 if (BaseAddress)
664 {
665 //
666 // Get the data
667 //
668 BootSector = (PPACKED_BOOT_SECTOR)BaseAddress;
669 FatUnpackBios(&BiosBlock, &BootSector->PackedBpb);
670 BytesPerSector = BiosBlock.BytesPerSector;
671 SectorsPerTrack = BiosBlock.SectorsPerTrack;
672 Heads = BiosBlock.Heads;
673
674 //
675 // Save it
676 //
677 DriveExtension->BytesPerSector = BytesPerSector;
678 DriveExtension->SectorsPerTrack = SectorsPerTrack;
679 DriveExtension->NumberOfHeads = Heads;
680
681 //
682 // Unmap now
683 //
684 CurrentOffset.QuadPart = 0;
685 RamdiskUnmapPages(DriveExtension,
686 BaseAddress,
687 CurrentOffset,
688 BytesRead);
689 }
690 else
691 {
692 //
693 // Fail
694 //
695 Status = STATUS_INSUFFICIENT_RESOURCES;
696 goto FailCreate;
697 }
698 }
699
700 //
701 // Check if the drive settings haven't been set yet
702 //
703 if ((DriveExtension->BytesPerSector == 0) ||
704 (DriveExtension->SectorsPerTrack == 0) ||
705 (DriveExtension->NumberOfHeads == 0))
706 {
707 //
708 // Check if this is a CD
709 //
710 if (Input->Options.ExportAsCd)
711 {
712 //
713 // Setup partition parameters default for ISO 9660
714 //
715 DriveExtension->BytesPerSector = 2048;
716 DriveExtension->SectorsPerTrack = 32;
717 DriveExtension->NumberOfHeads = 64;
718 }
719 else
720 {
721 //
722 // Setup partition parameters default for FAT
723 //
724 DriveExtension->BytesPerSector = 512;
725 DriveExtension->SectorsPerTrack = 128;
726 DriveExtension->NumberOfHeads = 16;
727 }
728 }
729
730 //
731 // Calculate the cylinder size
732 //
733 CylinderSize.QuadPart = DriveExtension->BytesPerSector *
734 DriveExtension->SectorsPerTrack *
735 DriveExtension->NumberOfHeads;
736 CylinderCount = DiskLength.QuadPart / CylinderSize.QuadPart;
737 SizeByCylinders = CylinderSize.QuadPart * CylinderCount;
738 DriveExtension->Cylinders = CylinderCount;
739 if ((DiskLength.HighPart > 0) || (SizeByCylinders < DiskLength.LowPart))
740 {
741 //
742 // Align cylinder size up
743 //
744 DriveExtension->Cylinders++;
745 }
746
747 //
748 // Acquire the disk lock
749 //
750 KeEnterCriticalRegion();
751 ExAcquireFastMutex(&DeviceExtension->DiskListLock);
752
753 //
754 // Insert us
755 //
756 InsertTailList(&DeviceExtension->DiskList, &DriveExtension->DiskList);
757
758 //
759 // Release the lock
760 //
761 ExReleaseFastMutex(&DeviceExtension->DiskListLock);
762 KeLeaveCriticalRegion();
763
764 //
765 // Clear init flag
766 //
767 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
768 return STATUS_SUCCESS;
769 }
770
771 FailCreate:
772 UNIMPLEMENTED;
773 while (TRUE);
774 return STATUS_SUCCESS;
775 }
776
777 NTSTATUS
778 NTAPI
779 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject,
780 IN PIRP Irp,
781 IN BOOLEAN ValidateOnly)
782 {
783 PRAMDISK_CREATE_INPUT Input;
784 ULONG Length;
785 PRAMDISK_BUS_EXTENSION DeviceExtension;
786 PRAMDISK_DRIVE_EXTENSION DriveExtension;
787 ULONG DiskType;
788 PWCHAR FileNameStart, FileNameEnd;
789 NTSTATUS Status;
790 PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
791
792 //
793 // Get the device extension and our input data
794 //
795 DeviceExtension = DeviceObject->DeviceExtension;
796 Length = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
797 Input = (PRAMDISK_CREATE_INPUT)Irp->AssociatedIrp.SystemBuffer;
798
799 //
800 // Validate input parameters
801 //
802 if ((Length < sizeof(RAMDISK_CREATE_INPUT)) ||
803 (Input->Version != sizeof(RAMDISK_CREATE_INPUT)))
804 {
805 //
806 // Invalid input
807 //
808 return STATUS_INVALID_PARAMETER;
809 }
810
811 //
812 // Validate the disk type
813 //
814 DiskType = Input->DiskType;
815 if (DiskType == RAMDISK_WIM_DISK) return STATUS_INVALID_PARAMETER;
816
817 //
818 // Look at the disk type
819 //
820 if (DiskType == RAMDISK_BOOT_DISK)
821 {
822 //
823 // We only allow this as an early-init boot
824 //
825 if (!KeLoaderBlock) return STATUS_INVALID_PARAMETER;
826
827 //
828 // Save command-line flags
829 //
830 if (ExportBootDiskAsCd) Input->Options.ExportAsCd = TRUE;
831 if (IsWinPEBoot) Input->Options.NoDriveLetter = TRUE;
832 }
833
834 //
835 // Validate the disk type
836 //
837 if ((Input->Options.ExportAsCd) && (DiskType != RAMDISK_BOOT_DISK))
838 {
839 //
840 // If the type isn't CDFS, it has to at least be raw CD
841 //
842 if (DiskType != RAMDISK_MEMORY_MAPPED_DISK) return STATUS_INVALID_PARAMETER;
843 }
844
845 //
846 // Check if this is an actual file
847 //
848 if (DiskType <= RAMDISK_MEMORY_MAPPED_DISK)
849 {
850 //
851 // Validate the file name
852 //
853 FileNameStart = (PWCHAR)((ULONG_PTR)Input + Length);
854 FileNameEnd = Input->FileName + 1;
855 while ((FileNameEnd < FileNameStart) && *(FileNameEnd)) FileNameEnd++;
856 if (FileNameEnd == FileNameStart) return STATUS_INVALID_PARAMETER;
857 }
858
859 //
860 // Create the actual device
861 //
862 Status = RamdiskCreateDiskDevice(DeviceExtension,
863 Input,
864 ValidateOnly,
865 &DriveExtension);
866 if (NT_SUCCESS(Status))
867 {
868 //
869 // Invalidate and set success
870 //
871 IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, 0);
872 Irp->IoStatus.Information = STATUS_SUCCESS;
873 }
874
875 //
876 // We're done
877 //
878 return Status;
879 }
880
881 VOID
882 NTAPI
883 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject,
884 IN PVOID Context)
885 {
886 PRAMDISK_BUS_EXTENSION DeviceExtension;
887 NTSTATUS Status;
888 PIO_STACK_LOCATION IoStackLocation;
889 PIRP Irp = Context;
890
891 //
892 // Get the stack location
893 //
894 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
895
896 //
897 // Free the work item
898 //
899 IoFreeWorkItem(Irp->Tail.Overlay.DriverContext[0]);
900
901 //
902 // Grab the device extension and lock it
903 //
904 DeviceExtension = DeviceObject->DeviceExtension;
905 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
906 if (NT_SUCCESS(Status))
907 {
908 //
909 // Discriminate by major code
910 //
911 switch (IoStackLocation->MajorFunction)
912 {
913 //
914 // Device control
915 //
916 case IRP_MJ_DEVICE_CONTROL:
917
918 //
919 // Let's take a look at the IOCTL
920 //
921 switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
922 {
923 //
924 // Ramdisk create request
925 //
926 case FSCTL_CREATE_RAM_DISK:
927
928 //
929 // This time we'll do it for real
930 //
931 Status = RamdiskCreateRamdisk(DeviceObject, Irp, FALSE);
932 break;
933
934 case IOCTL_DISK_SET_PARTITION_INFO:
935
936 DPRINT1("Set partition info request\n");
937 UNIMPLEMENTED;
938 while (TRUE);
939 break;
940
941 case IOCTL_DISK_GET_DRIVE_LAYOUT:
942
943 DPRINT1("Get drive layout request\n");
944 UNIMPLEMENTED;
945 while (TRUE);
946 break;
947
948 case IOCTL_DISK_GET_PARTITION_INFO:
949
950 DPRINT1("Get partitinon info request\n");
951 UNIMPLEMENTED;
952 while (TRUE);
953 break;
954
955 default:
956
957 DPRINT1("Invalid request\n");
958 UNIMPLEMENTED;
959 while (TRUE);
960 break;
961 }
962
963 //
964 // We're here
965 //
966 break;
967
968 //
969 // Read or write request
970 //
971 case IRP_MJ_READ:
972 case IRP_MJ_WRITE:
973
974 DPRINT1("Read/Write request\n");
975 UNIMPLEMENTED;
976 while (TRUE);
977 break;
978
979 //
980 // Internal request (SCSI?)
981 //
982 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
983
984 DPRINT1("SCSI request\n");
985 UNIMPLEMENTED;
986 while (TRUE);
987 break;
988
989 //
990 // Flush request
991 //
992 case IRP_MJ_FLUSH_BUFFERS:
993
994 DPRINT1("Flush request\n");
995 UNIMPLEMENTED;
996 while (TRUE);
997 break;
998
999 //
1000 // Anything else
1001 //
1002 default:
1003
1004 DPRINT1("Invalid request: %lx\n", IoStackLocation->MajorFunction);
1005 UNIMPLEMENTED;
1006 while (TRUE);
1007 break;
1008 }
1009
1010 //
1011 // Complete the I/O
1012 //
1013 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
1014 Irp->IoStatus.Status = Status;
1015 Irp->IoStatus.Information = 0;
1016 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
1017 return;
1018 }
1019
1020 //
1021 // Fail the I/O
1022 //
1023 Irp->IoStatus.Status = Status;
1024 Irp->IoStatus.Information = 0;
1025 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1026 }
1027
1028 NTSTATUS
1029 NTAPI
1030 SendIrpToThread(IN PDEVICE_OBJECT DeviceObject,
1031 IN PIRP Irp)
1032 {
1033 PIO_WORKITEM WorkItem;
1034
1035 //
1036 // Mark the IRP pending
1037 //
1038 IoMarkIrpPending(Irp);
1039
1040 //
1041 // Allocate a work item
1042 //
1043 WorkItem = IoAllocateWorkItem(DeviceObject);
1044 if (WorkItem)
1045 {
1046 //
1047 // Queue it up
1048 //
1049 Irp->Tail.Overlay.DriverContext[0] = WorkItem;
1050 IoQueueWorkItem(WorkItem, RamdiskWorkerThread, DelayedWorkQueue, Irp);
1051 return STATUS_PENDING;
1052 }
1053 else
1054 {
1055 //
1056 // Fail
1057 //
1058 return STATUS_INSUFFICIENT_RESOURCES;
1059 }
1060 }
1061
1062 NTSTATUS
1063 NTAPI
1064 RamdiskReadWriteReal(IN PIRP Irp,
1065 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension)
1066 {
1067 PMDL Mdl;
1068 PVOID CurrentBase, SystemVa, BaseAddress;
1069 PIO_STACK_LOCATION IoStackLocation;
1070 LARGE_INTEGER CurrentOffset;
1071 ULONG BytesRead, BytesLeft, CopyLength;
1072 PVOID Source, Destination;
1073 NTSTATUS Status;
1074
1075 //
1076 // Get the MDL and check if it's mapped
1077 //
1078 Mdl = Irp->MdlAddress;
1079 if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
1080 {
1081 //
1082 // Use the mapped address
1083 //
1084 SystemVa = Mdl->MappedSystemVa;
1085 }
1086 else
1087 {
1088 //
1089 // Map it ourselves
1090 //
1091 SystemVa = MmMapLockedPagesSpecifyCache(Mdl,
1092 0,
1093 MmCached,
1094 NULL,
1095 0,
1096 NormalPagePriority);
1097 }
1098
1099 //
1100 // Make sure we were able to map it
1101 //
1102 CurrentBase = SystemVa;
1103 if (!SystemVa) return STATUS_INSUFFICIENT_RESOURCES;
1104
1105 //
1106 // Initialize default
1107 //
1108 Irp->IoStatus.Information = 0;
1109
1110 //
1111 // Get the I/O Stack Location and capture the data
1112 //
1113 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1114 CurrentOffset = IoStackLocation->Parameters.Read.ByteOffset;
1115 BytesLeft = IoStackLocation->Parameters.Read.Length;
1116 if (!BytesLeft) return STATUS_INVALID_PARAMETER;
1117
1118 //
1119 // Do the copy loop
1120 //
1121 while (TRUE)
1122 {
1123 //
1124 // Map the pages
1125 //
1126 BaseAddress = RamdiskMapPages(DeviceExtension,
1127 CurrentOffset,
1128 BytesLeft,
1129 &BytesRead);
1130 if (!BaseAddress) return STATUS_INSUFFICIENT_RESOURCES;
1131
1132 //
1133 // Update our lengths
1134 //
1135 Irp->IoStatus.Information += BytesRead;
1136 CopyLength = BytesRead;
1137
1138 //
1139 // Check if this was a read or write
1140 //
1141 Status = STATUS_SUCCESS;
1142 if (IoStackLocation->MajorFunction == IRP_MJ_READ)
1143 {
1144 //
1145 // Set our copy parameters
1146 //
1147 Destination = CurrentBase;
1148 Source = BaseAddress;
1149 goto DoCopy;
1150 }
1151 else if (IoStackLocation->MajorFunction == IRP_MJ_WRITE)
1152 {
1153 //
1154 // Set our copy parameters
1155 //
1156 Destination = BaseAddress;
1157 Source = CurrentBase;
1158 DoCopy:
1159 //
1160 // Copy the data
1161 //
1162 RtlCopyMemory(Destination, Source, CopyLength);
1163 }
1164 else
1165 {
1166 //
1167 // Prepare us for failure
1168 //
1169 BytesLeft = CopyLength;
1170 Status = STATUS_INVALID_PARAMETER;
1171 }
1172
1173 //
1174 // Unmap the pages
1175 //
1176 RamdiskUnmapPages(DeviceExtension,
1177 BaseAddress,
1178 CurrentOffset,
1179 BytesRead);
1180
1181 //
1182 // Update offset and bytes left
1183 //
1184 BytesLeft -= BytesRead;
1185 CurrentOffset.QuadPart += BytesRead;
1186 CurrentBase = (PVOID)((ULONG_PTR)CurrentBase + BytesRead);
1187
1188 //
1189 // Check if we're done
1190 //
1191 if (!BytesLeft) return Status;
1192 }
1193 }
1194
1195 NTSTATUS
1196 NTAPI
1197 RamdiskGetPartitionInfo(IN PIRP Irp,
1198 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension)
1199 {
1200 NTSTATUS Status;
1201 PPARTITION_INFORMATION PartitionInfo;
1202 PVOID BaseAddress;
1203 LARGE_INTEGER Zero = {{0, 0}};
1204 ULONG Length;
1205 PIO_STACK_LOCATION IoStackLocation;
1206
1207 //
1208 // Validate the length
1209 //
1210 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1211 if (IoStackLocation->Parameters.DeviceIoControl.
1212 OutputBufferLength < sizeof(PARTITION_INFORMATION))
1213 {
1214 //
1215 // Invalid length
1216 //
1217 Status = STATUS_BUFFER_TOO_SMALL;
1218 Irp->IoStatus.Status = Status;
1219 Irp->IoStatus.Information = 0;
1220 return Status;
1221 }
1222
1223 //
1224 // Map the partition table
1225 //
1226 BaseAddress = RamdiskMapPages(DeviceExtension, Zero, PAGE_SIZE, &Length);
1227 if (!BaseAddress)
1228 {
1229 //
1230 // No memory
1231 //
1232 Status = STATUS_INSUFFICIENT_RESOURCES;
1233 Irp->IoStatus.Status = Status;
1234 Irp->IoStatus.Information = 0;
1235 return Status;
1236 }
1237
1238 //
1239 // Fill out the information
1240 //
1241 PartitionInfo = Irp->AssociatedIrp.SystemBuffer;
1242 PartitionInfo->StartingOffset.QuadPart = DeviceExtension->BytesPerSector;
1243 PartitionInfo->PartitionLength.QuadPart = DeviceExtension->BytesPerSector *
1244 DeviceExtension->SectorsPerTrack *
1245 DeviceExtension->NumberOfHeads *
1246 DeviceExtension->Cylinders;
1247 PartitionInfo->HiddenSectors = DeviceExtension->HiddenSectors;
1248 PartitionInfo->PartitionNumber = 0;
1249 PartitionInfo->PartitionType = PARTITION_FAT32; //*((PCHAR)BaseAddress + 450);
1250 PartitionInfo->BootIndicator = (DeviceExtension->DiskType ==
1251 RAMDISK_BOOT_DISK) ? TRUE: FALSE;
1252 PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartitionInfo->
1253 PartitionType);
1254 PartitionInfo->RewritePartition = FALSE;
1255
1256 //
1257 // Unmap the partition table
1258 //
1259 RamdiskUnmapPages(DeviceExtension, BaseAddress, Zero, Length);
1260
1261 //
1262 // Done
1263 //
1264 Irp->IoStatus.Status = STATUS_SUCCESS;
1265 Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
1266 return STATUS_SUCCESS;
1267 }
1268
1269 NTSTATUS
1270 NTAPI
1271 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject,
1272 IN PIRP Irp)
1273 {
1274 //
1275 // Complete the IRP
1276 //
1277 Irp->IoStatus.Information = 1;
1278 Irp->IoStatus.Status = STATUS_SUCCESS;
1279 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1280 return STATUS_SUCCESS;
1281 }
1282
1283 NTSTATUS
1284 NTAPI
1285 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject,
1286 IN PIRP Irp)
1287 {
1288 PRAMDISK_DRIVE_EXTENSION DeviceExtension;
1289 ULONG Length;
1290 LARGE_INTEGER ByteOffset;
1291 PIO_STACK_LOCATION IoStackLocation;
1292 NTSTATUS Status, ReturnStatus;
1293
1294 //
1295 // Get the device extension and make sure this isn't a bus
1296 //
1297 DeviceExtension = DeviceObject->DeviceExtension;
1298 if (DeviceExtension->Type == RamdiskBus)
1299 {
1300 //
1301 // Fail
1302 //
1303 Status = STATUS_INVALID_DEVICE_REQUEST;
1304 goto Complete;
1305 }
1306
1307 //
1308 // Capture parameters
1309 //
1310 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1311 Length = IoStackLocation->Parameters.Read.Length;
1312 ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
1313
1314 //
1315 // FIXME: Validate offset
1316 //
1317
1318 //
1319 // FIXME: Validate sector
1320 //
1321
1322 //
1323 // Validate write
1324 //
1325 if ((IoStackLocation->MajorFunction == IRP_MJ_WRITE) &&
1326 (DeviceExtension->DiskOptions.Readonly))
1327 {
1328 //
1329 // Fail, this is read-only
1330 //
1331 Status = STATUS_MEDIA_WRITE_PROTECTED;
1332 goto Complete;
1333 }
1334
1335 //
1336 // See if we want to do this sync or async
1337 //
1338 if (DeviceExtension->DiskType > RAMDISK_MEMORY_MAPPED_DISK)
1339 {
1340 //
1341 // Do it sync
1342 //
1343 Status = RamdiskReadWriteReal(Irp, DeviceExtension);
1344 goto Complete;
1345 }
1346
1347 //
1348 // Queue it to the worker
1349 //
1350 Status = SendIrpToThread(DeviceObject, Irp);
1351 ReturnStatus = STATUS_PENDING;
1352
1353 //
1354 // Check if we're pending or not
1355 //
1356 if (Status != STATUS_PENDING)
1357 {
1358 Complete:
1359 //
1360 // Complete the IRP
1361 //
1362 Irp->IoStatus.Status = Status;
1363 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
1364 ReturnStatus = Status;
1365 }
1366
1367 //
1368 // Return to caller
1369 //
1370 return ReturnStatus;
1371 }
1372
1373 NTSTATUS
1374 NTAPI
1375 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
1376 IN PIRP Irp)
1377 {
1378 NTSTATUS Status;
1379 PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1380 PRAMDISK_BUS_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
1381 PRAMDISK_DRIVE_EXTENSION DriveExtension = (PVOID)DeviceExtension;
1382 ULONG Information;
1383 PCDROM_TOC Toc;
1384 PDISK_GEOMETRY DiskGeometry;
1385
1386 //
1387 // Grab the remove lock
1388 //
1389 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
1390 if (!NT_SUCCESS(Status))
1391 {
1392 //
1393 // Fail the IRP
1394 //
1395 Irp->IoStatus.Information = 0;
1396 Irp->IoStatus.Status = Status;
1397 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1398 return Status;
1399 }
1400
1401 //
1402 // Setup some defaults
1403 //
1404 Status = STATUS_INVALID_DEVICE_REQUEST;
1405 Information = 0;
1406
1407 //
1408 // Check if this is an bus device or the drive
1409 //
1410 if (DeviceExtension->Type == RamdiskBus)
1411 {
1412 //
1413 // Check what the request is
1414 //
1415 switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
1416 {
1417 //
1418 // Request to create a ramdisk
1419 //
1420 case FSCTL_CREATE_RAM_DISK:
1421
1422 //
1423 // Do it
1424 //
1425 Status = RamdiskCreateRamdisk(DeviceObject, Irp, TRUE);
1426 if (!NT_SUCCESS(Status)) goto CompleteRequest;
1427 break;
1428
1429 default:
1430
1431 //
1432 // We don't handle anything else yet
1433 //
1434 ASSERT(FALSE);
1435 while (TRUE);
1436 }
1437 }
1438 else
1439 {
1440 //
1441 // Check what the request is
1442 //
1443 switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
1444 {
1445 case IOCTL_DISK_CHECK_VERIFY:
1446 case IOCTL_STORAGE_CHECK_VERIFY:
1447 case IOCTL_STORAGE_CHECK_VERIFY2:
1448 case IOCTL_CDROM_CHECK_VERIFY:
1449
1450 UNIMPLEMENTED;
1451 while (TRUE);
1452 break;
1453
1454 case IOCTL_STORAGE_GET_MEDIA_TYPES:
1455 case IOCTL_DISK_GET_MEDIA_TYPES:
1456 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
1457 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
1458
1459 //
1460 // Validate the length
1461 //
1462 if (IoStackLocation->Parameters.DeviceIoControl.
1463 OutputBufferLength < sizeof(DISK_GEOMETRY))
1464 {
1465 //
1466 // Invalid length
1467 //
1468 Status = STATUS_BUFFER_TOO_SMALL;
1469 break;
1470 }
1471
1472 //
1473 // Fill it out
1474 //
1475 DiskGeometry = Irp->AssociatedIrp.SystemBuffer;
1476 DiskGeometry->Cylinders.QuadPart = DriveExtension->Cylinders;
1477 DiskGeometry->BytesPerSector = DriveExtension->BytesPerSector;
1478 DiskGeometry->SectorsPerTrack = DriveExtension->SectorsPerTrack;
1479 DiskGeometry->TracksPerCylinder = DriveExtension->NumberOfHeads;
1480 DiskGeometry->MediaType = DriveExtension->DiskOptions.Fixed ?
1481 FixedMedia : RemovableMedia;
1482
1483 //
1484 // We're done
1485 //
1486 Status = STATUS_SUCCESS;
1487 Information = sizeof(DISK_GEOMETRY);
1488 break;
1489
1490 //
1491 // Hack to support ReactOS's broken CDFS
1492 //
1493 case IOCTL_CDROM_GET_LAST_SESSION:
1494
1495 //
1496 // Validate the length
1497 //
1498 if (IoStackLocation->Parameters.DeviceIoControl.
1499 OutputBufferLength < RAMDISK_SESSION_SIZE)
1500 {
1501 //
1502 // Invalid length
1503 //
1504 Status = STATUS_BUFFER_TOO_SMALL;
1505 break;
1506 }
1507
1508 //
1509 // Fill out the TOC
1510 //
1511 Toc = Irp->AssociatedIrp.SystemBuffer;
1512 Toc->Length[0] = 0;
1513 Toc->Length[1] = RAMDISK_SESSION_SIZE - sizeof(Toc->Length);
1514 Toc->FirstTrack = 1;
1515 Toc->LastTrack = 1;
1516 Toc->TrackData[0].Adr = 1;
1517 Toc->TrackData[0].Control = TOC_DATA_TRACK;
1518 Toc->TrackData[0].TrackNumber = 1;
1519 Toc->TrackData[0].Address[0] =
1520 Toc->TrackData[0].Address[1] =
1521 Toc->TrackData[0].Address[2] =
1522 Toc->TrackData[0].Address[3] = 0;
1523
1524 //
1525 // We're done
1526 //
1527 Status = STATUS_SUCCESS;
1528 Information = RAMDISK_SESSION_SIZE;
1529 break;
1530
1531 case IOCTL_CDROM_READ_TOC:
1532
1533 //
1534 // Validate the length
1535 //
1536 if (IoStackLocation->Parameters.DeviceIoControl.
1537 OutputBufferLength < sizeof(CDROM_TOC))
1538 {
1539 //
1540 // Invalid length
1541 //
1542 Status = STATUS_BUFFER_TOO_SMALL;
1543 break;
1544 }
1545
1546 //
1547 // Clear the TOC
1548 //
1549 Toc = Irp->AssociatedIrp.SystemBuffer;
1550 RtlZeroMemory(Toc, sizeof(CDROM_TOC));
1551
1552 //
1553 // Fill it out
1554 //
1555 Toc->Length[0] = 0;
1556 Toc->Length[1] = RAMDISK_TOC_SIZE - sizeof(Toc->Length);
1557 Toc->FirstTrack = 1;
1558 Toc->LastTrack = 1;
1559 Toc->TrackData[0].Adr = 1;
1560 Toc->TrackData[0].Control = TOC_DATA_TRACK;
1561 Toc->TrackData[0].TrackNumber = 1;
1562
1563 //
1564 // We're done
1565 //
1566 Status = STATUS_SUCCESS;
1567 Information = RAMDISK_TOC_SIZE;
1568 break;
1569
1570 case IOCTL_DISK_SET_PARTITION_INFO:
1571
1572 UNIMPLEMENTED;
1573 while (TRUE);
1574 break;
1575
1576 case IOCTL_DISK_GET_PARTITION_INFO:
1577
1578 //
1579 // Validate the length
1580 //
1581 if (IoStackLocation->Parameters.DeviceIoControl.
1582 OutputBufferLength < sizeof(PARTITION_INFORMATION))
1583 {
1584 //
1585 // Invalid length
1586 //
1587 Status = STATUS_BUFFER_TOO_SMALL;
1588 break;
1589 }
1590
1591 //
1592 // Check if we need to do this sync or async
1593 //
1594 if (DriveExtension->DiskType > RAMDISK_MEMORY_MAPPED_DISK)
1595 {
1596 //
1597 // Call the helper function
1598 //
1599 Status = RamdiskGetPartitionInfo(Irp, DriveExtension);
1600 }
1601 else
1602 {
1603 //
1604 // Do it asynchronously later
1605 //
1606 goto CallWorker;
1607 }
1608
1609 //
1610 // We're done
1611 //
1612 Information = Irp->IoStatus.Information;
1613 break;
1614
1615 case IOCTL_DISK_GET_DRIVE_LAYOUT:
1616
1617 UNIMPLEMENTED;
1618 while (TRUE);
1619 break;
1620
1621 case IOCTL_DISK_GET_LENGTH_INFO:
1622
1623 UNIMPLEMENTED;
1624 while (TRUE);
1625 break;
1626
1627 case IOCTL_DISK_IS_WRITABLE:
1628
1629 UNIMPLEMENTED;
1630 while (TRUE);
1631 break;
1632
1633 case IOCTL_SCSI_MINIPORT:
1634
1635 UNIMPLEMENTED;
1636 while (TRUE);
1637 break;
1638
1639 case IOCTL_STORAGE_QUERY_PROPERTY:
1640
1641 UNIMPLEMENTED;
1642 while (TRUE);
1643 break;
1644
1645 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
1646
1647 UNIMPLEMENTED;
1648 while (TRUE);
1649 break;
1650
1651 case IOCTL_MOUNTDEV_QUERY_STABLE_GUID:
1652
1653 UNIMPLEMENTED;
1654 while (TRUE);
1655 break;
1656
1657 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
1658
1659 UNIMPLEMENTED;
1660 while (TRUE);
1661 break;
1662
1663 case IOCTL_VOLUME_SET_GPT_ATTRIBUTES:
1664
1665 UNIMPLEMENTED;
1666 while (TRUE);
1667 break;
1668
1669 case IOCTL_VOLUME_GET_GPT_ATTRIBUTES:
1670
1671 UNIMPLEMENTED;
1672 while (TRUE);
1673 break;
1674
1675 case IOCTL_VOLUME_OFFLINE:
1676
1677 UNIMPLEMENTED;
1678 while (TRUE);
1679 break;
1680
1681 default:
1682
1683 //
1684 // Drive code not emulated
1685 //
1686 DPRINT1("IOCTL: %lx\n", IoStackLocation->Parameters.DeviceIoControl.IoControlCode);
1687 break;
1688 }
1689
1690 //
1691 // If requests drop down here, we just return them complete them
1692 //
1693 goto CompleteRequest;
1694 }
1695
1696 //
1697 // Queue the request to our worker thread
1698 //
1699 CallWorker:
1700 Status = SendIrpToThread(DeviceObject, Irp);
1701
1702 CompleteRequest:
1703 //
1704 // Release the lock
1705 //
1706 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
1707 if (Status != STATUS_PENDING)
1708 {
1709 //
1710 // Complete the request
1711 //
1712 Irp->IoStatus.Status = Status;
1713 Irp->IoStatus.Information = Information;
1714 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1715 }
1716
1717 //
1718 // Return status
1719 //
1720 return Status;
1721 }
1722
1723 NTSTATUS
1724 NTAPI
1725 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type,
1726 IN PDEVICE_OBJECT DeviceObject,
1727 IN PIRP Irp)
1728 {
1729 PRAMDISK_BUS_EXTENSION DeviceExtension;
1730 PRAMDISK_DRIVE_EXTENSION DriveExtension;
1731 PDEVICE_RELATIONS DeviceRelations, OurDeviceRelations;
1732 ULONG Count, DiskCount, FinalCount;
1733 PLIST_ENTRY ListHead, NextEntry;
1734 PDEVICE_OBJECT* DriveDeviceObject;
1735 RAMDISK_DEVICE_STATE State;
1736
1737 //
1738 // Get the device extension and check if this is a drive
1739 //
1740 DeviceExtension = DeviceObject->DeviceExtension;
1741 if (DeviceExtension->Type == RamdiskDrive)
1742 {
1743 //
1744 // FIXME: TODO
1745 //
1746 UNIMPLEMENTED;
1747 while (TRUE);
1748 }
1749
1750 //
1751 // Anything but bus relations, we don't handle
1752 //
1753 if (Type) goto PassToNext;
1754
1755 //
1756 // Acquire the disk list lock
1757 //
1758 KeEnterCriticalRegion();
1759 ExAcquireFastMutex(&DeviceExtension->DiskListLock);
1760
1761 //
1762 // Did a device already fill relations?
1763 //
1764 DeviceRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
1765 if (DeviceRelations)
1766 {
1767 //
1768 // Use the data
1769 //
1770 Count = DeviceRelations->Count;
1771 }
1772 else
1773 {
1774 //
1775 // We're the first
1776 //
1777 Count = 0;
1778 }
1779
1780 //
1781 // Now loop our drives
1782 //
1783 DiskCount = 0;
1784 ListHead = &DeviceExtension->DiskList;
1785 NextEntry = ListHead->Flink;
1786 while (NextEntry != ListHead)
1787 {
1788 //
1789 // As long as it wasn't removed, count it in
1790 //
1791 DriveExtension = CONTAINING_RECORD(NextEntry,
1792 RAMDISK_DRIVE_EXTENSION,
1793 DiskList);
1794 if (DriveExtension->State < RamdiskStateBusRemoved) DiskCount++;
1795
1796 //
1797 // Move to the next one
1798 //
1799 NextEntry = NextEntry->Flink;
1800 }
1801
1802 //
1803 // Now we know our final count
1804 //
1805 FinalCount = Count + DiskCount;
1806
1807 //
1808 // Allocate the structure
1809 //
1810 OurDeviceRelations = ExAllocatePoolWithTag(PagedPool,
1811 FIELD_OFFSET(DEVICE_RELATIONS,
1812 Objects) +
1813 FinalCount *
1814 sizeof(PDEVICE_OBJECT),
1815 'dmaR');
1816 if (!OurDeviceRelations)
1817 {
1818 //
1819 // Fail
1820 //
1821 ExReleaseFastMutex(&DeviceExtension->DiskListLock);
1822 KeLeaveCriticalRegion();
1823 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1824 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1825 return STATUS_INSUFFICIENT_RESOURCES;
1826 }
1827
1828 //
1829 // Check if we already had some relations
1830 //
1831 if (Count)
1832 {
1833 //
1834 // Copy them in
1835 //
1836 RtlCopyMemory(OurDeviceRelations->Objects,
1837 DeviceRelations->Objects,
1838 Count * sizeof(PDEVICE_OBJECT));
1839 }
1840
1841 //
1842 // Save the count
1843 //
1844 OurDeviceRelations->Count = FinalCount;
1845
1846 //
1847 // Now loop our drives again
1848 //
1849 ListHead = &DeviceExtension->DiskList;
1850 NextEntry = ListHead->Flink;
1851 while (NextEntry != ListHead)
1852 {
1853 //
1854 // Go to the end of the list
1855 //
1856 DriveDeviceObject = &OurDeviceRelations->Objects[Count];
1857
1858 //
1859 // Get the drive state
1860 //
1861 DriveExtension = CONTAINING_RECORD(NextEntry,
1862 RAMDISK_DRIVE_EXTENSION,
1863 DiskList);
1864 State = DriveExtension->State;
1865
1866 //
1867 // If it was removed or enumerated, we don't touch the device object
1868 //
1869 if (State >= RamdiskStateBusRemoved)
1870 {
1871 //
1872 // If it was removed, we still have to keep track of this though
1873 //
1874 if (State == RamdiskStateBusRemoved)
1875 {
1876 //
1877 // Mark it as enumerated now, but don't actually reference it
1878 //
1879 DriveExtension->State = RamdiskStateEnumerated;
1880 }
1881 }
1882 else
1883 {
1884 //
1885 // First time it's enumerated, reference the device object
1886 //
1887 ObReferenceObject(DriveExtension->DeviceObject);
1888
1889 //
1890 // Save the object pointer, and move on
1891 //
1892 *DriveDeviceObject++ = DriveExtension->DeviceObject;
1893 }
1894
1895 if (DriveExtension->State < RamdiskStateBusRemoved) DiskCount++;
1896
1897 //
1898 // Move to the next one
1899 //
1900 NextEntry = NextEntry->Flink;
1901 }
1902
1903 //
1904 // Release the lock
1905 //
1906 ExReleaseFastMutex(&DeviceExtension->DiskListLock);
1907 KeLeaveCriticalRegion();
1908
1909 //
1910 // Cleanup old relations
1911 //
1912 if (DeviceRelations) ExFreePool(DeviceRelations);
1913
1914 //
1915 // Complete our IRP
1916 //
1917 Irp->IoStatus.Information = (ULONG_PTR)OurDeviceRelations;
1918 Irp->IoStatus.Status = STATUS_SUCCESS;
1919
1920 //
1921 // Pass to the next driver
1922 //
1923 PassToNext:
1924 IoCopyCurrentIrpStackLocationToNext(Irp);
1925 return IoCallDriver(DeviceExtension->AttachedDevice, Irp);
1926 }
1927
1928 NTSTATUS
1929 NTAPI
1930 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
1931 IN PIRP Irp)
1932 {
1933 PIO_STACK_LOCATION IoStackLocation;
1934 PRAMDISK_BUS_EXTENSION DeviceExtension;
1935 NTSTATUS Status;
1936 UCHAR Minor;
1937
1938 //
1939 // Get the device extension and stack location
1940 //
1941 DeviceExtension = DeviceObject->DeviceExtension;
1942 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1943 Minor = IoStackLocation->MinorFunction;
1944
1945 //
1946 // Check if the bus is removed
1947 //
1948 if (DeviceExtension->State == RamdiskStateBusRemoved)
1949 {
1950 //
1951 // Only remove-device and query-id are allowed
1952 //
1953 if ((Minor != IRP_MN_REMOVE_DEVICE) || (Minor != IRP_MN_QUERY_ID))
1954 {
1955 //
1956 // Fail anything else
1957 //
1958 Status = STATUS_NO_SUCH_DEVICE;
1959 Irp->IoStatus.Status = Status;
1960 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1961 return Status;
1962 }
1963 }
1964
1965 //
1966 // Acquire the remove lock
1967 //
1968 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
1969 if (!NT_SUCCESS(Status))
1970 {
1971 //
1972 // Fail the IRP
1973 //
1974 Irp->IoStatus.Information = 0;
1975 Irp->IoStatus.Status = Status;
1976 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1977 return Status;
1978 }
1979
1980 //
1981 // Query the IRP type
1982 //
1983 switch (Minor)
1984 {
1985 case IRP_MN_START_DEVICE:
1986
1987 DPRINT1("PnP IRP: %lx\n", Minor);
1988 while (TRUE);
1989 break;
1990
1991 case IRP_MN_QUERY_STOP_DEVICE:
1992
1993 DPRINT1("PnP IRP: %lx\n", Minor);
1994 while (TRUE);
1995 break;
1996
1997 case IRP_MN_CANCEL_STOP_DEVICE:
1998
1999 DPRINT1("PnP IRP: %lx\n", Minor);
2000 while (TRUE);
2001 break;
2002
2003 case IRP_MN_STOP_DEVICE:
2004
2005 DPRINT1("PnP IRP: %lx\n", Minor);
2006 while (TRUE);
2007 break;
2008
2009 case IRP_MN_QUERY_REMOVE_DEVICE:
2010
2011 DPRINT1("PnP IRP: %lx\n", Minor);
2012 while (TRUE);
2013 break;
2014
2015 case IRP_MN_CANCEL_REMOVE_DEVICE:
2016
2017 DPRINT1("PnP IRP: %lx\n", Minor);
2018 while (TRUE);
2019 break;
2020
2021 case IRP_MN_REMOVE_DEVICE:
2022
2023 DPRINT1("PnP IRP: %lx\n", Minor);
2024 while (TRUE);
2025 break;
2026
2027 case IRP_MN_SURPRISE_REMOVAL:
2028
2029 DPRINT1("PnP IRP: %lx\n", Minor);
2030 while (TRUE);
2031 break;
2032
2033 case IRP_MN_QUERY_ID:
2034
2035 //
2036 // Are we a drive?
2037 //
2038 if (DeviceExtension->Type == RamdiskDrive)
2039 {
2040 DPRINT1("PnP IRP: %lx\n", Minor);
2041 while (TRUE);
2042 }
2043 break;
2044
2045 case IRP_MN_QUERY_BUS_INFORMATION:
2046
2047 //
2048 // Are we a drive?
2049 //
2050 if (DeviceExtension->Type == RamdiskDrive)
2051 {
2052 DPRINT1("PnP IRP: %lx\n", Minor);
2053 while (TRUE);
2054 }
2055 break;
2056
2057 case IRP_MN_EJECT:
2058
2059 DPRINT1("PnP IRP: %lx\n", Minor);
2060 while (TRUE);
2061 break;
2062
2063 case IRP_MN_QUERY_DEVICE_TEXT:
2064
2065 //
2066 // Are we a drive?
2067 //
2068 if (DeviceExtension->Type == RamdiskDrive)
2069 {
2070 DPRINT1("PnP IRP: %lx\n", Minor);
2071 while (TRUE);
2072 }
2073 break;
2074
2075 case IRP_MN_QUERY_DEVICE_RELATIONS:
2076
2077 //
2078 // Call our main routine
2079 //
2080 Status = RamdiskQueryDeviceRelations(IoStackLocation->
2081 Parameters.
2082 QueryDeviceRelations.Type,
2083 DeviceObject,
2084 Irp);
2085 goto ReleaseAndReturn;
2086
2087 case IRP_MN_QUERY_CAPABILITIES:
2088
2089 //
2090 // Are we a drive?
2091 //
2092 if (DeviceExtension->Type == RamdiskDrive)
2093 {
2094 DPRINT1("PnP IRP: %lx\n", Minor);
2095 while (TRUE);
2096 }
2097 break;
2098
2099 case IRP_MN_QUERY_RESOURCES:
2100 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
2101
2102 //
2103 // Complete immediately without touching it
2104 //
2105 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2106 goto ReleaseAndReturn;
2107
2108 default:
2109
2110 DPRINT1("Illegal IRP: %lx\n", Minor);
2111 break;
2112 }
2113
2114 //
2115 // Are we the bus?
2116 //
2117 if (DeviceExtension->Type == RamdiskBus)
2118 {
2119 //
2120 // Do we have an attached device?
2121 //
2122 if (DeviceExtension->AttachedDevice)
2123 {
2124 //
2125 // Forward the IRP
2126 //
2127 IoSkipCurrentIrpStackLocation(Irp);
2128 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
2129 }
2130 }
2131
2132 //
2133 // Release the lock and return status
2134 //
2135 ReleaseAndReturn:
2136 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
2137 return Status;
2138 }
2139
2140 NTSTATUS
2141 NTAPI
2142 RamdiskPower(IN PDEVICE_OBJECT DeviceObject,
2143 IN PIRP Irp)
2144 {
2145 UNIMPLEMENTED;
2146 while (TRUE);
2147 return STATUS_SUCCESS;
2148 }
2149
2150 NTSTATUS
2151 NTAPI
2152 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject,
2153 IN PIRP Irp)
2154 {
2155 UNIMPLEMENTED;
2156 while (TRUE);
2157 return STATUS_SUCCESS;
2158 }
2159
2160 NTSTATUS
2161 NTAPI
2162 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject,
2163 IN PIRP Irp)
2164 {
2165 UNIMPLEMENTED;
2166 while (TRUE);
2167 return STATUS_SUCCESS;
2168 }
2169
2170 NTSTATUS
2171 NTAPI
2172 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
2173 IN PIRP Irp)
2174 {
2175 UNIMPLEMENTED;
2176 while (TRUE);
2177 return STATUS_SUCCESS;
2178 }
2179
2180 VOID
2181 NTAPI
2182 RamdiskUnload(IN PDRIVER_OBJECT DriverObject)
2183 {
2184 UNIMPLEMENTED;
2185 while (TRUE);
2186 }
2187
2188 NTSTATUS
2189 NTAPI
2190 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject,
2191 IN PDEVICE_OBJECT PhysicalDeviceObject)
2192 {
2193 PRAMDISK_BUS_EXTENSION DeviceExtension;
2194 PDEVICE_OBJECT AttachedDevice;
2195 NTSTATUS Status;
2196 UNICODE_STRING DeviceName;
2197 PDEVICE_OBJECT DeviceObject;
2198
2199 //
2200 // Only create the bus FDO once
2201 //
2202 if (RamdiskBusFdo) return STATUS_DEVICE_ALREADY_ATTACHED;
2203
2204 //
2205 // Create the bus FDO
2206 //
2207 RtlInitUnicodeString(&DeviceName, L"\\Device\\Ramdisk");
2208 Status = IoCreateDevice(DriverObject,
2209 sizeof(RAMDISK_BUS_EXTENSION),
2210 &DeviceName,
2211 FILE_DEVICE_BUS_EXTENDER,
2212 FILE_DEVICE_SECURE_OPEN,
2213 0,
2214 &DeviceObject);
2215 if (NT_SUCCESS(Status))
2216 {
2217 //
2218 // Initialize the bus FDO extension
2219 //
2220 DeviceExtension = DeviceObject->DeviceExtension;
2221 RtlZeroMemory(DeviceObject->DeviceExtension,
2222 sizeof(RAMDISK_BUS_EXTENSION));
2223
2224 //
2225 // Set bus FDO flags
2226 //
2227 DeviceObject->Flags |= DO_POWER_PAGABLE | DO_DIRECT_IO;
2228
2229 //
2230 // Setup the bus FDO extension
2231 //
2232 DeviceExtension->Type = RamdiskBus;
2233 ExInitializeFastMutex(&DeviceExtension->DiskListLock);
2234 IoInitializeRemoveLock(&DeviceExtension->RemoveLock,
2235 'dmaR',
2236 0,
2237 1);
2238 InitializeListHead(&DeviceExtension->DiskList);
2239 DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
2240 DeviceExtension->DeviceObject = DeviceObject;
2241
2242 //
2243 // Register the RAM disk device interface
2244 //
2245 Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
2246 &RamdiskBusInterface,
2247 NULL,
2248 &DeviceExtension->BusDeviceName);
2249 if (!NT_SUCCESS(Status))
2250 {
2251 //
2252 // Fail
2253 //
2254 IoDeleteDevice(DeviceObject);
2255 return Status;
2256 }
2257
2258 //
2259 // Attach us to the device stack
2260 //
2261 AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject,
2262 PhysicalDeviceObject);
2263 DeviceExtension->AttachedDevice = AttachedDevice;
2264 if (!AttachedDevice)
2265 {
2266 //
2267 // Fail
2268 //
2269 IoSetDeviceInterfaceState(&DeviceExtension->BusDeviceName, 0);
2270 RtlFreeUnicodeString(&DeviceExtension->BusDeviceName);
2271 IoDeleteDevice(DeviceObject);
2272 return STATUS_NO_SUCH_DEVICE;
2273 }
2274
2275 //
2276 // Bus FDO is initialized
2277 //
2278 RamdiskBusFdo = DeviceObject;
2279
2280 //
2281 // Loop for loader block
2282 //
2283 if (KeLoaderBlock)
2284 {
2285 //
2286 // Are we being booted from setup? Not yet supported
2287 //
2288 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
2289 }
2290
2291 //
2292 // All done
2293 //
2294 DeviceObject->Flags &= DO_DEVICE_INITIALIZING;
2295 Status = STATUS_SUCCESS;
2296 }
2297
2298 //
2299 // Return status
2300 //
2301 return Status;
2302 }
2303
2304 NTSTATUS
2305 NTAPI
2306 DriverEntry(IN PDRIVER_OBJECT DriverObject,
2307 IN PUNICODE_STRING RegistryPath)
2308 {
2309 PCHAR BootDeviceName, CommandLine;
2310 PDEVICE_OBJECT PhysicalDeviceObject = NULL;
2311 NTSTATUS Status;
2312 DPRINT("RAM Disk Driver Initialized\n");
2313
2314 //
2315 // Query ramdisk parameters
2316 //
2317 QueryParameters(RegistryPath);
2318
2319 //
2320 // Save the registry path
2321 //
2322 DriverRegistryPath = *RegistryPath;
2323 DriverRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
2324 RegistryPath->Length +
2325 sizeof(WCHAR),
2326 'dmaR');
2327 if (!DriverRegistryPath.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
2328 RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath);
2329
2330 //
2331 // Set device routines
2332 //
2333 DriverObject->MajorFunction[IRP_MJ_CREATE] = RamdiskOpenClose;
2334 DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamdiskOpenClose;
2335 DriverObject->MajorFunction[IRP_MJ_READ] = RamdiskReadWrite;
2336 DriverObject->MajorFunction[IRP_MJ_WRITE] = RamdiskReadWrite;
2337 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamdiskDeviceControl;
2338 DriverObject->MajorFunction[IRP_MJ_PNP] = RamdiskPnp;
2339 DriverObject->MajorFunction[IRP_MJ_POWER] = RamdiskPower;
2340 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamdiskSystemControl;
2341 DriverObject->MajorFunction[IRP_MJ_SCSI] = RamdiskScsi;
2342 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = RamdiskFlushBuffers;
2343 DriverObject->DriverExtension->AddDevice = RamdiskAddDevice;
2344 DriverObject->DriverUnload = RamdiskUnload;
2345
2346 //
2347 // Check for a loader block
2348 //
2349 if (KeLoaderBlock)
2350 {
2351 //
2352 // Get the boot device name
2353 //
2354 BootDeviceName = KeLoaderBlock->ArcBootDeviceName;
2355 if (BootDeviceName)
2356 {
2357 //
2358 // Check if we're booting from ramdisk
2359 //
2360 if ((strlen(BootDeviceName) >= 10) &&
2361 !(_strnicmp(BootDeviceName, "ramdisk(0)", 10)))
2362 {
2363 //
2364 // We'll have to tell the PnP Manager
2365 //
2366 ReportDetectedDevice = TRUE;
2367
2368 //
2369 // Check for a command line
2370 //
2371 CommandLine = KeLoaderBlock->LoadOptions;
2372 if (CommandLine)
2373 {
2374 //
2375 // Check if this is an ISO boot
2376 //
2377 if (strstr(CommandLine, "RDEXPORTASCD"))
2378 {
2379 //
2380 // Remember for later
2381 //
2382 ExportBootDiskAsCd = TRUE;
2383 }
2384
2385 //
2386 // Check if this is PE boot
2387 //
2388 if (strstr(CommandLine, "MININT"))
2389 {
2390 //
2391 // Remember for later
2392 //
2393 IsWinPEBoot = TRUE;
2394 }
2395 }
2396 }
2397
2398 }
2399 }
2400
2401 //
2402 // Installing from Ramdisk isn't supported yet
2403 //
2404 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
2405
2406 //
2407 // Are we reporting the device
2408 //
2409 if (ReportDetectedDevice)
2410 {
2411 //
2412 // Do it
2413 //
2414 Status = IoReportDetectedDevice(DriverObject,
2415 InterfaceTypeUndefined,
2416 0xFFFFFFFF,
2417 0xFFFFFFFF,
2418 NULL,
2419 NULL,
2420 0,
2421 &PhysicalDeviceObject);
2422 if (NT_SUCCESS(Status))
2423 {
2424 //
2425 // ReactOS Fix
2426 // The ReactOS Plug and Play Manager is broken and does not create
2427 // the required keys when reporting a detected device.
2428 // We hack around this ourselves.
2429 //
2430 RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION)
2431 PhysicalDeviceObject->DeviceObjectExtension)
2432 ->DeviceNode->InstancePath,
2433 L"Root\\UNKNOWN\\0000");
2434
2435 //
2436 // Create the device object
2437 //
2438 Status = RamdiskAddDevice(DriverObject, PhysicalDeviceObject);
2439 if (NT_SUCCESS(Status))
2440 {
2441 //
2442 // We're done
2443 //
2444 PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
2445 Status = STATUS_SUCCESS;
2446 }
2447 }
2448 }
2449 else
2450 {
2451 //
2452 // Done
2453 //
2454 Status = STATUS_SUCCESS;
2455 }
2456
2457 //
2458 // Done
2459 //
2460 return Status;
2461 }