Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenramdisk.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
1.7.6.1
|