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