sync with trunk head (34904)
[reactos.git] / reactos / drivers / storage / class / ramdisk / ramdisk.c
1 /*
2 * PROJECT: Ramdisk Class Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/storage/class/ramdisk/ramdisk.c
5 * PURPOSE: Main Driver Routines
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <initguid.h>
12 #include <ntddk.h>
13 #include <ntdddisk.h>
14 #include <ntddcdrm.h>
15 #include <scsi.h>
16 #include <ntddscsi.h>
17 #include <ntddvol.h>
18 #include <mountdev.h>
19 #include <mountmgr.h>
20 #include <helper.h>
21 #include <ketypes.h>
22 #include <iotypes.h>
23 #include <rtlfuncs.h>
24 #include <arc/arc.h>
25 #include <reactos/drivers/ntddrdsk.h>
26 #include "../../../filesystems/fs_rec/fs_rec.h"
27 #include <stdio.h>
28 #define NDEBUG
29 #include <debug.h>
30
31 /* GLOBALS ********************************************************************/
32
33 #define RAMDISK_SESSION_SIZE \
34 FIELD_OFFSET(CDROM_TOC, TrackData) + sizeof(TRACK_DATA)
35
36 #define RAMDISK_TOC_SIZE \
37 FIELD_OFFSET(CDROM_TOC, TrackData) + 2 * sizeof(TRACK_DATA)
38
39 #define TOC_DATA_TRACK (0x04)
40
41 typedef enum _RAMDISK_DEVICE_TYPE
42 {
43 RamdiskBus,
44 RamdiskDrive
45 } RAMDISK_DEVICE_TYPE;
46
47 typedef enum _RAMDISK_DEVICE_STATE
48 {
49 RamdiskStateUninitialized,
50 RamdiskStateStarted,
51 RamdiskStatePaused,
52 RamdiskStateStopped,
53 RamdiskStateRemoved,
54 RamdiskStateBusRemoved,
55 RamdiskStateEnumerated,
56 } RAMDISK_DEVICE_STATE;
57
58 DEFINE_GUID(RamdiskBusInterface,
59 0x5DC52DF0,
60 0x2F8A,
61 0x410F,
62 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
63
64 typedef struct _RAMDISK_EXTENSION
65 {
66 RAMDISK_DEVICE_TYPE Type;
67 RAMDISK_DEVICE_STATE State;
68 PDEVICE_OBJECT DeviceObject;
69 PDEVICE_OBJECT PhysicalDeviceObject;
70 PDEVICE_OBJECT AttachedDevice;
71 IO_REMOVE_LOCK RemoveLock;
72 UNICODE_STRING DriveDeviceName;
73 UNICODE_STRING BusDeviceName;
74 FAST_MUTEX DiskListLock;
75 LIST_ENTRY DiskList;
76 } RAMDISK_EXTENSION, *PRAMDISK_EXTENSION;
77
78 typedef struct _RAMDISK_BUS_EXTENSION
79 {
80 RAMDISK_EXTENSION;
81 } RAMDISK_BUS_EXTENSION, *PRAMDISK_BUS_EXTENSION;
82
83 typedef struct _RAMDISK_DRIVE_EXTENSION
84 {
85 //
86 // Inherited base class
87 //
88 RAMDISK_EXTENSION;
89
90 //
91 // Data we get from the creator
92 //
93 GUID DiskGuid;
94 UNICODE_STRING GuidString;
95 UNICODE_STRING SymbolicLinkName;
96 ULONG DiskType;
97 RAMDISK_CREATE_OPTIONS DiskOptions;
98 LARGE_INTEGER DiskLength;
99 LONG DiskOffset;
100 WCHAR DriveLetter;
101 ULONG BasePage;
102
103 //
104 // Data we get from the disk
105 //
106 ULONG BytesPerSector;
107 ULONG SectorsPerTrack;
108 ULONG NumberOfHeads;
109 ULONG Cylinders;
110 ULONG HiddenSectors;
111 } RAMDISK_DRIVE_EXTENSION, *PRAMDISK_DRIVE_EXTENSION;
112
113 ULONG MaximumViewLength;
114 ULONG MaximumPerDiskViewLength;
115 ULONG ReportDetectedDevice;
116 ULONG MarkRamdisksAsRemovable;
117 ULONG MinimumViewCount;
118 ULONG DefaultViewCount;
119 ULONG MaximumViewCount;
120 ULONG MinimumViewLength;
121 ULONG DefaultViewLength;
122 UNICODE_STRING DriverRegistryPath;
123 BOOLEAN ExportBootDiskAsCd;
124 BOOLEAN IsWinPEBoot;
125 PDEVICE_OBJECT RamdiskBusFdo;
126
127 /* FUNCTIONS ******************************************************************/
128
129 VOID
130 NTAPI
131 QueryParameters(IN PUNICODE_STRING RegistryPath)
132 {
133 ULONG MinView, DefView, MinViewLength, DefViewLength, MaxViewLength;
134 RTL_QUERY_REGISTRY_TABLE QueryTable[10];
135
136 //
137 // Set defaults
138 //
139 MaximumViewLength = 0x10000000u;
140 MaximumPerDiskViewLength = 0x10000000u;
141 ReportDetectedDevice = 0;
142 MarkRamdisksAsRemovable = 0;
143 MinimumViewCount = 2;
144 DefaultViewCount = 16;
145 MaximumViewCount = 64;
146 MinimumViewLength = 0x10000u;
147 DefaultViewLength = 0x100000u;
148
149 //
150 // Setup the query table and query the registry
151 //
152 RtlZeroMemory(QueryTable, sizeof(QueryTable));
153 QueryTable[0].Flags = 1;
154 QueryTable[0].Name = L"Parameters";
155 QueryTable[1].Flags = 32;
156 QueryTable[1].Name = L"ReportDetectedDevice";
157 QueryTable[1].EntryContext = &ReportDetectedDevice;
158 QueryTable[2].Flags = 32;
159 QueryTable[2].Name = L"MarkRamdisksAsRemovable";
160 QueryTable[2].EntryContext = &MarkRamdisksAsRemovable;
161 QueryTable[3].Flags = 32;
162 QueryTable[3].Name = L"MinimumViewCount";
163 QueryTable[3].EntryContext = &MinimumViewCount;
164 QueryTable[4].Flags = 32;
165 QueryTable[4].Name = L"DefaultViewCount";
166 QueryTable[4].EntryContext = &DefaultViewCount;
167 QueryTable[5].Flags = 32;
168 QueryTable[5].Name = L"MaximumViewCount";
169 QueryTable[5].EntryContext = &MaximumViewCount;
170 QueryTable[6].Flags = 32;
171 QueryTable[6].Name = L"MinimumViewLength";
172 QueryTable[6].EntryContext = &MinimumViewLength;
173 QueryTable[7].Flags = 32;
174 QueryTable[7].Name = L"DefaultViewLength";
175 QueryTable[7].EntryContext = &DefaultViewLength;
176 QueryTable[8].Flags = 32;
177 QueryTable[8].Name = L"MaximumViewLength";
178 QueryTable[8].EntryContext = &MaximumViewLength;
179 QueryTable[9].Flags = 32;
180 QueryTable[9].Name = L"MaximumPerDiskViewLength";
181 QueryTable[9].EntryContext = &MaximumPerDiskViewLength;
182 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL,
183 RegistryPath->Buffer,
184 QueryTable,
185 NULL,
186 NULL);
187
188 //
189 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
190 //
191 MinView = MinimumViewCount;
192 if (MinimumViewCount >= 2)
193 {
194 if (MinimumViewCount > 256) MinView = 256;
195 }
196 else
197 {
198 MinView = 2;
199 }
200 MinimumViewCount = MinView;
201
202 //
203 // Parse default view count, cannot be bigger than 256 or smaller than minimum
204 //
205 DefView = DefaultViewCount;
206 if (DefaultViewCount >= MinView)
207 {
208 if (DefaultViewCount > 256) DefView = 256;
209 }
210 else
211 {
212 DefView = MinView;
213 }
214 DefaultViewCount = DefView;
215
216 //
217 // Parse maximum view count, cannot be bigger than 256 or smaller than default
218 //
219 if (MaximumViewCount >= DefView)
220 {
221 if (MaximumViewCount > 256) MaximumViewCount = 256;
222 }
223 else
224 {
225 MaximumViewCount = DefView;
226 }
227
228 //
229 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
230 //
231 MinViewLength = MinimumViewLength;
232 if (MinimumViewLength >= 0x10000)
233 {
234 if (MinimumViewLength > 0x40000000) MinViewLength = 0x40000000u;
235 }
236 else
237 {
238 MinViewLength = 0x10000u;
239 }
240 MinimumViewLength = MinViewLength;
241
242 //
243 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
244 //
245 DefViewLength = DefaultViewLength;
246 if (DefaultViewLength >= MinViewLength)
247 {
248 if (DefaultViewLength > 0x40000000) DefViewLength = 0x40000000u;
249 }
250 else
251 {
252 DefViewLength = MinViewLength;
253 }
254 DefaultViewLength = DefViewLength;
255
256 //
257 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
258 //
259 MaxViewLength = MaximumViewLength;
260 if (MaximumViewLength >= DefViewLength)
261 {
262 if (MaximumViewLength > 0x40000000) MaxViewLength = 0x40000000u;
263 }
264 else
265 {
266 MaxViewLength = DefViewLength;
267 }
268 MaximumViewLength = MaxViewLength;
269
270 //
271 // Parse maximum view length per disk, cannot be smaller than 16MB
272 //
273 if (MaximumPerDiskViewLength >= 0x1000000)
274 {
275 if (MaxViewLength > 0xFFFFFFFF) MaximumPerDiskViewLength = -1;
276 }
277 else
278 {
279 MaximumPerDiskViewLength = 0x1000000u;
280 }
281 }
282
283 PVOID
284 NTAPI
285 RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
286 IN LARGE_INTEGER Offset,
287 IN ULONG Length,
288 OUT PULONG OutputLength)
289 {
290 PHYSICAL_ADDRESS PhysicalAddress;
291 PVOID MappedBase;
292 ULONG PageOffset;
293 SIZE_T ActualLength;
294 LARGE_INTEGER ActualOffset;
295 LARGE_INTEGER ActualPages;
296
297 //
298 // We only support boot disks for now
299 //
300 ASSERT(DeviceExtension->DiskType == RAMDISK_BOOT_DISK);
301
302 //
303 // Calculate the actual offset in the drive
304 //
305 ActualOffset.QuadPart = DeviceExtension->DiskOffset + Offset.QuadPart;
306
307 //
308 // Convert to pages
309 //
310 ActualPages.QuadPart = ActualOffset.QuadPart >> PAGE_SHIFT;
311
312 //
313 // Now add the base page
314 //
315 ActualPages.QuadPart = DeviceExtension->BasePage + ActualPages.QuadPart;
316
317 //
318 // Calculate final amount of bytes
319 //
320 PhysicalAddress.QuadPart = ActualPages.QuadPart << PAGE_SHIFT;
321
322 //
323 // Calculate pages spanned for the mapping
324 //
325 ActualLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset.QuadPart, Length);
326
327 //
328 // And convert this back to bytes
329 //
330 ActualLength <<= PAGE_SHIFT;
331
332 //
333 // Get the offset within the page
334 //
335 PageOffset = BYTE_OFFSET(ActualOffset.QuadPart);
336
337 //
338 // Map the I/O Space from the loader
339 //
340 MappedBase = MmMapIoSpace(PhysicalAddress, ActualLength, MmCached);
341
342 //
343 // Return actual offset within the page as well as the length
344 //
345 if (MappedBase) MappedBase = (PVOID)((ULONG_PTR)MappedBase + PageOffset);
346 *OutputLength = Length;
347 return MappedBase;
348 }
349
350 VOID
351 NTAPI
352 RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
353 IN PVOID BaseAddress,
354 IN LARGE_INTEGER Offset,
355 IN ULONG Length)
356 {
357 LARGE_INTEGER ActualOffset;
358 SIZE_T ActualLength;
359 ULONG PageOffset;
360
361 //
362 // We only support boot disks for now
363 //
364 ASSERT(DeviceExtension->DiskType == RAMDISK_BOOT_DISK);
365
366 //
367 // Calculate the actual offset in the drive
368 //
369 ActualOffset.QuadPart = DeviceExtension->DiskOffset + Offset.QuadPart;
370
371 //
372 // Calculate pages spanned for the mapping
373 //
374 ActualLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset.QuadPart, Length);
375
376 //
377 // And convert this back to bytes
378 //
379 ActualLength <<= PAGE_SHIFT;
380
381 //
382 // Get the offset within the page
383 //
384 PageOffset = BYTE_OFFSET(ActualOffset.QuadPart);
385
386 //
387 // Calculate actual base address where we mapped this
388 //
389 BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - PageOffset);
390
391 //
392 // Unmap the I/O space we got from the loader
393 //
394 MmUnmapIoSpace(BaseAddress, ActualLength);
395 }
396
397 NTSTATUS
398 NTAPI
399 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension,
400 IN PRAMDISK_CREATE_INPUT Input,
401 IN BOOLEAN ValidateOnly,
402 OUT PRAMDISK_DRIVE_EXTENSION *NewDriveExtension)
403 {
404 ULONG BasePage, ViewCount, DiskType, Length;
405 NTSTATUS Status;
406 PDEVICE_OBJECT DeviceObject;
407 PRAMDISK_DRIVE_EXTENSION DriveExtension;
408 PVOID Buffer;
409 WCHAR LocalBuffer[16];
410 UNICODE_STRING SymbolicLinkName, DriveString, GuidString, DeviceName;
411 PPACKED_BOOT_SECTOR BootSector;
412 BIOS_PARAMETER_BLOCK BiosBlock;
413 ULONG BytesPerSector, SectorsPerTrack, Heads, BytesRead;
414 PVOID BaseAddress;
415 LARGE_INTEGER CurrentOffset, CylinderSize, DiskLength;
416 ULONG CylinderCount, SizeByCylinders;
417
418 //
419 // Check if we're a boot RAM disk
420 //
421 DiskType = Input->DiskType;
422 if (DiskType >= RAMDISK_BOOT_DISK)
423 {
424 //
425 // Check if we're an ISO
426 //
427 if (DiskType == RAMDISK_BOOT_DISK)
428 {
429 //
430 // NTLDR mounted us somewhere
431 //
432 BasePage = Input->BasePage;
433 if (!BasePage) return STATUS_INVALID_PARAMETER;
434
435 //
436 // Sanitize disk options
437 //
438 Input->Options.Fixed = TRUE;
439 Input->Options.Readonly = Input->Options.ExportAsCd |
440 Input->Options.Readonly;
441 Input->Options.Hidden = FALSE;
442 Input->Options.NoDosDevice = FALSE;
443 Input->Options.NoDriveLetter = IsWinPEBoot ? TRUE : FALSE;
444 }
445 else
446 {
447 //
448 // The only other possibility is a WIM disk
449 //
450 if (DiskType != RAMDISK_WIM_DISK)
451 {
452 //
453 // Fail
454 //
455 return STATUS_INVALID_PARAMETER;
456 }
457
458 //
459 // Read the view count instead
460 //
461 ViewCount = Input->ViewCount;
462
463 //
464 // Sanitize disk options
465 //
466 Input->Options.Hidden = FALSE;
467 Input->Options.NoDosDevice = FALSE;
468 Input->Options.Readonly = FALSE;
469 Input->Options.NoDriveLetter = TRUE;
470 Input->Options.Fixed = TRUE;
471 }
472
473 //
474 // Are we just validating and returning to the user?
475 //
476 if (ValidateOnly) return STATUS_SUCCESS;
477
478 //
479 // Build the GUID string
480 //
481 Status = RtlStringFromGUID(&Input->DiskGuid, &GuidString);
482 if (!(NT_SUCCESS(Status)) || !(GuidString.Buffer))
483 {
484 //
485 // Fail
486 //
487 Status = STATUS_INSUFFICIENT_RESOURCES;
488 goto FailCreate;
489 }
490
491 //
492 // Allocate our device name
493 //
494 Length = GuidString.Length + 32;
495 Buffer = ExAllocatePoolWithTag(NonPagedPool,
496 Length,
497 TAG('R', 'a', 'm', 'd'));
498 if (!Buffer)
499 {
500 //
501 // Fail
502 //
503 Status = STATUS_INSUFFICIENT_RESOURCES;
504 goto FailCreate;
505 }
506
507 //
508 // Build the device name string
509 //
510 DeviceName.Buffer = Buffer;
511 DeviceName.Length = Length - 2;
512 DeviceName.MaximumLength = Length;
513 wcsncpy(Buffer, L"\\Device\\Ramdisk", Length / sizeof(WCHAR));
514 wcsncat(Buffer, GuidString.Buffer, Length / sizeof(WCHAR));
515
516 //
517 // Create the drive device
518 //
519 Status = IoCreateDevice(DeviceExtension->DeviceObject->DriverObject,
520 sizeof(RAMDISK_DRIVE_EXTENSION),
521 &DeviceName,
522 (Input->Options.ExportAsCd) ?
523 FILE_DEVICE_CD_ROM : FILE_DEVICE_DISK,
524 0,
525 0,
526 &DeviceObject);
527 if (!NT_SUCCESS(Status)) goto FailCreate;
528
529 //
530 // Grab the drive extension
531 //
532 DriveExtension = DeviceObject->DeviceExtension;
533
534 //
535 // Check if we need a DOS device
536 //
537 if (!Input->Options.NoDosDevice)
538 {
539 //
540 // Build the symbolic link name
541 //
542 SymbolicLinkName.MaximumLength = GuidString.Length + 36;
543 SymbolicLinkName.Length = GuidString.Length + 34;
544 Buffer = ExAllocatePoolWithTag(NonPagedPool,
545 SymbolicLinkName.MaximumLength,
546 TAG('R', 'a', 'm', 'd'));
547 SymbolicLinkName.Buffer = Buffer;
548 if (Buffer)
549 {
550 //
551 // Create it
552 //
553 wcsncpy(Buffer,
554 L"\\GLOBAL??\\Ramdisk",
555 SymbolicLinkName.MaximumLength / sizeof(WCHAR));
556 wcsncat(Buffer,
557 GuidString.Buffer,
558 SymbolicLinkName.MaximumLength / sizeof(WCHAR));
559 Status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
560 if (!NT_SUCCESS(Status))
561 {
562 //
563 // Nevermind...
564 //
565 Input->Options.NoDosDevice = TRUE;
566 ExFreePool(Buffer);
567 SymbolicLinkName.Buffer = NULL;
568 }
569 }
570 else
571 {
572 //
573 // No DOS device
574 //
575 Input->Options.NoDosDevice = TRUE;
576 }
577
578 //
579 // It this an ISO boot ramdisk?
580 //
581 if (Input->DiskType == RAMDISK_BOOT_DISK)
582 {
583 //
584 // Does it need a drive letter?
585 //
586 if (!Input->Options.NoDriveLetter)
587 {
588 //
589 // Build it and take over the existing symbolic link
590 //
591 _snwprintf(LocalBuffer,
592 30,
593 L"\\DosDevices\\%wc:",
594 Input->DriveLetter);
595 RtlInitUnicodeString(&DriveString, LocalBuffer);
596 IoDeleteSymbolicLink(&DriveString);
597 IoCreateSymbolicLink(&DriveString, &DeviceName);
598
599 //
600 // Save the drive letter
601 //
602 DriveExtension->DriveLetter = Input->DriveLetter;
603 }
604 }
605
606 }
607
608 //
609 // Setup the device object flags
610 //
611 DeviceObject->Flags |= (DO_XIP | DO_POWER_PAGABLE | DO_DIRECT_IO);
612 DeviceObject->AlignmentRequirement = 1;
613
614 //
615 // Build the drive FDO
616 //
617 *NewDriveExtension = DriveExtension;
618 DriveExtension->Type = RamdiskDrive;
619 DiskLength = Input->DiskLength;
620 ExInitializeFastMutex(&DriveExtension->DiskListLock);
621 IoInitializeRemoveLock(&DriveExtension->RemoveLock,
622 TAG('R', 'a', 'm', 'd'),
623 0,
624 1);
625 DriveExtension->DriveDeviceName = DeviceName;
626 DriveExtension->SymbolicLinkName = SymbolicLinkName;
627 DriveExtension->GuidString = GuidString;
628 DriveExtension->DiskGuid = Input->DiskGuid;
629 DriveExtension->PhysicalDeviceObject = DeviceObject;
630 DriveExtension->DeviceObject = RamdiskBusFdo;
631 DriveExtension->AttachedDevice = RamdiskBusFdo;
632 DriveExtension->DiskType = Input->DiskType;
633 DriveExtension->DiskOptions = Input->Options;
634 DriveExtension->DiskLength = DiskLength;
635 DriveExtension->DiskOffset = Input->DiskOffset;
636 DriveExtension->BasePage = Input->BasePage;
637 DriveExtension->BytesPerSector = 0;
638 DriveExtension->SectorsPerTrack = 0;
639 DriveExtension->NumberOfHeads = 0;
640
641 //
642 // Make sure we don't free it later
643 //
644 DeviceName.Buffer = NULL;
645 SymbolicLinkName.Buffer = NULL;
646 GuidString.Buffer = NULL;
647
648 //
649 // Check if this is an boot disk, or a registry ram drive
650 //
651 if (!(Input->Options.ExportAsCd) &&
652 (Input->DiskType == RAMDISK_BOOT_DISK))
653 {
654 //
655 // Not an ISO boot, but it's a boot FS -- map it to figure out the
656 // drive settings
657 //
658 CurrentOffset.QuadPart = 0;
659 BaseAddress = RamdiskMapPages(DriveExtension,
660 CurrentOffset,
661 PAGE_SIZE,
662 &BytesRead);
663 if (BaseAddress)
664 {
665 //
666 // Get the data
667 //
668 BootSector = (PPACKED_BOOT_SECTOR)BaseAddress;
669 FatUnpackBios(&BiosBlock, &BootSector->PackedBpb);
670 BytesPerSector = BiosBlock.BytesPerSector;
671 SectorsPerTrack = BiosBlock.SectorsPerTrack;
672 Heads = BiosBlock.Heads;
673
674 //
675 // Save it
676 //
677 DriveExtension->BytesPerSector = BytesPerSector;
678 DriveExtension->SectorsPerTrack = SectorsPerTrack;
679 DriveExtension->NumberOfHeads = Heads;
680
681 //
682 // Unmap now
683 //
684 CurrentOffset.QuadPart = 0;
685 RamdiskUnmapPages(DriveExtension,
686 BaseAddress,
687 CurrentOffset,
688 BytesRead);
689 }
690 else
691 {
692 //
693 // Fail
694 //
695 Status = STATUS_INSUFFICIENT_RESOURCES;
696 goto FailCreate;
697 }
698 }
699
700 //
701 // Check if the drive settings haven't been set yet
702 //
703 if ((DriveExtension->BytesPerSector == 0) ||
704 (DriveExtension->SectorsPerTrack == 0) ||
705 (DriveExtension->NumberOfHeads == 0))
706 {
707 //
708 // Check if this is a CD
709 //
710 if (Input->Options.ExportAsCd)
711 {
712 //
713 // Setup partition parameters default for ISO 9660
714 //
715 DriveExtension->BytesPerSector = 2048;
716 DriveExtension->SectorsPerTrack = 32;
717 DriveExtension->NumberOfHeads = 64;
718 }
719 else
720 {
721 //
722 // Setup partition parameters default for FAT
723 //
724 DriveExtension->BytesPerSector = 512;
725 DriveExtension->SectorsPerTrack = 128;
726 DriveExtension->NumberOfHeads = 16;
727 }
728 }
729
730 //
731 // Calculate the cylinder size
732 //
733 CylinderSize.QuadPart = DriveExtension->BytesPerSector *
734 DriveExtension->SectorsPerTrack *
735 DriveExtension->NumberOfHeads;
736 CylinderCount = DiskLength.QuadPart / CylinderSize.QuadPart;
737 SizeByCylinders = CylinderSize.QuadPart * CylinderCount;
738 DriveExtension->Cylinders = CylinderCount;
739 if ((DiskLength.HighPart > 0) || (SizeByCylinders < DiskLength.LowPart))
740 {
741 //
742 // Align cylinder size up
743 //
744 DriveExtension->Cylinders++;
745 }
746
747 //
748 // Acquire the disk lock
749 //
750 KeEnterCriticalRegion();
751 ExAcquireFastMutex(&DeviceExtension->DiskListLock);
752
753 //
754 // Insert us
755 //
756 InsertTailList(&DeviceExtension->DiskList, &DriveExtension->DiskList);
757
758 //
759 // Release the lock
760 //
761 ExReleaseFastMutex(&DeviceExtension->DiskListLock);
762 KeLeaveCriticalRegion();
763
764 //
765 // Clear init flag
766 //
767 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
768 return STATUS_SUCCESS;
769 }
770
771 FailCreate:
772 UNIMPLEMENTED;
773 while (TRUE);
774 return STATUS_SUCCESS;
775 }
776
777 NTSTATUS
778 NTAPI
779 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject,
780 IN PIRP Irp,
781 IN BOOLEAN ValidateOnly)
782 {
783 PRAMDISK_CREATE_INPUT Input;
784 ULONG Length;
785 PRAMDISK_BUS_EXTENSION DeviceExtension;
786 PRAMDISK_DRIVE_EXTENSION DriveExtension;
787 ULONG DiskType;
788 PWCHAR FileNameStart, FileNameEnd;
789 NTSTATUS Status;
790 PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
791
792 //
793 // Get the device extension and our input data
794 //
795 DeviceExtension = DeviceObject->DeviceExtension;
796 Length = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
797 Input = (PRAMDISK_CREATE_INPUT)Irp->AssociatedIrp.SystemBuffer;
798
799 //
800 // Validate input parameters
801 //
802 if ((Length < sizeof(RAMDISK_CREATE_INPUT)) ||
803 (Input->Version != sizeof(RAMDISK_CREATE_INPUT)))
804 {
805 //
806 // Invalid input
807 //
808 return STATUS_INVALID_PARAMETER;
809 }
810
811 //
812 // Validate the disk type
813 //
814 DiskType = Input->DiskType;
815 if (DiskType == RAMDISK_WIM_DISK) return STATUS_INVALID_PARAMETER;
816
817 //
818 // Look at the disk type
819 //
820 if (DiskType == RAMDISK_BOOT_DISK)
821 {
822 //
823 // We only allow this as an early-init boot
824 //
825 if (!KeLoaderBlock) return STATUS_INVALID_PARAMETER;
826
827 //
828 // Save command-line flags
829 //
830 if (ExportBootDiskAsCd) Input->Options.ExportAsCd = TRUE;
831 if (IsWinPEBoot) Input->Options.NoDriveLetter = TRUE;
832 }
833
834 //
835 // Validate the disk type
836 //
837 if ((Input->Options.ExportAsCd) && (DiskType != RAMDISK_BOOT_DISK))
838 {
839 //
840 // If the type isn't CDFS, it has to at least be raw CD
841 //
842 if (DiskType != RAMDISK_MEMORY_MAPPED_DISK) return STATUS_INVALID_PARAMETER;
843 }
844
845 //
846 // Check if this is an actual file
847 //
848 if (DiskType <= RAMDISK_MEMORY_MAPPED_DISK)
849 {
850 //
851 // Validate the file name
852 //
853 FileNameStart = (PWCHAR)((ULONG_PTR)Input + Length);
854 FileNameEnd = Input->FileName + 1;
855 while ((FileNameEnd < FileNameStart) && *(FileNameEnd)) FileNameEnd++;
856 if (FileNameEnd == FileNameStart) return STATUS_INVALID_PARAMETER;
857 }
858
859 //
860 // Create the actual device
861 //
862 Status = RamdiskCreateDiskDevice(DeviceExtension,
863 Input,
864 ValidateOnly,
865 &DriveExtension);
866 if (NT_SUCCESS(Status))
867 {
868 //
869 // Invalidate and set success
870 //
871 IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, 0);
872 Irp->IoStatus.Information = STATUS_SUCCESS;
873 }
874
875 //
876 // We're done
877 //
878 return Status;
879 }
880
881 VOID
882 NTAPI
883 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject,
884 IN PVOID Context)
885 {
886 PRAMDISK_BUS_EXTENSION DeviceExtension;
887 NTSTATUS Status;
888 PIO_STACK_LOCATION IoStackLocation;
889 PIRP Irp = Context;
890
891 //
892 // Get the stack location
893 //
894 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
895
896 //
897 // Free the work item
898 //
899 IoFreeWorkItem(Irp->Tail.Overlay.DriverContext[0]);
900
901 //
902 // Grab the device extension and lock it
903 //
904 DeviceExtension = DeviceObject->DeviceExtension;
905 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
906 if (NT_SUCCESS(Status))
907 {
908 //
909 // Discriminate by major code
910 //
911 switch (IoStackLocation->MajorFunction)
912 {
913 //
914 // Device control
915 //
916 case IRP_MJ_DEVICE_CONTROL:
917
918 //
919 // Let's take a look at the IOCTL
920 //
921 switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
922 {
923 //
924 // Ramdisk create request
925 //
926 case FSCTL_CREATE_RAM_DISK:
927
928 //
929 // This time we'll do it for real
930 //
931 Status = RamdiskCreateRamdisk(DeviceObject, Irp, FALSE);
932 break;
933
934 case IOCTL_DISK_SET_PARTITION_INFO:
935
936 DPRINT1("Set partition info request\n");
937 UNIMPLEMENTED;
938 while (TRUE);
939 break;
940
941 case IOCTL_DISK_GET_DRIVE_LAYOUT:
942
943 DPRINT1("Get drive layout request\n");
944 UNIMPLEMENTED;
945 while (TRUE);
946 break;
947
948 case IOCTL_DISK_GET_PARTITION_INFO:
949
950 DPRINT1("Get partitinon info request\n");
951 UNIMPLEMENTED;
952 while (TRUE);
953 break;
954
955 default:
956
957 DPRINT1("Invalid request\n");
958 UNIMPLEMENTED;
959 while (TRUE);
960 break;
961 }
962
963 //
964 // We're here
965 //
966 break;
967
968 //
969 // Read or write request
970 //
971 case IRP_MJ_READ:
972 case IRP_MJ_WRITE:
973
974 DPRINT1("Read/Write request\n");
975 UNIMPLEMENTED;
976 while (TRUE);
977 break;
978
979 //
980 // Internal request (SCSI?)
981 //
982 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
983
984 DPRINT1("SCSI request\n");
985 UNIMPLEMENTED;
986 while (TRUE);
987 break;
988
989 //
990 // Flush request
991 //
992 case IRP_MJ_FLUSH_BUFFERS:
993
994 DPRINT1("Flush request\n");
995 UNIMPLEMENTED;
996 while (TRUE);
997 break;
998
999 //
1000 // Anything else
1001 //
1002 default:
1003
1004 DPRINT1("Invalid request: %lx\n", IoStackLocation->MajorFunction);
1005 UNIMPLEMENTED;
1006 while (TRUE);
1007 break;
1008 }
1009
1010 //
1011 // Complete the I/O
1012 //
1013 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
1014 Irp->IoStatus.Status = Status;
1015 Irp->IoStatus.Information = 0;
1016 return IoCompleteRequest(Irp, IO_DISK_INCREMENT);
1017 }
1018
1019 //
1020 // Fail the I/O
1021 //
1022 Irp->IoStatus.Status = Status;
1023 Irp->IoStatus.Information = 0;
1024 return 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}};
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 TAG('R', 'a', 'm', 'd'));
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 TAG('R', 'a', 'm', 'd'),
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
2312 //
2313 // Query ramdisk parameters
2314 //
2315 QueryParameters(RegistryPath);
2316
2317 //
2318 // Save the registry path
2319 //
2320 DriverRegistryPath = *RegistryPath;
2321 DriverRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
2322 RegistryPath->Length +
2323 sizeof(WCHAR),
2324 TAG('R', 'a', 'm', 'd'));
2325 if (!DriverRegistryPath.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
2326 RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath);
2327
2328 //
2329 // Set device routines
2330 //
2331 DriverObject->MajorFunction[IRP_MJ_CREATE] = RamdiskOpenClose;
2332 DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamdiskOpenClose;
2333 DriverObject->MajorFunction[IRP_MJ_READ] = RamdiskReadWrite;
2334 DriverObject->MajorFunction[IRP_MJ_WRITE] = RamdiskReadWrite;
2335 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamdiskDeviceControl;
2336 DriverObject->MajorFunction[IRP_MJ_PNP] = RamdiskPnp;
2337 DriverObject->MajorFunction[IRP_MJ_POWER] = RamdiskPower;
2338 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamdiskSystemControl;
2339 DriverObject->MajorFunction[IRP_MJ_SCSI] = RamdiskScsi;
2340 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = RamdiskFlushBuffers;
2341 DriverObject->DriverExtension->AddDevice = RamdiskAddDevice;
2342 DriverObject->DriverUnload = RamdiskUnload;
2343
2344 //
2345 // Check for a loader block
2346 //
2347 if (KeLoaderBlock)
2348 {
2349 //
2350 // Get the boot device name
2351 //
2352 BootDeviceName = KeLoaderBlock->ArcBootDeviceName;
2353 if (BootDeviceName)
2354 {
2355 //
2356 // Check if we're booting from ramdisk
2357 //
2358 if ((strlen(BootDeviceName) >= 10) &&
2359 !(_strnicmp(BootDeviceName, "ramdisk(0)", 10)))
2360 {
2361 //
2362 // We'll have to tell the PnP Manager
2363 //
2364 ReportDetectedDevice = TRUE;
2365
2366 //
2367 // Check for a command line
2368 //
2369 CommandLine = KeLoaderBlock->LoadOptions;
2370 if (CommandLine)
2371 {
2372 //
2373 // Check if this is an ISO boot
2374 //
2375 if (strstr(CommandLine, "RDEXPORTASCD"))
2376 {
2377 //
2378 // Remember for later
2379 //
2380 ExportBootDiskAsCd = TRUE;
2381 }
2382
2383 //
2384 // Check if this is PE boot
2385 //
2386 if (strstr(CommandLine, "MININT"))
2387 {
2388 //
2389 // Remember for later
2390 //
2391 IsWinPEBoot = TRUE;
2392 }
2393 }
2394 }
2395
2396 }
2397 }
2398
2399 //
2400 // Installing from Ramdisk isn't supported yet
2401 //
2402 ASSERT(!KeLoaderBlock->SetupLdrBlock);
2403
2404 //
2405 // Are we reporting the device
2406 //
2407 if (ReportDetectedDevice)
2408 {
2409 //
2410 // Do it
2411 //
2412 Status = IoReportDetectedDevice(DriverObject,
2413 InterfaceTypeUndefined,
2414 0xFFFFFFFF,
2415 0xFFFFFFFF,
2416 NULL,
2417 NULL,
2418 0,
2419 &PhysicalDeviceObject);
2420 if (NT_SUCCESS(Status))
2421 {
2422 //
2423 // ReactOS Fix
2424 // The ReactOS Plug and Play Manager is broken and does not create
2425 // the required keys when reporting a detected device.
2426 // We hack around this ourselves.
2427 //
2428 RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION)
2429 PhysicalDeviceObject->DeviceObjectExtension)
2430 ->DeviceNode->InstancePath,
2431 L"Root\\UNKNOWN\\0000");
2432
2433 //
2434 // Create the device object
2435 //
2436 Status = RamdiskAddDevice(DriverObject, PhysicalDeviceObject);
2437 if (NT_SUCCESS(Status))
2438 {
2439 //
2440 // We're done
2441 //
2442 PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
2443 Status = STATUS_SUCCESS;
2444 }
2445 }
2446 }
2447 else
2448 {
2449 //
2450 // Done
2451 //
2452 Status = STATUS_SUCCESS;
2453 }
2454
2455 //
2456 // Done
2457 //
2458 return Status;
2459 }