ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ramdisk.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         Ramdisk Class Driver
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            drivers/storage/class/ramdisk/ramdisk.c
00005  * PURPOSE:         Main Driver Routines
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  */
00008 
00009 /* INCLUDES *******************************************************************/
00010 
00011 #include <initguid.h>
00012 #include <ntddk.h>
00013 #include <ntifs.h>
00014 #include <ntdddisk.h>
00015 #include <ntddcdrm.h>
00016 #include <scsi.h>
00017 #include <ntddscsi.h>
00018 #include <ntddvol.h>
00019 #include <mountdev.h>
00020 #include <mountmgr.h>
00021 #include <ketypes.h>
00022 #include <iotypes.h>
00023 #include <rtlfuncs.h>
00024 #include <arc/arc.h>
00025 #include <reactos/drivers/ntddrdsk.h>
00026 #include "../../../filesystems/fs_rec/fs_rec.h"
00027 #include <stdio.h>
00028 #define NDEBUG
00029 #include <debug.h>
00030 
00031 #define DO_XIP   0x00020000
00032 
00033 /* GLOBALS ********************************************************************/
00034 
00035 #define RAMDISK_SESSION_SIZE \
00036     FIELD_OFFSET(CDROM_TOC, TrackData) + sizeof(TRACK_DATA)
00037     
00038 #define RAMDISK_TOC_SIZE \
00039     FIELD_OFFSET(CDROM_TOC, TrackData) + 2 * sizeof(TRACK_DATA)
00040                                     
00041 #define TOC_DATA_TRACK              (0x04)
00042 
00043 typedef enum _RAMDISK_DEVICE_TYPE
00044 {
00045     RamdiskBus,
00046     RamdiskDrive
00047 } RAMDISK_DEVICE_TYPE;
00048 
00049 typedef enum _RAMDISK_DEVICE_STATE
00050 {
00051     RamdiskStateUninitialized,
00052     RamdiskStateStarted,
00053     RamdiskStatePaused,
00054     RamdiskStateStopped,
00055     RamdiskStateRemoved,
00056     RamdiskStateBusRemoved,
00057     RamdiskStateEnumerated,
00058 } RAMDISK_DEVICE_STATE;
00059 
00060 DEFINE_GUID(RamdiskBusInterface,
00061             0x5DC52DF0,
00062             0x2F8A,
00063             0x410F,
00064             0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
00065 
00066 typedef struct _RAMDISK_EXTENSION
00067 {
00068     RAMDISK_DEVICE_TYPE Type;
00069     RAMDISK_DEVICE_STATE State;
00070     PDEVICE_OBJECT DeviceObject;
00071     PDEVICE_OBJECT PhysicalDeviceObject;
00072     PDEVICE_OBJECT AttachedDevice;
00073     IO_REMOVE_LOCK RemoveLock;
00074     UNICODE_STRING DriveDeviceName;
00075     UNICODE_STRING BusDeviceName;
00076     FAST_MUTEX DiskListLock;
00077     LIST_ENTRY DiskList;
00078 } RAMDISK_EXTENSION, *PRAMDISK_EXTENSION;
00079 
00080 typedef struct _RAMDISK_BUS_EXTENSION
00081 {
00082     RAMDISK_EXTENSION;
00083 } RAMDISK_BUS_EXTENSION, *PRAMDISK_BUS_EXTENSION;
00084 
00085 typedef struct _RAMDISK_DRIVE_EXTENSION
00086 {
00087     //
00088     // Inherited base class
00089     //
00090     RAMDISK_EXTENSION;
00091     
00092     //
00093     // Data we get from the creator
00094     //
00095     GUID DiskGuid;
00096     UNICODE_STRING GuidString;
00097     UNICODE_STRING SymbolicLinkName;
00098     ULONG DiskType;
00099     RAMDISK_CREATE_OPTIONS DiskOptions;
00100     LARGE_INTEGER DiskLength;
00101     LONG DiskOffset;
00102     WCHAR DriveLetter;
00103     ULONG BasePage;
00104     
00105     //
00106     // Data we get from the disk
00107     //
00108     ULONG BytesPerSector;
00109     ULONG SectorsPerTrack;
00110     ULONG NumberOfHeads;
00111     ULONG Cylinders;
00112     ULONG HiddenSectors;
00113 } RAMDISK_DRIVE_EXTENSION, *PRAMDISK_DRIVE_EXTENSION;
00114 
00115 ULONG MaximumViewLength;
00116 ULONG MaximumPerDiskViewLength;
00117 ULONG ReportDetectedDevice;
00118 ULONG MarkRamdisksAsRemovable;
00119 ULONG MinimumViewCount;
00120 ULONG DefaultViewCount;
00121 ULONG MaximumViewCount;
00122 ULONG MinimumViewLength;
00123 ULONG DefaultViewLength;
00124 UNICODE_STRING DriverRegistryPath;
00125 BOOLEAN ExportBootDiskAsCd;
00126 BOOLEAN IsWinPEBoot;
00127 PDEVICE_OBJECT RamdiskBusFdo;
00128 
00129 /* FUNCTIONS ******************************************************************/
00130 
00131 VOID
00132 NTAPI
00133 QueryParameters(IN PUNICODE_STRING RegistryPath)
00134 {
00135     ULONG MinView, DefView, MinViewLength, DefViewLength, MaxViewLength;
00136     RTL_QUERY_REGISTRY_TABLE QueryTable[10];
00137     
00138     //
00139     // Set defaults
00140     //
00141     MaximumViewLength = 0x10000000u;
00142     MaximumPerDiskViewLength = 0x10000000u;
00143     ReportDetectedDevice = 0;
00144     MarkRamdisksAsRemovable = 0;
00145     MinimumViewCount = 2;
00146     DefaultViewCount = 16;
00147     MaximumViewCount = 64;
00148     MinimumViewLength = 0x10000u;
00149     DefaultViewLength = 0x100000u;
00150     
00151     //
00152     // Setup the query table and query the registry
00153     //
00154     RtlZeroMemory(QueryTable, sizeof(QueryTable));
00155     QueryTable[0].Flags = 1;
00156     QueryTable[0].Name = L"Parameters";
00157     QueryTable[1].Flags = 32;
00158     QueryTable[1].Name = L"ReportDetectedDevice";
00159     QueryTable[1].EntryContext = &ReportDetectedDevice;
00160     QueryTable[2].Flags = 32;
00161     QueryTable[2].Name = L"MarkRamdisksAsRemovable";
00162     QueryTable[2].EntryContext = &MarkRamdisksAsRemovable;
00163     QueryTable[3].Flags = 32;
00164     QueryTable[3].Name = L"MinimumViewCount";
00165     QueryTable[3].EntryContext = &MinimumViewCount;
00166     QueryTable[4].Flags = 32;
00167     QueryTable[4].Name = L"DefaultViewCount";
00168     QueryTable[4].EntryContext = &DefaultViewCount;
00169     QueryTable[5].Flags = 32;
00170     QueryTable[5].Name = L"MaximumViewCount";
00171     QueryTable[5].EntryContext = &MaximumViewCount;
00172     QueryTable[6].Flags = 32;
00173     QueryTable[6].Name = L"MinimumViewLength";
00174     QueryTable[6].EntryContext = &MinimumViewLength;
00175     QueryTable[7].Flags = 32;
00176     QueryTable[7].Name = L"DefaultViewLength";
00177     QueryTable[7].EntryContext = &DefaultViewLength;
00178     QueryTable[8].Flags = 32;
00179     QueryTable[8].Name = L"MaximumViewLength";
00180     QueryTable[8].EntryContext = &MaximumViewLength;
00181     QueryTable[9].Flags = 32;
00182     QueryTable[9].Name = L"MaximumPerDiskViewLength";
00183     QueryTable[9].EntryContext = &MaximumPerDiskViewLength;
00184     RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL,
00185                            RegistryPath->Buffer,
00186                            QueryTable,
00187                            NULL,
00188                            NULL);
00189     
00190     //
00191     // Parse minimum view count, cannot be bigger than 256 or smaller than 2
00192     //
00193     MinView = MinimumViewCount;
00194     if (MinimumViewCount >= 2)
00195     {
00196         if (MinimumViewCount > 256) MinView = 256;
00197     }
00198     else
00199     {
00200         MinView = 2;
00201     }
00202     MinimumViewCount = MinView;
00203 
00204     //
00205     // Parse default view count, cannot be bigger than 256 or smaller than minimum
00206     //
00207     DefView = DefaultViewCount;
00208     if (DefaultViewCount >= MinView)
00209     {
00210         if (DefaultViewCount > 256) DefView = 256;
00211     }
00212     else
00213     {
00214         DefView = MinView;
00215     }
00216     DefaultViewCount = DefView;
00217     
00218     //
00219     // Parse maximum view count, cannot be bigger than 256 or smaller than default
00220     //
00221     if (MaximumViewCount >= DefView)
00222     {
00223         if (MaximumViewCount > 256) MaximumViewCount = 256;
00224     }
00225     else
00226     {
00227         MaximumViewCount = DefView;
00228     }
00229     
00230     //
00231     // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
00232     //
00233     MinViewLength = MinimumViewLength;
00234     if (MinimumViewLength >= 0x10000)
00235     {
00236         if (MinimumViewLength > 0x40000000) MinViewLength = 0x40000000u;
00237     }
00238     else
00239     {
00240         MinViewLength = 0x10000u;
00241     }
00242     MinimumViewLength = MinViewLength;
00243 
00244     //
00245     // Parse default view length, cannot be bigger than 1GB or smaller than minimum
00246     //
00247     DefViewLength = DefaultViewLength;
00248     if (DefaultViewLength >= MinViewLength)
00249     {
00250         if (DefaultViewLength > 0x40000000) DefViewLength = 0x40000000u;
00251     }
00252     else
00253     {
00254         DefViewLength = MinViewLength;
00255     }
00256     DefaultViewLength = DefViewLength;
00257 
00258     //
00259     // Parse maximum view length, cannot be bigger than 1GB or smaller than default
00260     //
00261     MaxViewLength = MaximumViewLength;
00262     if (MaximumViewLength >= DefViewLength)
00263     {
00264         if (MaximumViewLength > 0x40000000) MaxViewLength = 0x40000000u;
00265     }
00266     else
00267     {
00268         MaxViewLength = DefViewLength;
00269     }
00270     MaximumViewLength = MaxViewLength;
00271 
00272     //
00273     // Parse maximum view length per disk, cannot be smaller than 16MB
00274     //
00275     if (MaximumPerDiskViewLength >= 0x1000000)
00276     {
00277         if (MaxViewLength > 0xFFFFFFFF) MaximumPerDiskViewLength = -1;
00278     }
00279     else
00280     {
00281         MaximumPerDiskViewLength = 0x1000000u;
00282     }
00283 }
00284 
00285 PVOID
00286 NTAPI
00287 RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
00288                 IN LARGE_INTEGER Offset,
00289                 IN ULONG Length,
00290                 OUT PULONG OutputLength)
00291 {
00292     PHYSICAL_ADDRESS PhysicalAddress;
00293     PVOID MappedBase;
00294     ULONG PageOffset;
00295     SIZE_T ActualLength;
00296     LARGE_INTEGER ActualOffset;
00297     LARGE_INTEGER ActualPages;
00298     
00299     //
00300     // We only support boot disks for now
00301     //
00302     ASSERT(DeviceExtension->DiskType == RAMDISK_BOOT_DISK);
00303     
00304     //
00305     // Calculate the actual offset in the drive
00306     //
00307     ActualOffset.QuadPart = DeviceExtension->DiskOffset + Offset.QuadPart;
00308     
00309     //
00310     // Convert to pages
00311     //
00312     ActualPages.QuadPart = ActualOffset.QuadPart >> PAGE_SHIFT;
00313     
00314     //
00315     // Now add the base page
00316     //
00317     ActualPages.QuadPart = DeviceExtension->BasePage + ActualPages.QuadPart;
00318     
00319     //
00320     // Calculate final amount of bytes
00321     //
00322     PhysicalAddress.QuadPart = ActualPages.QuadPart << PAGE_SHIFT;
00323     
00324     //
00325     // Calculate pages spanned for the mapping
00326     //
00327     ActualLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset.QuadPart, Length);
00328     
00329     //
00330     // And convert this back to bytes
00331     //
00332     ActualLength <<= PAGE_SHIFT;
00333     
00334     //
00335     // Get the offset within the page
00336     //
00337     PageOffset = BYTE_OFFSET(ActualOffset.QuadPart);
00338     
00339     //
00340     // Map the I/O Space from the loader
00341     //
00342     MappedBase = MmMapIoSpace(PhysicalAddress, ActualLength, MmCached);
00343     
00344     //
00345     // Return actual offset within the page as well as the length
00346     //
00347     if (MappedBase) MappedBase = (PVOID)((ULONG_PTR)MappedBase + PageOffset);
00348     *OutputLength = Length;
00349     return MappedBase;
00350 }
00351 
00352 VOID
00353 NTAPI
00354 RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
00355                   IN PVOID BaseAddress,
00356                   IN LARGE_INTEGER Offset,
00357                   IN ULONG Length)
00358 {
00359     LARGE_INTEGER ActualOffset;
00360     SIZE_T ActualLength;
00361     ULONG PageOffset;
00362     
00363     //
00364     // We only support boot disks for now
00365     //
00366     ASSERT(DeviceExtension->DiskType == RAMDISK_BOOT_DISK);
00367     
00368     //
00369     // Calculate the actual offset in the drive
00370     //
00371     ActualOffset.QuadPart = DeviceExtension->DiskOffset + Offset.QuadPart;
00372     
00373     //
00374     // Calculate pages spanned for the mapping
00375     //
00376     ActualLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset.QuadPart, Length);
00377     
00378     //
00379     // And convert this back to bytes
00380     //
00381     ActualLength <<= PAGE_SHIFT;
00382     
00383     //
00384     // Get the offset within the page
00385     //
00386     PageOffset = BYTE_OFFSET(ActualOffset.QuadPart);
00387     
00388     //
00389     // Calculate actual base address where we mapped this
00390     //
00391     BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - PageOffset);
00392     
00393     //
00394     // Unmap the I/O space we got from the loader
00395     //
00396     MmUnmapIoSpace(BaseAddress, ActualLength);
00397 }
00398 
00399 NTSTATUS
00400 NTAPI
00401 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension,
00402                         IN PRAMDISK_CREATE_INPUT Input,
00403                         IN BOOLEAN ValidateOnly,
00404                         OUT PRAMDISK_DRIVE_EXTENSION *NewDriveExtension)
00405 {
00406     ULONG BasePage, DiskType, Length;
00407     //ULONG ViewCount;
00408     NTSTATUS Status;
00409     PDEVICE_OBJECT DeviceObject;
00410     PRAMDISK_DRIVE_EXTENSION DriveExtension;
00411     PVOID Buffer;
00412     WCHAR LocalBuffer[16];
00413     UNICODE_STRING SymbolicLinkName, DriveString, GuidString, DeviceName;
00414     PPACKED_BOOT_SECTOR BootSector;
00415     BIOS_PARAMETER_BLOCK BiosBlock;
00416     ULONG BytesPerSector, SectorsPerTrack, Heads, BytesRead;
00417     PVOID BaseAddress;
00418     LARGE_INTEGER CurrentOffset, CylinderSize, DiskLength;
00419     ULONG CylinderCount, SizeByCylinders;
00420     
00421     //
00422     // Check if we're a boot RAM disk
00423     //
00424     DiskType = Input->DiskType;
00425     if (DiskType >= RAMDISK_BOOT_DISK)
00426     {
00427         //
00428         // Check if we're an ISO
00429         // 
00430         if (DiskType == RAMDISK_BOOT_DISK)
00431         {
00432             //
00433             // NTLDR mounted us somewhere
00434             //
00435             BasePage = Input->BasePage;
00436             if (!BasePage) return STATUS_INVALID_PARAMETER;
00437             
00438             //
00439             // Sanitize disk options
00440             //
00441             Input->Options.Fixed = TRUE;
00442             Input->Options.Readonly = Input->Options.ExportAsCd |
00443                                       Input->Options.Readonly;
00444             Input->Options.Hidden = FALSE;
00445             Input->Options.NoDosDevice = FALSE;
00446             Input->Options.NoDriveLetter = IsWinPEBoot ? TRUE : FALSE;
00447         }
00448         else
00449         {
00450             //
00451             // The only other possibility is a WIM disk
00452             //
00453             if (DiskType != RAMDISK_WIM_DISK)
00454             {
00455                 //
00456                 // Fail
00457                 //
00458                 return STATUS_INVALID_PARAMETER;
00459             }
00460 
00461             //
00462             // Read the view count instead
00463             //
00464             //ViewCount = Input->ViewCount;
00465             
00466             //
00467             // Sanitize disk options
00468             //
00469             Input->Options.Hidden = FALSE;
00470             Input->Options.NoDosDevice = FALSE;
00471             Input->Options.Readonly = FALSE;
00472             Input->Options.NoDriveLetter = TRUE;
00473             Input->Options.Fixed = TRUE;
00474         }
00475         
00476         //
00477         // Are we just validating and returning to the user?
00478         //
00479         if (ValidateOnly) return STATUS_SUCCESS;
00480         
00481         //
00482         // Build the GUID string
00483         //
00484         Status = RtlStringFromGUID(&Input->DiskGuid, &GuidString);
00485         if (!(NT_SUCCESS(Status)) || !(GuidString.Buffer))
00486         {
00487             //
00488             // Fail
00489             //
00490             Status = STATUS_INSUFFICIENT_RESOURCES;
00491             goto FailCreate;
00492         }
00493         
00494         //
00495         // Allocate our device name
00496         //
00497         Length = GuidString.Length + 32;
00498         Buffer = ExAllocatePoolWithTag(NonPagedPool,
00499                                        Length,
00500                                        'dmaR');
00501         if (!Buffer)
00502         {
00503             //
00504             // Fail
00505             //
00506             Status = STATUS_INSUFFICIENT_RESOURCES;
00507             goto FailCreate;
00508         }
00509         
00510         // 
00511         // Build the device name string
00512         //
00513         DeviceName.Buffer = Buffer;
00514         DeviceName.Length = Length - 2;
00515         DeviceName.MaximumLength = Length;
00516         wcsncpy(Buffer, L"\\Device\\Ramdisk", Length / sizeof(WCHAR));
00517         wcsncat(Buffer, GuidString.Buffer, Length / sizeof(WCHAR));
00518         
00519         //
00520         // Create the drive device
00521         //
00522         Status = IoCreateDevice(DeviceExtension->DeviceObject->DriverObject,
00523                                 sizeof(RAMDISK_DRIVE_EXTENSION),
00524                                 &DeviceName,
00525                                 (Input->Options.ExportAsCd) ?
00526                                 FILE_DEVICE_CD_ROM : FILE_DEVICE_DISK,
00527                                 0,
00528                                 0,
00529                                 &DeviceObject);
00530         if (!NT_SUCCESS(Status)) goto FailCreate;
00531         
00532         //
00533         // Grab the drive extension
00534         //
00535         DriveExtension = DeviceObject->DeviceExtension;
00536        
00537         //
00538         // Check if we need a DOS device
00539         //
00540         if (!Input->Options.NoDosDevice)
00541         {
00542             //
00543             // Build the symbolic link name
00544             //
00545             SymbolicLinkName.MaximumLength = GuidString.Length + 36;
00546             SymbolicLinkName.Length = GuidString.Length + 34;
00547             Buffer = ExAllocatePoolWithTag(NonPagedPool,
00548                                            SymbolicLinkName.MaximumLength,
00549                                            'dmaR');
00550             SymbolicLinkName.Buffer = Buffer;
00551             if (Buffer)
00552             {
00553                 //
00554                 // Create it
00555                 //
00556                 wcsncpy(Buffer,
00557                         L"\\GLOBAL??\\Ramdisk",
00558                         SymbolicLinkName.MaximumLength / sizeof(WCHAR));
00559                 wcsncat(Buffer,
00560                         GuidString.Buffer,
00561                         SymbolicLinkName.MaximumLength / sizeof(WCHAR));
00562                 Status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
00563                 if (!NT_SUCCESS(Status))
00564                 {
00565                     //
00566                     // Nevermind...
00567                     //
00568                     Input->Options.NoDosDevice = TRUE;
00569                     ExFreePool(Buffer);
00570                     SymbolicLinkName.Buffer = NULL;
00571                 }
00572             }
00573             else
00574             {
00575                 //
00576                 // No DOS device
00577                 //
00578                 Input->Options.NoDosDevice = TRUE;
00579             }
00580             
00581             //
00582             // It this an ISO boot ramdisk?
00583             //
00584             if (Input->DiskType == RAMDISK_BOOT_DISK)
00585             {
00586                 //
00587                 // Does it need a drive letter?
00588                 //
00589                 if (!Input->Options.NoDriveLetter)
00590                 {
00591                     //
00592                     // Build it and take over the existing symbolic link
00593                     //
00594                     _snwprintf(LocalBuffer,
00595                                30,
00596                                L"\\DosDevices\\%wc:",
00597                                Input->DriveLetter);
00598                     RtlInitUnicodeString(&DriveString, LocalBuffer);
00599                     IoDeleteSymbolicLink(&DriveString);
00600                     IoCreateSymbolicLink(&DriveString, &DeviceName);
00601                     
00602                     //
00603                     // Save the drive letter
00604                     //
00605                     DriveExtension->DriveLetter = Input->DriveLetter;
00606                 }
00607             }
00608             
00609         }
00610         
00611         //
00612         // Setup the device object flags
00613         //
00614         DeviceObject->Flags |= (DO_XIP | DO_POWER_PAGABLE | DO_DIRECT_IO);
00615         DeviceObject->AlignmentRequirement = 1;
00616         
00617         //
00618         // Build the drive FDO
00619         //
00620         *NewDriveExtension = DriveExtension;
00621         DriveExtension->Type = RamdiskDrive;
00622         DiskLength = Input->DiskLength;
00623         ExInitializeFastMutex(&DriveExtension->DiskListLock);
00624         IoInitializeRemoveLock(&DriveExtension->RemoveLock,
00625                                'dmaR',
00626                                0,
00627                                1);
00628         DriveExtension->DriveDeviceName = DeviceName;
00629         DriveExtension->SymbolicLinkName = SymbolicLinkName;
00630         DriveExtension->GuidString = GuidString;
00631         DriveExtension->DiskGuid = Input->DiskGuid;
00632         DriveExtension->PhysicalDeviceObject = DeviceObject;
00633         DriveExtension->DeviceObject = RamdiskBusFdo;
00634         DriveExtension->AttachedDevice = RamdiskBusFdo;
00635         DriveExtension->DiskType = Input->DiskType;
00636         DriveExtension->DiskOptions = Input->Options;
00637         DriveExtension->DiskLength = DiskLength;
00638         DriveExtension->DiskOffset = Input->DiskOffset;
00639         DriveExtension->BasePage = Input->BasePage;
00640         DriveExtension->BytesPerSector = 0;
00641         DriveExtension->SectorsPerTrack = 0;
00642         DriveExtension->NumberOfHeads = 0;
00643         
00644         //
00645         // Make sure we don't free it later
00646         //
00647         DeviceName.Buffer = NULL;
00648         SymbolicLinkName.Buffer = NULL;
00649         GuidString.Buffer = NULL;
00650         
00651         //
00652         // Check if this is an boot disk, or a registry ram drive
00653         //
00654         if (!(Input->Options.ExportAsCd) &&
00655             (Input->DiskType == RAMDISK_BOOT_DISK))
00656         {
00657             //
00658             // Not an ISO boot, but it's a boot FS -- map it to figure out the
00659             // drive settings
00660             //
00661             CurrentOffset.QuadPart = 0;
00662             BaseAddress = RamdiskMapPages(DriveExtension,
00663                                           CurrentOffset,
00664                                           PAGE_SIZE,
00665                                           &BytesRead);
00666             if (BaseAddress)
00667             {
00668                 //
00669                 // Get the data
00670                 //
00671                 BootSector = (PPACKED_BOOT_SECTOR)BaseAddress;
00672                 FatUnpackBios(&BiosBlock, &BootSector->PackedBpb);
00673                 BytesPerSector = BiosBlock.BytesPerSector;
00674                 SectorsPerTrack = BiosBlock.SectorsPerTrack;
00675                 Heads = BiosBlock.Heads;
00676                 
00677                 //
00678                 // Save it
00679                 //
00680                 DriveExtension->BytesPerSector = BytesPerSector;
00681                 DriveExtension->SectorsPerTrack = SectorsPerTrack;
00682                 DriveExtension->NumberOfHeads = Heads;
00683                 
00684                 //
00685                 // Unmap now
00686                 //
00687                 CurrentOffset.QuadPart = 0;
00688                 RamdiskUnmapPages(DriveExtension,
00689                                   BaseAddress,
00690                                   CurrentOffset,
00691                                   BytesRead);
00692             }
00693             else
00694             {
00695                 //
00696                 // Fail
00697                 //
00698                 Status = STATUS_INSUFFICIENT_RESOURCES;
00699                 goto FailCreate;
00700             }
00701         }
00702                 
00703         //
00704         // Check if the drive settings haven't been set yet
00705         //
00706         if ((DriveExtension->BytesPerSector == 0) ||
00707             (DriveExtension->SectorsPerTrack == 0) ||
00708             (DriveExtension->NumberOfHeads == 0))
00709         {
00710             //
00711             // Check if this is a CD
00712             //
00713             if (Input->Options.ExportAsCd)
00714             {
00715                 //
00716                 // Setup partition parameters default for ISO 9660
00717                 //
00718                 DriveExtension->BytesPerSector = 2048;
00719                 DriveExtension->SectorsPerTrack = 32;
00720                 DriveExtension->NumberOfHeads = 64;
00721             }
00722             else
00723             {
00724                 //
00725                 // Setup partition parameters default for FAT
00726                 //
00727                 DriveExtension->BytesPerSector = 512;
00728                 DriveExtension->SectorsPerTrack = 128;
00729                 DriveExtension->NumberOfHeads = 16;
00730             }
00731         }
00732         
00733         //
00734         // Calculate the cylinder size
00735         //
00736         CylinderSize.QuadPart = DriveExtension->BytesPerSector *
00737                                 DriveExtension->SectorsPerTrack *
00738                                 DriveExtension->NumberOfHeads;
00739         CylinderCount = DiskLength.QuadPart / CylinderSize.QuadPart;
00740         SizeByCylinders = CylinderSize.QuadPart * CylinderCount;
00741         DriveExtension->Cylinders = CylinderCount;
00742         if ((DiskLength.HighPart > 0) || (SizeByCylinders < DiskLength.LowPart))
00743         {
00744             //
00745             // Align cylinder size up
00746             //
00747             DriveExtension->Cylinders++;
00748         }
00749         
00750         //
00751         // Acquire the disk lock
00752         //
00753         KeEnterCriticalRegion();
00754         ExAcquireFastMutex(&DeviceExtension->DiskListLock);
00755         
00756         //
00757         // Insert us
00758         //
00759         InsertTailList(&DeviceExtension->DiskList, &DriveExtension->DiskList);
00760         
00761         //
00762         // Release the lock
00763         //
00764         ExReleaseFastMutex(&DeviceExtension->DiskListLock);
00765         KeLeaveCriticalRegion();
00766         
00767         //
00768         // Clear init flag
00769         //
00770         DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
00771         return STATUS_SUCCESS;
00772     }
00773     
00774 FailCreate:
00775     UNIMPLEMENTED;
00776     while (TRUE);
00777     return STATUS_SUCCESS;
00778 }
00779 
00780 NTSTATUS
00781 NTAPI
00782 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject,
00783                      IN PIRP Irp,
00784                      IN BOOLEAN ValidateOnly)
00785 {
00786     PRAMDISK_CREATE_INPUT Input;
00787     ULONG Length;
00788     PRAMDISK_BUS_EXTENSION DeviceExtension;
00789     PRAMDISK_DRIVE_EXTENSION DriveExtension; 
00790     ULONG DiskType;
00791     PWCHAR FileNameStart, FileNameEnd;
00792     NTSTATUS Status;
00793     PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
00794     
00795     //
00796     // Get the device extension and our input data
00797     //
00798     DeviceExtension = DeviceObject->DeviceExtension;
00799     Length = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
00800     Input = (PRAMDISK_CREATE_INPUT)Irp->AssociatedIrp.SystemBuffer;
00801     
00802     //
00803     // Validate input parameters
00804     //
00805     if ((Length < sizeof(RAMDISK_CREATE_INPUT)) ||
00806         (Input->Version != sizeof(RAMDISK_CREATE_INPUT)))
00807     {
00808         //
00809         // Invalid input
00810         //
00811         return STATUS_INVALID_PARAMETER;
00812     }
00813     
00814     //
00815     // Validate the disk type
00816     //
00817     DiskType = Input->DiskType;
00818     if (DiskType == RAMDISK_WIM_DISK) return STATUS_INVALID_PARAMETER;
00819     
00820     //
00821     // Look at the disk type
00822     //
00823     if (DiskType == RAMDISK_BOOT_DISK)
00824     {
00825         //
00826         // We only allow this as an early-init boot
00827         //
00828         if (!KeLoaderBlock) return STATUS_INVALID_PARAMETER;
00829         
00830         //
00831         // Save command-line flags
00832         //
00833         if (ExportBootDiskAsCd) Input->Options.ExportAsCd = TRUE;
00834         if (IsWinPEBoot) Input->Options.NoDriveLetter = TRUE;
00835     }
00836     
00837     //
00838     // Validate the disk type
00839     //
00840     if ((Input->Options.ExportAsCd) && (DiskType != RAMDISK_BOOT_DISK))
00841     {
00842         //
00843         // If the type isn't CDFS, it has to at least be raw CD
00844         //
00845         if (DiskType != RAMDISK_MEMORY_MAPPED_DISK) return STATUS_INVALID_PARAMETER;
00846     }
00847     
00848     //
00849     // Check if this is an actual file
00850     //
00851     if (DiskType <= RAMDISK_MEMORY_MAPPED_DISK)
00852     {
00853         //
00854         // Validate the file name
00855         //
00856         FileNameStart = (PWCHAR)((ULONG_PTR)Input + Length);
00857         FileNameEnd = Input->FileName + 1;
00858         while ((FileNameEnd < FileNameStart) && *(FileNameEnd)) FileNameEnd++;
00859         if (FileNameEnd == FileNameStart) return STATUS_INVALID_PARAMETER;
00860     }
00861     
00862     //
00863     // Create the actual device
00864     //
00865     Status = RamdiskCreateDiskDevice(DeviceExtension,
00866                                      Input, 
00867                                      ValidateOnly,
00868                                      &DriveExtension);
00869     if (NT_SUCCESS(Status))
00870     {
00871         //
00872         // Invalidate and set success
00873         //
00874         IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, 0);
00875         Irp->IoStatus.Information = STATUS_SUCCESS;
00876     }
00877     
00878     //
00879     // We're done
00880     //
00881     return Status;
00882 }
00883 
00884 NTSTATUS
00885 NTAPI
00886 RamdiskGetPartitionInfo(IN PIRP Irp,
00887                         IN PRAMDISK_DRIVE_EXTENSION DeviceExtension)
00888 {
00889     NTSTATUS Status;
00890     PPARTITION_INFORMATION PartitionInfo;
00891     PVOID BaseAddress;
00892     LARGE_INTEGER Zero = {{0, 0}};
00893     ULONG Length;
00894     PIO_STACK_LOCATION IoStackLocation;
00895     
00896     //
00897     // Validate the length
00898     //
00899     IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
00900     if (IoStackLocation->Parameters.DeviceIoControl.
00901         OutputBufferLength < sizeof(PARTITION_INFORMATION))
00902     {
00903         //
00904         // Invalid length
00905         //
00906         Status = STATUS_BUFFER_TOO_SMALL;
00907         Irp->IoStatus.Status = Status;
00908         Irp->IoStatus.Information = 0;
00909         return Status;
00910     }
00911     
00912     //
00913     // Map the partition table
00914     //
00915     BaseAddress = RamdiskMapPages(DeviceExtension, Zero, PAGE_SIZE, &Length);
00916     if (!BaseAddress)
00917     {
00918         //
00919         // No memory
00920         //
00921         Status = STATUS_INSUFFICIENT_RESOURCES;
00922         Irp->IoStatus.Status = Status;
00923         Irp->IoStatus.Information = 0;
00924         return Status;
00925     }
00926     
00927     //
00928     // Fill out the information
00929     //
00930     PartitionInfo = Irp->AssociatedIrp.SystemBuffer;
00931     PartitionInfo->StartingOffset.QuadPart = DeviceExtension->BytesPerSector;
00932     PartitionInfo->PartitionLength.QuadPart = DeviceExtension->BytesPerSector *
00933                                               DeviceExtension->SectorsPerTrack *
00934                                               DeviceExtension->NumberOfHeads *
00935                                               DeviceExtension->Cylinders;
00936     PartitionInfo->HiddenSectors = DeviceExtension->HiddenSectors;
00937     PartitionInfo->PartitionNumber = 0;
00938     PartitionInfo->PartitionType = *((PCHAR)BaseAddress + 450);
00939     PartitionInfo->BootIndicator = (DeviceExtension->DiskType ==
00940                                     RAMDISK_BOOT_DISK) ? TRUE: FALSE;
00941     PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartitionInfo->
00942                                                                PartitionType);
00943     PartitionInfo->RewritePartition = FALSE;
00944 
00945     //
00946     // Unmap the partition table
00947     //
00948     RamdiskUnmapPages(DeviceExtension, BaseAddress, Zero, Length);
00949     
00950     //
00951     // Done
00952     //
00953     Irp->IoStatus.Status = STATUS_SUCCESS;
00954     Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
00955     return STATUS_SUCCESS;
00956 }
00957 
00958 NTSTATUS
00959 NTAPI
00960 RamdiskSetPartitionInfo(IN PIRP Irp,
00961                         IN PRAMDISK_DRIVE_EXTENSION DeviceExtension)
00962 {
00963     ULONG BytesRead;
00964     NTSTATUS Status;
00965     PVOID BaseAddress;
00966     PIO_STACK_LOCATION Stack;
00967     LARGE_INTEGER Zero = {{0, 0}};
00968     PPARTITION_INFORMATION PartitionInfo;
00969 
00970     //
00971     // First validate input
00972     //
00973     Stack = IoGetCurrentIrpStackLocation(Irp);
00974     if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(PARTITION_INFORMATION))
00975     {
00976         Status = STATUS_INVALID_PARAMETER;
00977         goto SetAndQuit;
00978     }
00979 
00980     //
00981     // Map to get MBR
00982     //
00983     BaseAddress = RamdiskMapPages(DeviceExtension, Zero, PAGE_SIZE, &BytesRead);
00984     if (BaseAddress == NULL)
00985     {
00986         Status = STATUS_INSUFFICIENT_RESOURCES;
00987         goto SetAndQuit;
00988     }
00989 
00990     //
00991     // Set the new partition type
00992     // On partition 0, field system indicator
00993     //
00994     PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
00995     *((PCHAR)BaseAddress + 450) = PartitionInfo->PartitionType;
00996 
00997     //
00998     // And unmap
00999     //
01000     RamdiskUnmapPages(DeviceExtension, BaseAddress, Zero, BytesRead);
01001     Status = STATUS_SUCCESS;
01002 
01003 SetAndQuit:
01004     Irp->IoStatus.Status = Status;
01005     Irp->IoStatus.Information = 0;
01006     return Status;
01007 }
01008 
01009 VOID
01010 NTAPI
01011 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject,
01012                     IN PVOID Context)
01013 {
01014     PRAMDISK_BUS_EXTENSION DeviceExtension;
01015     NTSTATUS Status;
01016     PIO_STACK_LOCATION IoStackLocation;
01017     PIRP Irp = Context;
01018     
01019     //
01020     // Get the stack location
01021     //
01022     IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
01023     
01024     //
01025     // Free the work item
01026     //
01027     IoFreeWorkItem(Irp->Tail.Overlay.DriverContext[0]);
01028     
01029     //
01030     // Grab the device extension and lock it
01031     //
01032     DeviceExtension = DeviceObject->DeviceExtension;
01033     Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
01034     if (NT_SUCCESS(Status))
01035     {
01036         //
01037         // Discriminate by major code
01038         //
01039         switch (IoStackLocation->MajorFunction)
01040         {
01041             //
01042             // Device control
01043             //
01044             case IRP_MJ_DEVICE_CONTROL:
01045                                
01046                 //
01047                 // Let's take a look at the IOCTL
01048                 //
01049                 switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
01050                 {
01051                     //
01052                     // Ramdisk create request
01053                     //
01054                     case FSCTL_CREATE_RAM_DISK:
01055                         
01056                         //
01057                         // This time we'll do it for real
01058                         //
01059                         Status = RamdiskCreateRamdisk(DeviceObject, Irp, FALSE);
01060                         break;
01061                         
01062                     case IOCTL_DISK_SET_PARTITION_INFO:
01063 
01064                         Status = RamdiskSetPartitionInfo(Irp, (PRAMDISK_DRIVE_EXTENSION)DeviceExtension);
01065                         break;
01066 
01067                     case IOCTL_DISK_GET_DRIVE_LAYOUT:
01068                         
01069                         DPRINT1("Get drive layout request\n");
01070                         UNIMPLEMENTED;
01071                         while (TRUE);
01072                         break;
01073                         
01074                     case IOCTL_DISK_GET_PARTITION_INFO:
01075 
01076                         Status = RamdiskGetPartitionInfo(Irp, (PRAMDISK_DRIVE_EXTENSION)DeviceExtension);
01077                         break;
01078 
01079                     default:
01080                         
01081                         DPRINT1("Invalid request\n");
01082                         UNIMPLEMENTED;
01083                         while (TRUE);
01084                         break;
01085                 }
01086                 
01087                 //
01088                 // We're  here
01089                 //
01090                 break;
01091                 
01092             //
01093             // Read or write request
01094             //
01095             case IRP_MJ_READ:
01096             case IRP_MJ_WRITE:
01097                 
01098                 DPRINT1("Read/Write request\n");
01099                 UNIMPLEMENTED;
01100                 while (TRUE);
01101                 break;
01102                 
01103             //
01104             // Internal request (SCSI?)
01105             //
01106             case IRP_MJ_INTERNAL_DEVICE_CONTROL:
01107 
01108                 DPRINT1("SCSI request\n");
01109                 UNIMPLEMENTED;
01110                 while (TRUE);
01111                 break;
01112                 
01113             //
01114             // Flush request
01115             //
01116             case IRP_MJ_FLUSH_BUFFERS:
01117                 
01118                 DPRINT1("Flush request\n");
01119                 UNIMPLEMENTED;
01120                 while (TRUE);
01121                 break;
01122 
01123             //
01124             // Anything else
01125             //
01126             default:
01127                 
01128                 DPRINT1("Invalid request: %lx\n", IoStackLocation->MajorFunction);
01129                 UNIMPLEMENTED;
01130                 while (TRUE);
01131                 break;
01132         }
01133         
01134         //
01135         // Complete the I/O
01136         //
01137         IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
01138         Irp->IoStatus.Status = Status;
01139         Irp->IoStatus.Information = 0;
01140         IoCompleteRequest(Irp, IO_DISK_INCREMENT);
01141         return;
01142     }
01143     
01144     //
01145     // Fail the I/O
01146     //
01147     Irp->IoStatus.Status = Status;
01148     Irp->IoStatus.Information = 0;
01149     IoCompleteRequest(Irp, IO_NO_INCREMENT);
01150 }
01151 
01152 NTSTATUS
01153 NTAPI
01154 SendIrpToThread(IN PDEVICE_OBJECT DeviceObject,
01155                 IN PIRP Irp)
01156 {
01157     PIO_WORKITEM WorkItem;
01158     
01159     //
01160     // Mark the IRP pending
01161     //
01162     IoMarkIrpPending(Irp);
01163     
01164     //
01165     // Allocate a work item
01166     //
01167     WorkItem = IoAllocateWorkItem(DeviceObject);
01168     if (WorkItem)
01169     {
01170         //
01171         // Queue it up
01172         //
01173         Irp->Tail.Overlay.DriverContext[0] = WorkItem;
01174         IoQueueWorkItem(WorkItem, RamdiskWorkerThread, DelayedWorkQueue, Irp);
01175         return STATUS_PENDING;
01176     }
01177     else
01178     {
01179         //
01180         // Fail
01181         //
01182         return STATUS_INSUFFICIENT_RESOURCES;
01183     }
01184 }
01185 
01186 NTSTATUS
01187 NTAPI
01188 RamdiskReadWriteReal(IN PIRP Irp,
01189                      IN PRAMDISK_DRIVE_EXTENSION DeviceExtension)
01190 {
01191     PMDL Mdl;
01192     PVOID CurrentBase, SystemVa, BaseAddress;
01193     PIO_STACK_LOCATION IoStackLocation;
01194     LARGE_INTEGER CurrentOffset;
01195     ULONG BytesRead, BytesLeft, CopyLength;
01196     PVOID Source, Destination;
01197     NTSTATUS Status;
01198     
01199     //
01200     // Get the MDL and check if it's mapped
01201     //
01202     Mdl = Irp->MdlAddress;
01203     if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
01204     {
01205         //
01206         // Use the mapped address
01207         //
01208         SystemVa = Mdl->MappedSystemVa;
01209     }
01210     else
01211     {
01212         //
01213         // Map it ourselves
01214         //
01215         SystemVa = MmMapLockedPagesSpecifyCache(Mdl,
01216                                                 0,
01217                                                 MmCached,
01218                                                 NULL,
01219                                                 0, 
01220                                                 NormalPagePriority);
01221     }
01222     
01223     //
01224     // Make sure we were able to map it
01225     //
01226     CurrentBase = SystemVa;
01227     if (!SystemVa) return STATUS_INSUFFICIENT_RESOURCES;
01228     
01229     //
01230     // Initialize default
01231     //
01232     Irp->IoStatus.Information = 0;
01233     
01234     //
01235     // Get the I/O Stack Location and capture the data
01236     //
01237     IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
01238     CurrentOffset = IoStackLocation->Parameters.Read.ByteOffset;
01239     BytesLeft = IoStackLocation->Parameters.Read.Length;
01240     if (!BytesLeft) return STATUS_INVALID_PARAMETER;
01241     
01242     //
01243     // Do the copy loop
01244     //
01245     while (TRUE)
01246     {
01247         //
01248         // Map the pages
01249         //
01250         BaseAddress = RamdiskMapPages(DeviceExtension,
01251                                       CurrentOffset,
01252                                       BytesLeft,
01253                                       &BytesRead);
01254         if (!BaseAddress) return STATUS_INSUFFICIENT_RESOURCES;
01255         
01256         //
01257         // Update our lengths
01258         //
01259         Irp->IoStatus.Information += BytesRead;
01260         CopyLength = BytesRead;
01261         
01262         //
01263         // Check if this was a read or write
01264         //
01265         Status = STATUS_SUCCESS;
01266         if (IoStackLocation->MajorFunction == IRP_MJ_READ)
01267         {
01268             //
01269             // Set our copy parameters
01270             //
01271             Destination = CurrentBase;
01272             Source = BaseAddress;
01273             goto DoCopy;
01274         }
01275         else if (IoStackLocation->MajorFunction == IRP_MJ_WRITE)
01276         {
01277             //
01278             // Set our copy parameters
01279             //
01280             Destination = BaseAddress;
01281             Source = CurrentBase;
01282 DoCopy:
01283             //
01284             // Copy the data
01285             //
01286             RtlCopyMemory(Destination, Source, CopyLength);
01287         }
01288         else
01289         {
01290             //
01291             // Prepare us for failure
01292             //
01293             BytesLeft = CopyLength;
01294             Status = STATUS_INVALID_PARAMETER;
01295         }
01296         
01297         //
01298         // Unmap the pages
01299         //
01300         RamdiskUnmapPages(DeviceExtension,
01301                           BaseAddress,
01302                           CurrentOffset,
01303                           BytesRead);
01304         
01305         //
01306         // Update offset and bytes left
01307         //
01308         BytesLeft -= BytesRead;
01309         CurrentOffset.QuadPart += BytesRead;
01310         CurrentBase = (PVOID)((ULONG_PTR)CurrentBase + BytesRead);
01311         
01312         //
01313         // Check if we're done
01314         //
01315         if (!BytesLeft) return Status;
01316     }
01317 }
01318 
01319 NTSTATUS
01320 NTAPI
01321 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject,
01322                  IN PIRP Irp)
01323 {
01324     //
01325     // Complete the IRP
01326     //
01327     Irp->IoStatus.Information = 1;
01328     Irp->IoStatus.Status = STATUS_SUCCESS;
01329     IoCompleteRequest(Irp, IO_NO_INCREMENT);
01330     return STATUS_SUCCESS;
01331 }
01332 
01333 NTSTATUS
01334 NTAPI
01335 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject,
01336                  IN PIRP Irp)
01337 {
01338     PRAMDISK_DRIVE_EXTENSION DeviceExtension;
01339     //ULONG Length;
01340     //LARGE_INTEGER ByteOffset;
01341     PIO_STACK_LOCATION IoStackLocation;
01342     NTSTATUS Status, ReturnStatus;
01343 
01344     //
01345     // Get the device extension and make sure this isn't a bus
01346     //
01347     DeviceExtension = DeviceObject->DeviceExtension;
01348     if (DeviceExtension->Type == RamdiskBus)
01349     {
01350         //
01351         // Fail
01352         //
01353         Status = STATUS_INVALID_DEVICE_REQUEST;
01354         goto Complete;
01355     }
01356     
01357     //
01358     // Capture parameters
01359     //
01360     IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
01361     //Length = IoStackLocation->Parameters.Read.Length;
01362     //ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
01363     
01364     //
01365     // FIXME: Validate offset
01366     //
01367     
01368     //
01369     // FIXME: Validate sector
01370     //
01371     
01372     //
01373     // Validate write
01374     //
01375     if ((IoStackLocation->MajorFunction == IRP_MJ_WRITE) &&
01376         (DeviceExtension->DiskOptions.Readonly))
01377     {
01378         //
01379         // Fail, this is read-only
01380         //
01381         Status = STATUS_MEDIA_WRITE_PROTECTED;
01382         goto Complete;
01383     }
01384     
01385     //
01386     // See if we want to do this sync or async
01387     //
01388     if (DeviceExtension->DiskType > RAMDISK_MEMORY_MAPPED_DISK)
01389     {
01390         //
01391         // Do it sync
01392         //
01393         Status = RamdiskReadWriteReal(Irp, DeviceExtension);
01394         goto Complete;
01395     }
01396     
01397     //
01398     // Queue it to the worker
01399     //
01400     Status = SendIrpToThread(DeviceObject, Irp);
01401     ReturnStatus = STATUS_PENDING;
01402     
01403     //
01404     // Check if we're pending or not
01405     //
01406     if (Status != STATUS_PENDING)
01407     {
01408 Complete:
01409         //
01410         // Complete the IRP
01411         //
01412         Irp->IoStatus.Status = Status;
01413         IoCompleteRequest(Irp, IO_DISK_INCREMENT);
01414         ReturnStatus = Status;
01415     }
01416     
01417     //
01418     // Return to caller
01419     //
01420     return ReturnStatus;
01421 }
01422 
01423 NTSTATUS
01424 NTAPI
01425 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
01426                      IN PIRP Irp)
01427 {
01428     NTSTATUS Status;
01429     PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
01430     PRAMDISK_BUS_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
01431     PRAMDISK_DRIVE_EXTENSION DriveExtension = (PVOID)DeviceExtension;
01432     ULONG Information;
01433     PCDROM_TOC Toc;
01434     PDISK_GEOMETRY DiskGeometry;
01435     
01436     //
01437     // Grab the remove lock
01438     //
01439     Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
01440     if (!NT_SUCCESS(Status))
01441     {
01442         //
01443         // Fail the IRP
01444         //
01445         Irp->IoStatus.Information = 0;
01446         Irp->IoStatus.Status = Status;
01447         IoCompleteRequest(Irp, IO_NO_INCREMENT);
01448         return Status;
01449     }
01450     
01451     //
01452     // Setup some defaults
01453     //
01454     Status = STATUS_INVALID_DEVICE_REQUEST;
01455     Information = 0;
01456     
01457     //
01458     // Check if this is an bus device or the drive
01459     //
01460     if (DeviceExtension->Type == RamdiskBus)
01461     {
01462         //
01463         // Check what the request is
01464         //
01465         switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
01466         {
01467             //
01468             // Request to create a ramdisk
01469             //
01470             case FSCTL_CREATE_RAM_DISK:
01471                 
01472                 //
01473                 // Do it
01474                 //
01475                 Status = RamdiskCreateRamdisk(DeviceObject, Irp, TRUE);
01476                 if (!NT_SUCCESS(Status)) goto CompleteRequest;
01477                 break;
01478                 
01479             default:
01480                 
01481                 //
01482                 // We don't handle anything else yet
01483                 //
01484                 ASSERT(FALSE);
01485                 while (TRUE);
01486         }
01487     }
01488     else
01489     {
01490         //
01491         // Check what the request is
01492         //
01493         switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
01494         {
01495             case IOCTL_DISK_CHECK_VERIFY:
01496             case IOCTL_STORAGE_CHECK_VERIFY:
01497             case IOCTL_STORAGE_CHECK_VERIFY2:
01498             case IOCTL_CDROM_CHECK_VERIFY:
01499                 
01500                 UNIMPLEMENTED;
01501                 while (TRUE);
01502                 break;
01503 
01504             case IOCTL_STORAGE_GET_MEDIA_TYPES:
01505             case IOCTL_DISK_GET_MEDIA_TYPES:
01506             case IOCTL_DISK_GET_DRIVE_GEOMETRY:
01507             case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
01508                 
01509                 //
01510                 // Validate the length
01511                 //
01512                 if (IoStackLocation->Parameters.DeviceIoControl.
01513                     OutputBufferLength < sizeof(DISK_GEOMETRY))
01514                 {
01515                     //
01516                     // Invalid length
01517                     //
01518                     Status = STATUS_BUFFER_TOO_SMALL;
01519                     break;
01520                 }
01521                 
01522                 //
01523                 // Fill it out
01524                 //
01525                 DiskGeometry = Irp->AssociatedIrp.SystemBuffer;
01526                 DiskGeometry->Cylinders.QuadPart = DriveExtension->Cylinders;
01527                 DiskGeometry->BytesPerSector = DriveExtension->BytesPerSector;
01528                 DiskGeometry->SectorsPerTrack = DriveExtension->SectorsPerTrack;
01529                 DiskGeometry->TracksPerCylinder = DriveExtension->NumberOfHeads;
01530                 DiskGeometry->MediaType = DriveExtension->DiskOptions.Fixed ?
01531                                           FixedMedia : RemovableMedia;
01532                 
01533                 //
01534                 // We're done
01535                 //
01536                 Status = STATUS_SUCCESS;
01537                 Information = sizeof(DISK_GEOMETRY);
01538                 break;
01539             
01540             //
01541             // Hack to support ReactOS's broken CDFS
01542             //
01543             case IOCTL_CDROM_GET_LAST_SESSION:
01544             
01545                 //
01546                 // Validate the length
01547                 //
01548                 if (IoStackLocation->Parameters.DeviceIoControl.
01549                     OutputBufferLength < RAMDISK_SESSION_SIZE)
01550                 {
01551                     //
01552                     // Invalid length
01553                     //
01554                     Status = STATUS_BUFFER_TOO_SMALL;
01555                     break;
01556                 }
01557                 
01558                 //
01559                 // Fill out the TOC
01560                 //
01561                 Toc = Irp->AssociatedIrp.SystemBuffer;
01562                 Toc->Length[0] = 0;
01563                 Toc->Length[1] = RAMDISK_SESSION_SIZE - sizeof(Toc->Length);
01564                 Toc->FirstTrack = 1;
01565                 Toc->LastTrack = 1;
01566                 Toc->TrackData[0].Adr = 1;
01567                 Toc->TrackData[0].Control = TOC_DATA_TRACK;
01568                 Toc->TrackData[0].TrackNumber = 1;
01569                 Toc->TrackData[0].Address[0] =
01570                 Toc->TrackData[0].Address[1] =
01571                 Toc->TrackData[0].Address[2] =
01572                 Toc->TrackData[0].Address[3] = 0;
01573                                 
01574                 //
01575                 // We're done
01576                 //
01577                 Status = STATUS_SUCCESS;
01578                 Information = RAMDISK_SESSION_SIZE;
01579                 break;
01580                                 
01581             case IOCTL_CDROM_READ_TOC:
01582                 
01583                 //
01584                 // Validate the length
01585                 //
01586                 if (IoStackLocation->Parameters.DeviceIoControl.
01587                     OutputBufferLength < sizeof(CDROM_TOC))
01588                 {
01589                     //
01590                     // Invalid length
01591                     //
01592                     Status = STATUS_BUFFER_TOO_SMALL;
01593                     break;
01594                 }
01595                 
01596                 //
01597                 // Clear the TOC
01598                 //
01599                 Toc = Irp->AssociatedIrp.SystemBuffer;
01600                 RtlZeroMemory(Toc, sizeof(CDROM_TOC));
01601                 
01602                 //
01603                 // Fill it out
01604                 //
01605                 Toc->Length[0] = 0;
01606                 Toc->Length[1] = RAMDISK_TOC_SIZE - sizeof(Toc->Length);
01607                 Toc->FirstTrack = 1;
01608                 Toc->LastTrack = 1;
01609                 Toc->TrackData[0].Adr = 1;
01610                 Toc->TrackData[0].Control = TOC_DATA_TRACK;
01611                 Toc->TrackData[0].TrackNumber = 1;
01612                 
01613                 //
01614                 // We're done
01615                 //
01616                 Status = STATUS_SUCCESS;
01617                 Information = RAMDISK_TOC_SIZE;
01618                 break;
01619                 
01620             case IOCTL_DISK_SET_PARTITION_INFO:
01621                 
01622                 Status = RamdiskSetPartitionInfo(Irp, DriveExtension);
01623                 break;
01624                 
01625             case IOCTL_DISK_GET_PARTITION_INFO:
01626                 
01627                 //
01628                 // Validate the length
01629                 //
01630                 if (IoStackLocation->Parameters.DeviceIoControl.
01631                     OutputBufferLength < sizeof(PARTITION_INFORMATION))
01632                 {
01633                     //
01634                     // Invalid length
01635                     //
01636                     Status = STATUS_BUFFER_TOO_SMALL;
01637                     break;
01638                 }
01639                 
01640                 //
01641                 // Check if we need to do this sync or async
01642                 //
01643                 if (DriveExtension->DiskType > RAMDISK_MEMORY_MAPPED_DISK)
01644                 {
01645                     //
01646                     // Call the helper function
01647                     //
01648                     Status = RamdiskGetPartitionInfo(Irp, DriveExtension);
01649                 }
01650                 else
01651                 {
01652                     //
01653                     // Do it asynchronously later
01654                     //
01655                     goto CallWorker;
01656                 }
01657                 
01658                 //
01659                 // We're done
01660                 //
01661                 Information = Irp->IoStatus.Information;
01662                 break;
01663                 
01664             case IOCTL_DISK_GET_DRIVE_LAYOUT:
01665                 
01666                 UNIMPLEMENTED;
01667                 while (TRUE);
01668                 break;
01669                 
01670             case IOCTL_DISK_GET_LENGTH_INFO:
01671                 
01672                 UNIMPLEMENTED;
01673                 while (TRUE);
01674                 break;
01675                 
01676             case IOCTL_DISK_IS_WRITABLE:
01677                 
01678                 UNIMPLEMENTED;
01679                 while (TRUE);
01680                 break;
01681                 
01682             case IOCTL_SCSI_MINIPORT:
01683                 
01684                 UNIMPLEMENTED;
01685                 while (TRUE);
01686                 break;
01687                 
01688             case IOCTL_STORAGE_QUERY_PROPERTY:
01689                 
01690                 UNIMPLEMENTED;
01691                 while (TRUE);
01692                 break;
01693                 
01694             case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
01695                 
01696                 UNIMPLEMENTED;
01697                 while (TRUE);
01698                 break;
01699                 
01700             case IOCTL_MOUNTDEV_QUERY_STABLE_GUID:
01701                 
01702                 UNIMPLEMENTED;
01703                 while (TRUE);
01704                 break;
01705                 
01706             case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
01707                 
01708                 UNIMPLEMENTED;
01709                 while (TRUE);
01710                 break;
01711                 
01712             case IOCTL_VOLUME_SET_GPT_ATTRIBUTES:
01713                 
01714                 UNIMPLEMENTED;
01715                 while (TRUE);
01716                 break;
01717                 
01718             case IOCTL_VOLUME_GET_GPT_ATTRIBUTES:
01719                 
01720                 UNIMPLEMENTED;
01721                 while (TRUE);
01722                 break;
01723                 
01724             case IOCTL_VOLUME_OFFLINE:
01725                 
01726                 UNIMPLEMENTED;
01727                 while (TRUE);
01728                 break;
01729                 
01730             default:
01731          
01732                 //
01733                 // Drive code not emulated
01734                 //
01735                 DPRINT1("IOCTL: %lx\n", IoStackLocation->Parameters.DeviceIoControl.IoControlCode);                
01736                 break;
01737         }
01738 
01739         //
01740         // If requests drop down here, we just return them complete them
01741         //
01742         goto CompleteRequest;
01743     }
01744     
01745     //
01746     // Queue the request to our worker thread
01747     //
01748 CallWorker:
01749     Status = SendIrpToThread(DeviceObject, Irp);
01750     
01751 CompleteRequest:
01752     //
01753     // Release the lock
01754     //
01755     IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
01756     if (Status != STATUS_PENDING)
01757     {
01758         //
01759         // Complete the request
01760         //
01761         Irp->IoStatus.Status = Status;
01762         Irp->IoStatus.Information = Information;
01763         IoCompleteRequest(Irp, IO_NO_INCREMENT);
01764     }
01765     
01766     //
01767     // Return status
01768     //
01769     return Status;
01770 }
01771 
01772 NTSTATUS
01773 NTAPI
01774 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type,
01775                             IN PDEVICE_OBJECT DeviceObject,
01776                             IN PIRP Irp)
01777 {
01778     PRAMDISK_BUS_EXTENSION DeviceExtension;
01779     PRAMDISK_DRIVE_EXTENSION DriveExtension;
01780     PDEVICE_RELATIONS DeviceRelations, OurDeviceRelations;
01781     ULONG Count, DiskCount, FinalCount;
01782     PLIST_ENTRY ListHead, NextEntry;
01783     PDEVICE_OBJECT* DriveDeviceObject;
01784     RAMDISK_DEVICE_STATE State;
01785     
01786     //
01787     // Get the device extension and check if this is a drive
01788     //
01789     DeviceExtension = DeviceObject->DeviceExtension;
01790     if (DeviceExtension->Type == RamdiskDrive)
01791     {
01792         //
01793         // FIXME: TODO
01794         //
01795         UNIMPLEMENTED;
01796         while (TRUE);
01797     }
01798     
01799     //
01800     // Anything but bus relations, we don't handle
01801     //
01802     if (Type) goto PassToNext;
01803     
01804     //
01805     // Acquire the disk list lock
01806     //
01807     KeEnterCriticalRegion();
01808     ExAcquireFastMutex(&DeviceExtension->DiskListLock);
01809     
01810     //
01811     // Did a device already fill relations?
01812     //
01813     DeviceRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
01814     if (DeviceRelations)
01815     {
01816         //
01817         // Use the data
01818         //
01819         Count = DeviceRelations->Count;
01820     }
01821     else
01822     {
01823         //
01824         // We're the first
01825         //
01826         Count = 0;
01827     }
01828     
01829     //
01830     // Now loop our drives
01831     //
01832     DiskCount = 0;
01833     ListHead = &DeviceExtension->DiskList;
01834     NextEntry = ListHead->Flink;
01835     while (NextEntry != ListHead)
01836     {
01837         //
01838         // As long as it wasn't removed, count it in
01839         //
01840         DriveExtension = CONTAINING_RECORD(NextEntry,
01841                                            RAMDISK_DRIVE_EXTENSION,
01842                                            DiskList);
01843         if (DriveExtension->State < RamdiskStateBusRemoved) DiskCount++;
01844         
01845         //
01846         // Move to the next one
01847         //
01848         NextEntry = NextEntry->Flink;
01849     }
01850     
01851     //
01852     // Now we know our final count
01853     //
01854     FinalCount = Count + DiskCount;
01855     
01856     //
01857     // Allocate the structure
01858     //
01859     OurDeviceRelations = ExAllocatePoolWithTag(PagedPool,
01860                                                FIELD_OFFSET(DEVICE_RELATIONS,
01861                                                             Objects) +
01862                                                FinalCount *
01863                                                sizeof(PDEVICE_OBJECT),
01864                                                'dmaR');
01865     if (!OurDeviceRelations)
01866     {
01867         //
01868         // Fail
01869         //
01870         ExReleaseFastMutex(&DeviceExtension->DiskListLock);
01871         KeLeaveCriticalRegion();
01872         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
01873         IoCompleteRequest(Irp, IO_NO_INCREMENT);
01874         return STATUS_INSUFFICIENT_RESOURCES;
01875     }
01876     
01877     //
01878     // Check if we already had some relations
01879     //
01880     if (Count)
01881     {
01882         //
01883         // Copy them in
01884         //
01885         RtlCopyMemory(OurDeviceRelations->Objects,
01886                       DeviceRelations->Objects,
01887                       Count * sizeof(PDEVICE_OBJECT));
01888     }
01889     
01890     //
01891     // Save the count
01892     //
01893     OurDeviceRelations->Count = FinalCount;
01894     
01895     //
01896     // Now loop our drives again
01897     //
01898     ListHead = &DeviceExtension->DiskList;
01899     NextEntry = ListHead->Flink;
01900     while (NextEntry != ListHead)
01901     {
01902         //
01903         // Go to the end of the list
01904         //
01905         DriveDeviceObject = &OurDeviceRelations->Objects[Count];
01906         
01907         //
01908         // Get the drive state
01909         //
01910         DriveExtension = CONTAINING_RECORD(NextEntry,
01911                                            RAMDISK_DRIVE_EXTENSION,
01912                                            DiskList);
01913         State = DriveExtension->State;
01914         
01915         //
01916         // If it was removed or enumerated, we don't touch the device object
01917         //
01918         if (State >= RamdiskStateBusRemoved)
01919         {
01920             //
01921             // If it was removed, we still have to keep track of this though
01922             //
01923             if (State == RamdiskStateBusRemoved)
01924             {
01925                 //
01926                 // Mark it as enumerated now, but don't actually reference it
01927                 //
01928                 DriveExtension->State = RamdiskStateEnumerated;
01929             }
01930         }
01931         else
01932         {
01933             //
01934             // First time it's enumerated, reference the device object
01935             //
01936             ObReferenceObject(DriveExtension->DeviceObject);
01937             
01938             //
01939             // Save the object pointer, and move on
01940             //
01941             *DriveDeviceObject++ = DriveExtension->DeviceObject;
01942         }
01943         
01944         if (DriveExtension->State < RamdiskStateBusRemoved) DiskCount++;
01945         
01946         //
01947         // Move to the next one
01948         //
01949         NextEntry = NextEntry->Flink;
01950     }
01951 
01952     //
01953     // Release the lock
01954     //
01955     ExReleaseFastMutex(&DeviceExtension->DiskListLock);
01956     KeLeaveCriticalRegion();
01957     
01958     //
01959     // Cleanup old relations
01960     //
01961     if (DeviceRelations) ExFreePool(DeviceRelations);
01962     
01963     //
01964     // Complete our IRP
01965     //
01966     Irp->IoStatus.Information = (ULONG_PTR)OurDeviceRelations;
01967     Irp->IoStatus.Status = STATUS_SUCCESS;
01968     
01969     //
01970     // Pass to the next driver
01971     //
01972 PassToNext:
01973     IoCopyCurrentIrpStackLocationToNext(Irp);
01974     return IoCallDriver(DeviceExtension->AttachedDevice, Irp);  
01975 }
01976 
01977 NTSTATUS
01978 NTAPI
01979 RamdiskDeleteDiskDevice(IN PDEVICE_OBJECT DeviceObject,
01980                         IN PIRP Irp)
01981 {
01982     UNIMPLEMENTED;
01983     while (TRUE);
01984     return STATUS_SUCCESS;
01985 }
01986 
01987 NTSTATUS
01988 NTAPI
01989 RamdiskRemoveBusDevice(IN PDEVICE_OBJECT DeviceObject,
01990                        IN PIRP Irp)
01991 {
01992     NTSTATUS Status;
01993     PLIST_ENTRY ListHead, NextEntry;
01994     PRAMDISK_BUS_EXTENSION DeviceExtension;
01995     PRAMDISK_DRIVE_EXTENSION DriveExtension;
01996 
01997     DeviceExtension = DeviceObject->DeviceExtension;
01998 
01999     //
02000     // Acquire disks list lock
02001     //
02002     KeEnterCriticalRegion();
02003     ExAcquireFastMutex(&DeviceExtension->DiskListLock);
02004 
02005     //
02006     // Loop over drives
02007     //
02008     ListHead = &DeviceExtension->DiskList;
02009     NextEntry = ListHead->Flink;
02010     while (NextEntry != ListHead)
02011     {
02012         DriveExtension = CONTAINING_RECORD(NextEntry,
02013                                            RAMDISK_DRIVE_EXTENSION,
02014                                            DiskList);
02015 
02016         //
02017         // Delete the disk
02018         //
02019         IoAcquireRemoveLock(&DriveExtension->RemoveLock, NULL);
02020         RamdiskDeleteDiskDevice(DriveExtension->PhysicalDeviceObject, NULL);
02021 
02022         //
02023         // RamdiskDeleteDiskDevice releases list lock, so reacquire it
02024         //
02025         KeEnterCriticalRegion();
02026         ExAcquireFastMutex(&DeviceExtension->DiskListLock);
02027     }
02028 
02029     //
02030     // Release disks list lock
02031     //
02032     ExReleaseFastMutex(&DeviceExtension->DiskListLock);
02033     KeLeaveCriticalRegion();
02034 
02035     //
02036     // Prepare to pass to the lower driver
02037     //
02038     IoSkipCurrentIrpStackLocation(Irp);
02039     //
02040     // Here everything went fine
02041     //
02042     Irp->IoStatus.Status = STATUS_SUCCESS;
02043 
02044     //
02045     // Call lower driver
02046     //
02047     Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
02048 
02049     //
02050     // Update state
02051     //
02052     DeviceExtension->State = RamdiskStateBusRemoved;
02053 
02054     //
02055     // Release the lock, and ensure that everyone
02056     // has finished its job before we continue
02057     // The lock has been acquired by the dispatcher
02058     //
02059     IoReleaseRemoveLockAndWait(&DeviceExtension->RemoveLock, Irp);
02060 
02061     //
02062     // If there's a drive name
02063     //
02064     if (DeviceExtension->DriveDeviceName.Buffer)
02065     {
02066         //
02067         // Inform it's going to be disabled
02068         // and free the drive name
02069         //
02070         IoSetDeviceInterfaceState(&DeviceExtension->DriveDeviceName, FALSE);
02071         RtlFreeUnicodeString(&DeviceExtension->DriveDeviceName);
02072     }
02073 
02074     //
02075     // Part from the stack, detach from lower device
02076     //
02077     IoDetachDevice(DeviceExtension->AttachedDevice);
02078 
02079     //
02080     // Finally, delete device
02081     //
02082     RamdiskBusFdo = NULL;
02083     IoDeleteDevice(DeviceObject);
02084 
02085     //
02086     // Return status from lower driver
02087     //
02088     return Status;
02089 }
02090 
02091 NTSTATUS
02092 NTAPI
02093 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
02094            IN PIRP Irp)
02095 {
02096     PIO_STACK_LOCATION IoStackLocation;
02097     PRAMDISK_BUS_EXTENSION DeviceExtension;
02098     NTSTATUS Status;
02099     UCHAR Minor;
02100     
02101     //
02102     // Get the device extension and stack location
02103     //
02104     DeviceExtension = DeviceObject->DeviceExtension;
02105     IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
02106     Minor = IoStackLocation->MinorFunction;
02107     
02108     //
02109     // Check if the bus is removed
02110     //
02111     if (DeviceExtension->State == RamdiskStateBusRemoved)
02112     {
02113         //
02114         // Only remove-device and query-id are allowed
02115         //
02116         if ((Minor != IRP_MN_REMOVE_DEVICE) && (Minor != IRP_MN_QUERY_ID))
02117         {
02118             //
02119             // Fail anything else
02120             //
02121             Status = STATUS_NO_SUCH_DEVICE;
02122             Irp->IoStatus.Status = Status;
02123             IoCompleteRequest(Irp, IO_NO_INCREMENT);
02124             return Status;
02125         }
02126     }
02127     
02128     //
02129     // Acquire the remove lock
02130     //
02131     Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
02132     if (!NT_SUCCESS(Status))
02133     {
02134         //
02135         // Fail the IRP
02136         //
02137         Irp->IoStatus.Information = 0;
02138         Irp->IoStatus.Status = Status;
02139         IoCompleteRequest(Irp, IO_NO_INCREMENT);
02140         return Status;
02141     }
02142     
02143     //
02144     // Query the IRP type
02145     //
02146     switch (Minor)
02147     {
02148         case IRP_MN_START_DEVICE:
02149             
02150             DPRINT1("PnP IRP: %lx\n", Minor);
02151             while (TRUE);
02152             break;
02153             
02154         case IRP_MN_QUERY_STOP_DEVICE:
02155             
02156             DPRINT1("PnP IRP: %lx\n", Minor);
02157             while (TRUE);
02158             break;
02159             
02160         case IRP_MN_CANCEL_STOP_DEVICE:
02161             
02162             DPRINT1("PnP IRP: %lx\n", Minor);
02163             while (TRUE);
02164             break;
02165             
02166         case IRP_MN_STOP_DEVICE:
02167             
02168             DPRINT1("PnP IRP: %lx\n", Minor);
02169             while (TRUE);
02170             break;
02171             
02172         case IRP_MN_QUERY_REMOVE_DEVICE:
02173             
02174             DPRINT1("PnP IRP: %lx\n", Minor);
02175             while (TRUE);
02176             break;
02177             
02178         case IRP_MN_CANCEL_REMOVE_DEVICE:
02179             
02180             DPRINT1("PnP IRP: %lx\n", Minor);
02181             while (TRUE);
02182             break;
02183             
02184         case IRP_MN_REMOVE_DEVICE:
02185 
02186             //
02187             // Remove the proper device
02188             //
02189             if (DeviceExtension->Type == RamdiskBus)
02190             {
02191                 Status = RamdiskRemoveBusDevice(DeviceObject, Irp);
02192 
02193                 //
02194                 // Return here, lower device has already been called
02195                 // And remove lock released. This is needed by the function.
02196                 //
02197                 return Status;
02198             }
02199             else
02200             {
02201                 Status = RamdiskDeleteDiskDevice(DeviceObject, Irp);
02202 
02203                 //
02204                 // Complete the IRP here and return
02205                 // Here again we don't have to release remove lock
02206                 // This has already been done by the function.
02207                 //
02208                 Irp->IoStatus.Status = Status;
02209                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
02210                 return Status;
02211             }
02212 
02213         case IRP_MN_SURPRISE_REMOVAL:
02214             
02215             DPRINT1("PnP IRP: %lx\n", Minor);
02216             while (TRUE);
02217             break;
02218             
02219         case IRP_MN_QUERY_ID:
02220             
02221             //
02222             // Are we a drive?
02223             //
02224             if (DeviceExtension->Type == RamdiskDrive)
02225             {
02226                 DPRINT1("PnP IRP: %lx\n", Minor);
02227                 while (TRUE);
02228             }
02229             break;
02230             
02231         case IRP_MN_QUERY_BUS_INFORMATION:
02232             
02233             //
02234             // Are we a drive?
02235             //
02236             if (DeviceExtension->Type == RamdiskDrive)
02237             {
02238                 DPRINT1("PnP IRP: %lx\n", Minor);
02239                 while (TRUE);
02240             }
02241             break;
02242             
02243         case IRP_MN_EJECT:
02244             
02245             DPRINT1("PnP IRP: %lx\n", Minor);
02246             while (TRUE);
02247             break;
02248             
02249         case IRP_MN_QUERY_DEVICE_TEXT:
02250             
02251             //
02252             // Are we a drive?
02253             //
02254             if (DeviceExtension->Type == RamdiskDrive)
02255             {
02256                 DPRINT1("PnP IRP: %lx\n", Minor);
02257                 while (TRUE);
02258             }
02259             break;
02260             
02261         case IRP_MN_QUERY_DEVICE_RELATIONS:
02262 
02263             //
02264             // Call our main routine
02265             //
02266             Status = RamdiskQueryDeviceRelations(IoStackLocation->
02267                                                  Parameters.
02268                                                  QueryDeviceRelations.Type,
02269                                                  DeviceObject,
02270                                                  Irp);
02271             goto ReleaseAndReturn;
02272             
02273         case IRP_MN_QUERY_CAPABILITIES:
02274             
02275             //
02276             // Are we a drive?
02277             //
02278             if (DeviceExtension->Type == RamdiskDrive)
02279             {
02280                 DPRINT1("PnP IRP: %lx\n", Minor);
02281                 while (TRUE);
02282             }
02283             break;
02284             
02285         case IRP_MN_QUERY_RESOURCES:
02286         case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
02287             
02288             //
02289             // Complete immediately without touching it
02290             //
02291             IoCompleteRequest(Irp, IO_NO_INCREMENT);
02292             goto ReleaseAndReturn;
02293             
02294         default:
02295             
02296             DPRINT1("Illegal IRP: %lx\n", Minor);
02297             break;
02298     }
02299     
02300     //
02301     // Are we the bus?
02302     //
02303     if (DeviceExtension->Type == RamdiskBus)
02304     {
02305         //
02306         // Do we have an attached device?
02307         //
02308         if (DeviceExtension->AttachedDevice)
02309         {
02310             //
02311             // Forward the IRP
02312             //
02313             IoSkipCurrentIrpStackLocation(Irp);
02314             Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
02315         }
02316     }
02317     
02318     //
02319     // Release the lock and return status
02320     //
02321 ReleaseAndReturn:
02322     IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
02323     return Status;
02324 }
02325 
02326 NTSTATUS
02327 NTAPI
02328 RamdiskPower(IN PDEVICE_OBJECT DeviceObject,
02329              IN PIRP Irp)
02330 {
02331     NTSTATUS Status;
02332     PIO_STACK_LOCATION IoStackLocation;
02333     PRAMDISK_BUS_EXTENSION DeviceExtension;
02334 
02335     DeviceExtension = DeviceObject->DeviceExtension;
02336 
02337     //
02338     // If we have a device extension, take extra caution
02339     // with the lower driver
02340     //
02341     if (DeviceExtension != NULL)
02342     {
02343         PoStartNextPowerIrp(Irp);
02344 
02345         //
02346         // Device has not been removed yet, so
02347         // pass to the attached/lower driver
02348         //
02349         if (DeviceExtension->State < RamdiskStateBusRemoved)
02350         {
02351             IoSkipCurrentIrpStackLocation(Irp);
02352             return PoCallDriver(DeviceExtension->AttachedDevice, Irp);
02353         }
02354         //
02355         // Otherwise, simply complete the IRP
02356         // Notifying that deletion is pending
02357         //
02358         else
02359         {
02360             Irp->IoStatus.Status = STATUS_DELETE_PENDING;
02361             IoCompleteRequest(Irp, IO_NO_INCREMENT);
02362             return STATUS_DELETE_PENDING;
02363         }
02364     }
02365 
02366     //
02367     // Get stack and deal with minor functions
02368     //
02369     IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
02370     switch (IoStackLocation->MinorFunction)
02371     {
02372         case IRP_MN_SET_POWER:
02373             //
02374             // If setting device power state
02375             // it's all fine and return success
02376             //
02377             if (DevicePowerState)
02378             {
02379                 Irp->IoStatus.Status = STATUS_SUCCESS;
02380             }
02381 
02382             //
02383             // Get appropriate status for return
02384             //
02385             Status = Irp->IoStatus.Status;
02386             PoStartNextPowerIrp(Irp);
02387             IoCompleteRequest(Irp, IO_NO_INCREMENT);
02388             break;
02389 
02390         case IRP_MN_QUERY_POWER:
02391             //
02392             // We can obviously accept all states
02393             // So just return success
02394             //
02395             Status =
02396             Irp->IoStatus.Status = STATUS_SUCCESS;
02397             PoStartNextPowerIrp(Irp);
02398             IoCompleteRequest(Irp, IO_NO_INCREMENT);
02399             break;
02400 
02401         default:
02402             //
02403             // Just complete and save status for return
02404             //
02405             Status = Irp->IoStatus.Status;
02406             PoStartNextPowerIrp(Irp);
02407             IoCompleteRequest(Irp, IO_NO_INCREMENT);
02408             break;
02409     }
02410 
02411     return Status;
02412 }
02413 
02414 NTSTATUS
02415 NTAPI
02416 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject,
02417                      IN PIRP Irp)
02418 {
02419     NTSTATUS Status;
02420     PRAMDISK_BUS_EXTENSION DeviceExtension;
02421 
02422     DeviceExtension = DeviceObject->DeviceExtension;
02423 
02424     //
02425     // If we have a device extension, forward the IRP
02426     // to the attached device
02427     //
02428     if (DeviceExtension != NULL)
02429     {
02430         IoSkipCurrentIrpStackLocation(Irp);
02431         Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
02432     }
02433     //
02434     // Otherwise just complete the request
02435     // And return the status with which we complete it
02436     //
02437     else
02438     {
02439         Status = Irp->IoStatus.Status;
02440         IoCompleteRequest(Irp, IO_NO_INCREMENT);
02441     }
02442 
02443     return Status;
02444 }
02445 
02446 NTSTATUS
02447 NTAPI
02448 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject,
02449             IN PIRP Irp)
02450 {
02451     NTSTATUS Status;
02452     PRAMDISK_BUS_EXTENSION DeviceExtension;
02453 
02454     DeviceExtension = DeviceObject->DeviceExtension;
02455 
02456     //
02457     // Having a proper device is mandatory
02458     //
02459     if (DeviceExtension->State > RamdiskStateStopped)
02460     {
02461         Status = STATUS_DEVICE_DOES_NOT_EXIST;
02462         goto CompleteIRP;
02463     }
02464 
02465     //
02466     // Acquire the remove lock
02467     //
02468     Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
02469     if (!NT_SUCCESS(Status))
02470     {
02471         goto CompleteIRP;
02472     }
02473 
02474     //
02475     // Queue the IRP for worker
02476     //
02477     Status = SendIrpToThread(DeviceObject, Irp);
02478     if (Status != STATUS_PENDING)
02479     {
02480         goto CompleteIRP;
02481     }
02482 
02483     //
02484     // Release the remove lock
02485     //
02486     IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
02487     goto Quit;
02488 
02489 CompleteIRP:
02490     Irp->IoStatus.Information = 0;
02491     Irp->IoStatus.Status = Status;
02492     IoCompleteRequest(Irp, IO_NO_INCREMENT);
02493 
02494 Quit:
02495     return Status;
02496 }
02497 
02498 NTSTATUS
02499 NTAPI
02500 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
02501                     IN PIRP Irp)
02502 {
02503     NTSTATUS Status;
02504     PRAMDISK_DRIVE_EXTENSION DeviceExtension;
02505 
02506     DeviceExtension = DeviceObject->DeviceExtension;
02507 
02508     //
02509     // Ensure we have drive extension
02510     // Only perform flush on disks that have been created
02511     // from registry entries
02512     //
02513     if (DeviceExtension->Type != RamdiskDrive ||
02514         DeviceExtension->DiskType > RAMDISK_MEMORY_MAPPED_DISK)
02515     {
02516         Irp->IoStatus.Information = 0;
02517         Irp->IoStatus.Status = STATUS_SUCCESS;
02518         IoCompleteRequest(Irp, IO_NO_INCREMENT);
02519         return STATUS_SUCCESS;
02520     }
02521 
02522     //
02523     // Queue the IRP for worker
02524     //
02525     Status = SendIrpToThread(DeviceObject, Irp);
02526     if (Status != STATUS_PENDING)
02527     {
02528         //
02529         // Queueing failed - complete the IRP
02530         // and return failure
02531         //
02532         Irp->IoStatus.Information = 0;
02533         Irp->IoStatus.Status = Status;
02534         IoCompleteRequest(Irp, IO_NO_INCREMENT);
02535     }
02536 
02537     return Status;
02538 }
02539 
02540 VOID
02541 NTAPI
02542 RamdiskUnload(IN PDRIVER_OBJECT DriverObject)
02543 {
02544     //
02545     // Just release registry path if previously allocated
02546     //
02547     if (DriverRegistryPath.Buffer)
02548     {
02549         ExFreePoolWithTag(DriverRegistryPath.Buffer, 'dmaR');
02550     }
02551 }
02552 
02553 NTSTATUS
02554 NTAPI
02555 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject, 
02556                  IN PDEVICE_OBJECT PhysicalDeviceObject)
02557 {
02558     PRAMDISK_BUS_EXTENSION DeviceExtension;
02559     PDEVICE_OBJECT AttachedDevice;
02560     NTSTATUS Status; 
02561     UNICODE_STRING DeviceName;
02562     PDEVICE_OBJECT DeviceObject;
02563     
02564     //
02565     // Only create the bus FDO once
02566     //
02567     if (RamdiskBusFdo) return STATUS_DEVICE_ALREADY_ATTACHED;
02568     
02569     //
02570     // Create the bus FDO
02571     //
02572     RtlInitUnicodeString(&DeviceName, L"\\Device\\Ramdisk");
02573     Status = IoCreateDevice(DriverObject,
02574                             sizeof(RAMDISK_BUS_EXTENSION),
02575                             &DeviceName,
02576                             FILE_DEVICE_BUS_EXTENDER,
02577                             FILE_DEVICE_SECURE_OPEN,
02578                             0,
02579                             &DeviceObject);
02580     if (NT_SUCCESS(Status))
02581     {
02582         //
02583         // Initialize the bus FDO extension
02584         //
02585         DeviceExtension = DeviceObject->DeviceExtension;
02586         RtlZeroMemory(DeviceObject->DeviceExtension,
02587                       sizeof(RAMDISK_BUS_EXTENSION));
02588 
02589         //
02590         // Set bus FDO flags
02591         //
02592         DeviceObject->Flags |= DO_POWER_PAGABLE | DO_DIRECT_IO;
02593 
02594         //
02595         // Setup the bus FDO extension
02596         //
02597         DeviceExtension->Type = RamdiskBus;
02598         ExInitializeFastMutex(&DeviceExtension->DiskListLock);
02599         IoInitializeRemoveLock(&DeviceExtension->RemoveLock,
02600                                'dmaR',
02601                                0,
02602                                1);
02603         InitializeListHead(&DeviceExtension->DiskList);
02604         DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
02605         DeviceExtension->DeviceObject = DeviceObject;
02606 
02607         //
02608         // Register the RAM disk device interface
02609         //
02610         Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
02611                                            &RamdiskBusInterface,
02612                                            NULL,
02613                                            &DeviceExtension->BusDeviceName);
02614         if (!NT_SUCCESS(Status))
02615         {
02616             //
02617             // Fail
02618             //
02619             IoDeleteDevice(DeviceObject);
02620             return Status;
02621         }
02622 
02623         //
02624         // Attach us to the device stack
02625         //
02626         AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject,
02627                                                      PhysicalDeviceObject);
02628         DeviceExtension->AttachedDevice = AttachedDevice;
02629         if (!AttachedDevice)
02630         {
02631             //
02632             // Fail
02633             //
02634             IoSetDeviceInterfaceState(&DeviceExtension->BusDeviceName, 0);
02635             RtlFreeUnicodeString(&DeviceExtension->BusDeviceName);
02636             IoDeleteDevice(DeviceObject);
02637             return STATUS_NO_SUCH_DEVICE;
02638         }
02639 
02640         //
02641         // Bus FDO is initialized
02642         //
02643         RamdiskBusFdo = DeviceObject;
02644 
02645         //
02646         // Loop for loader block
02647         //
02648         if (KeLoaderBlock)
02649         {
02650             //
02651             // Are we being booted from setup? Not yet supported
02652             //
02653             //ASSERT(!KeLoaderBlock->SetupLdrBlock);
02654         }
02655 
02656         //
02657         // All done
02658         //
02659         DeviceObject->Flags &= DO_DEVICE_INITIALIZING;
02660         Status = STATUS_SUCCESS;
02661     }
02662 
02663     //
02664     // Return status
02665     //
02666     return Status;
02667 }
02668 
02669 NTSTATUS
02670 NTAPI
02671 DriverEntry(IN PDRIVER_OBJECT DriverObject,
02672             IN PUNICODE_STRING RegistryPath)
02673 {
02674     PCHAR BootDeviceName, CommandLine;
02675     PDEVICE_OBJECT PhysicalDeviceObject = NULL;
02676     NTSTATUS Status;
02677     DPRINT("RAM Disk Driver Initialized\n");
02678     
02679     //
02680     // Query ramdisk parameters
02681     //
02682     QueryParameters(RegistryPath);
02683     
02684     //
02685     // Save the registry path
02686     //
02687     DriverRegistryPath = *RegistryPath;
02688     DriverRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
02689                                                       RegistryPath->Length +
02690                                                       sizeof(WCHAR),
02691                                                       'dmaR');
02692     if (!DriverRegistryPath.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
02693     RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath);
02694     
02695     //
02696     // Set device routines
02697     //
02698     DriverObject->MajorFunction[IRP_MJ_CREATE] = RamdiskOpenClose;
02699     DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamdiskOpenClose;
02700     DriverObject->MajorFunction[IRP_MJ_READ] = RamdiskReadWrite;
02701     DriverObject->MajorFunction[IRP_MJ_WRITE] = RamdiskReadWrite;
02702     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamdiskDeviceControl;
02703     DriverObject->MajorFunction[IRP_MJ_PNP] = RamdiskPnp;
02704     DriverObject->MajorFunction[IRP_MJ_POWER] = RamdiskPower;
02705     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamdiskSystemControl;
02706     DriverObject->MajorFunction[IRP_MJ_SCSI] = RamdiskScsi;
02707     DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = RamdiskFlushBuffers;
02708     DriverObject->DriverExtension->AddDevice = RamdiskAddDevice;
02709     DriverObject->DriverUnload = RamdiskUnload;
02710     
02711     //
02712     // Check for a loader block
02713     //
02714     if (KeLoaderBlock)
02715     {
02716         //
02717         // Get the boot device name
02718         //
02719         BootDeviceName = KeLoaderBlock->ArcBootDeviceName;
02720         if (BootDeviceName)
02721         {
02722             //
02723             // Check if we're booting from ramdisk
02724             //
02725             if ((strlen(BootDeviceName) >= 10) &&
02726                 !(_strnicmp(BootDeviceName, "ramdisk(0)", 10)))
02727             {
02728                 //
02729                 // We'll have to tell the PnP Manager
02730                 //
02731                 ReportDetectedDevice = TRUE;
02732                 
02733                 //
02734                 // Check for a command line
02735                 //
02736                 CommandLine = KeLoaderBlock->LoadOptions;
02737                 if (CommandLine)
02738                 {
02739                     //
02740                     // Check if this is an ISO boot
02741                     //
02742                     if (strstr(CommandLine, "RDEXPORTASCD"))
02743                     {
02744                         //
02745                         // Remember for later
02746                         //
02747                         ExportBootDiskAsCd = TRUE;
02748                     }
02749                     
02750                     //
02751                     // Check if this is PE boot
02752                     //
02753                     if (strstr(CommandLine, "MININT"))
02754                     {
02755                         //
02756                         // Remember for later
02757                         //
02758                         IsWinPEBoot = TRUE;
02759                     }
02760                 }
02761             }
02762             
02763         }
02764     }
02765     
02766     //
02767     // Installing from Ramdisk isn't supported yet
02768     //
02769     //ASSERT(!KeLoaderBlock->SetupLdrBlock);
02770     
02771     //
02772     // Are we reporting the device
02773     //
02774     if (ReportDetectedDevice)
02775     {
02776         //
02777         // Do it
02778         //
02779         Status = IoReportDetectedDevice(DriverObject,
02780                                         InterfaceTypeUndefined,
02781                                         0xFFFFFFFF,
02782                                         0xFFFFFFFF,
02783                                         NULL,
02784                                         NULL,
02785                                         0,
02786                                         &PhysicalDeviceObject);
02787         if (NT_SUCCESS(Status))
02788         {            
02789             //
02790             // Create the device object
02791             //
02792             Status = RamdiskAddDevice(DriverObject, PhysicalDeviceObject);
02793             if (NT_SUCCESS(Status))
02794             {
02795                 //
02796                 // We're done
02797                 //
02798                 PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
02799                 Status = STATUS_SUCCESS;
02800             }
02801         }
02802     }
02803     else
02804     {
02805         //
02806         // Done
02807         //
02808         Status = STATUS_SUCCESS;
02809     }
02810 
02811     //
02812     // Done
02813     //
02814     return Status;
02815 }

Generated on Sat May 26 2012 04:17:56 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.