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