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