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