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 case BusQueryContainerID: 1737 { 1738 /* Nothing to do */ 1739 break; 1740 } 1741 } 1742 1743 Irp->IoStatus.Status = Status; 1744 Irp->IoStatus.Information = (ULONG_PTR)OutputString; 1745 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1746 return Status; 1747 } 1748 1749 NTSTATUS 1750 NTAPI 1751 RamdiskQueryCapabilities(IN PDEVICE_OBJECT DeviceObject, 1752 IN PIRP Irp) 1753 { 1754 NTSTATUS Status; 1755 PIO_STACK_LOCATION IoStackLocation; 1756 PDEVICE_CAPABILITIES DeviceCapabilities; 1757 PRAMDISK_DRIVE_EXTENSION DriveExtension; 1758 1759 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 1760 DeviceCapabilities = IoStackLocation->Parameters.DeviceCapabilities.Capabilities; 1761 DriveExtension = DeviceObject->DeviceExtension; 1762 1763 /* Validate our input buffer */ 1764 if (DeviceCapabilities->Version != 1 || 1765 DeviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES)) 1766 { 1767 Status = STATUS_UNSUCCESSFUL; 1768 } 1769 else 1770 { 1771 /* And set everything we know about our capabilities */ 1772 DeviceCapabilities->Removable = MarkRamdisksAsRemovable; 1773 DeviceCapabilities->UniqueID = TRUE; 1774 DeviceCapabilities->SilentInstall = TRUE; 1775 DeviceCapabilities->RawDeviceOK = TRUE; 1776 DeviceCapabilities->SurpriseRemovalOK = (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK); 1777 DeviceCapabilities->NoDisplayInUI = TRUE; 1778 Status = STATUS_SUCCESS; 1779 } 1780 1781 Irp->IoStatus.Status = Status; 1782 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1783 return Status; 1784 } 1785 1786 NTSTATUS 1787 NTAPI 1788 RamdiskQueryDeviceText(IN PRAMDISK_DRIVE_EXTENSION DriveExtension, 1789 IN PIRP Irp) 1790 { 1791 NTSTATUS Status; 1792 PIO_STACK_LOCATION IoStackLocation; 1793 DEVICE_TEXT_TYPE DeviceTextType; 1794 PWSTR OutputString = NULL; 1795 1796 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 1797 DeviceTextType = IoStackLocation->Parameters.QueryDeviceText.DeviceTextType; 1798 Status = STATUS_SUCCESS; 1799 1800 /* Just copy our constants, according to the input */ 1801 switch (DeviceTextType) 1802 { 1803 case DeviceTextDescription: 1804 { 1805 OutputString = ExAllocatePoolWithTag(PagedPool, sizeof(L"RamDisk"), 'dmaR'); 1806 if (OutputString == NULL) 1807 { 1808 Status = STATUS_INSUFFICIENT_RESOURCES; 1809 break; 1810 } 1811 1812 wcsncpy(OutputString, L"RamDisk", sizeof(L"RamDisk") / sizeof(WCHAR)); 1813 1814 break; 1815 } 1816 1817 case DeviceTextLocationInformation: 1818 { 1819 OutputString = ExAllocatePoolWithTag(PagedPool, sizeof(L"RamDisk\\0"), 'dmaR'); 1820 if (OutputString == NULL) 1821 { 1822 Status = STATUS_INSUFFICIENT_RESOURCES; 1823 break; 1824 } 1825 1826 wcsncpy(OutputString, L"RamDisk\\0", sizeof(L"RamDisk\\0") / sizeof(WCHAR)); 1827 1828 break; 1829 } 1830 } 1831 1832 Irp->IoStatus.Status = Status; 1833 Irp->IoStatus.Information = (ULONG_PTR)OutputString; 1834 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1835 return Status; 1836 } 1837 1838 NTSTATUS 1839 NTAPI 1840 RamdiskQueryBusInformation(IN PDEVICE_OBJECT DeviceObject, 1841 IN PIRP Irp) 1842 { 1843 PPNP_BUS_INFORMATION PnpBusInfo; 1844 NTSTATUS Status = STATUS_SUCCESS; 1845 1846 /* Allocate output memory */ 1847 PnpBusInfo = ExAllocatePoolWithTag(PagedPool, sizeof(*PnpBusInfo), 'dmaR'); 1848 if (PnpBusInfo == NULL) 1849 { 1850 Status = STATUS_INSUFFICIENT_RESOURCES; 1851 } 1852 else 1853 { 1854 /* Copy our bus GUID and set our legacy type */ 1855 RtlCopyMemory(&PnpBusInfo->BusTypeGuid, &GUID_BUS_TYPE_RAMDISK, sizeof(GUID)); 1856 PnpBusInfo->LegacyBusType = PNPBus; 1857 PnpBusInfo->BusNumber = 0; 1858 } 1859 1860 Irp->IoStatus.Status = Status; 1861 Irp->IoStatus.Information = (ULONG_PTR)PnpBusInfo; 1862 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1863 return Status; 1864 } 1865 1866 NTSTATUS 1867 NTAPI 1868 RamdiskIoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, 1869 IN PIRP Irp, 1870 IN PVOID Context) 1871 1872 { 1873 /* Just set the event to unlock caller */ 1874 KeSetEvent((PKEVENT)Context, 0, FALSE); 1875 1876 return STATUS_MORE_PROCESSING_REQUIRED; 1877 } 1878 1879 NTSTATUS 1880 NTAPI 1881 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject, 1882 IN PIRP Irp) 1883 { 1884 PIO_STACK_LOCATION IoStackLocation; 1885 PRAMDISK_BUS_EXTENSION DeviceExtension; 1886 NTSTATUS Status; 1887 UCHAR Minor; 1888 KEVENT Event; 1889 1890 /* Get the device extension and stack location */ 1891 DeviceExtension = DeviceObject->DeviceExtension; 1892 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 1893 Minor = IoStackLocation->MinorFunction; 1894 1895 /* Check if the bus is removed */ 1896 if (DeviceExtension->State == RamdiskStateBusRemoved) 1897 { 1898 /* Only remove-device and query-id are allowed */ 1899 if ((Minor != IRP_MN_REMOVE_DEVICE) && (Minor != IRP_MN_QUERY_ID)) 1900 { 1901 /* Fail anything else */ 1902 Status = STATUS_NO_SUCH_DEVICE; 1903 Irp->IoStatus.Status = Status; 1904 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1905 return Status; 1906 } 1907 } 1908 1909 /* Acquire the remove lock */ 1910 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp); 1911 if (!NT_SUCCESS(Status)) 1912 { 1913 /* Fail the IRP */ 1914 Irp->IoStatus.Information = 0; 1915 Irp->IoStatus.Status = Status; 1916 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1917 return Status; 1918 } 1919 1920 /* Query the IRP type */ 1921 switch (Minor) 1922 { 1923 case IRP_MN_START_DEVICE: 1924 { 1925 if (DeviceExtension->Type == RamdiskDrive) 1926 { 1927 ULONG ResultLength; 1928 DEVICE_INSTALL_STATE InstallState; 1929 PRAMDISK_DRIVE_EXTENSION DriveExtension = (PRAMDISK_DRIVE_EXTENSION)DeviceExtension; 1930 1931 /* If we already have a drive name, free it */ 1932 if (DriveExtension->DriveDeviceName.Buffer) 1933 { 1934 ExFreePool(DriveExtension->DriveDeviceName.Buffer); 1935 } 1936 1937 /* Register our device interface */ 1938 if (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK) 1939 { 1940 Status = IoRegisterDeviceInterface(DeviceObject, 1941 &GUID_DEVINTERFACE_VOLUME, 1942 NULL, 1943 &DriveExtension->DriveDeviceName); 1944 } 1945 else 1946 { 1947 Status = IoRegisterDeviceInterface(DeviceObject, 1948 &RamdiskDiskInterface, 1949 NULL, 1950 &DriveExtension->DriveDeviceName); 1951 } 1952 1953 /* If we were asked not to assign a drive letter or if getting 1954 * a name failed, just return saying we're now started */ 1955 if (DriveExtension->DiskOptions.NoDriveLetter || 1956 DriveExtension->DriveDeviceName.Buffer == NULL) 1957 { 1958 DriveExtension->State = RamdiskStateStarted; 1959 Irp->IoStatus.Status = Status; 1960 break; 1961 } 1962 1963 /* Now get our installation state */ 1964 Status = IoGetDeviceProperty(DeviceObject, 1965 DevicePropertyInstallState, 1966 sizeof(InstallState), 1967 &InstallState, 1968 &ResultLength); 1969 /* If querying the information failed, assume success */ 1970 if (!NT_SUCCESS(Status)) 1971 { 1972 InstallState = InstallStateInstalled; 1973 } 1974 1975 /* If we were properly installed, then, enable the interface */ 1976 if (InstallState == InstallStateInstalled) 1977 { 1978 Status = IoSetDeviceInterfaceState(&DriveExtension->DriveDeviceName, TRUE); 1979 } 1980 1981 /* We're fine & up */ 1982 DriveExtension->State = RamdiskStateStarted; 1983 Irp->IoStatus.Status = Status; 1984 break; 1985 } 1986 1987 /* Prepare next stack to pass it down */ 1988 IoCopyCurrentIrpStackLocationToNext(Irp); 1989 1990 /* Initialize our notification event & our completion routine */ 1991 KeInitializeEvent(&Event, NotificationEvent, FALSE); 1992 IoSetCompletionRoutine(Irp, RamdiskIoCompletionRoutine, &Event, TRUE, TRUE, TRUE); 1993 1994 /* Call lower driver */ 1995 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); 1996 if (Status == STATUS_PENDING) 1997 { 1998 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 1999 Status = Irp->IoStatus.Status; 2000 } 2001 2002 /* If it succeed to start then enable ourselves and we're up! */ 2003 if (NT_SUCCESS(Status)) 2004 { 2005 Status = IoSetDeviceInterfaceState(&DeviceExtension->DriveDeviceName, TRUE); 2006 DeviceExtension->State = RamdiskStateStarted; 2007 } 2008 2009 Irp->IoStatus.Status = Status; 2010 break; 2011 } 2012 2013 case IRP_MN_QUERY_STOP_DEVICE: 2014 case IRP_MN_CANCEL_STOP_DEVICE: 2015 case IRP_MN_STOP_DEVICE: 2016 case IRP_MN_QUERY_REMOVE_DEVICE: 2017 case IRP_MN_CANCEL_REMOVE_DEVICE: 2018 { 2019 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor); 2020 break; 2021 } 2022 2023 case IRP_MN_REMOVE_DEVICE: 2024 { 2025 /* Remove the proper device */ 2026 if (DeviceExtension->Type == RamdiskBus) 2027 { 2028 Status = RamdiskRemoveBusDevice(DeviceObject, Irp); 2029 2030 /* Return here, lower device has already been called 2031 * And remove lock released. This is needed by the function. */ 2032 return Status; 2033 } 2034 else 2035 { 2036 Status = RamdiskDeleteDiskDevice(DeviceObject, Irp); 2037 2038 /* Complete the IRP here and return 2039 * Here again we don't have to release remove lock 2040 * This has already been done by the function. */ 2041 Irp->IoStatus.Status = Status; 2042 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2043 return Status; 2044 } 2045 } 2046 2047 case IRP_MN_SURPRISE_REMOVAL: 2048 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor); 2049 break; 2050 2051 case IRP_MN_QUERY_ID: 2052 { 2053 /* Are we a drive? */ 2054 if (DeviceExtension->Type == RamdiskDrive) 2055 { 2056 Status = RamdiskQueryId((PRAMDISK_DRIVE_EXTENSION)DeviceExtension, Irp); 2057 } 2058 break; 2059 } 2060 2061 case IRP_MN_QUERY_BUS_INFORMATION: 2062 { 2063 /* Are we a drive? */ 2064 if (DeviceExtension->Type == RamdiskDrive) 2065 { 2066 Status = RamdiskQueryBusInformation(DeviceObject, Irp); 2067 } 2068 break; 2069 } 2070 2071 case IRP_MN_EJECT: 2072 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor); 2073 break; 2074 2075 case IRP_MN_QUERY_DEVICE_TEXT: 2076 { 2077 /* Are we a drive? */ 2078 if (DeviceExtension->Type == RamdiskDrive) 2079 { 2080 Status = RamdiskQueryDeviceText((PRAMDISK_DRIVE_EXTENSION)DeviceExtension, Irp); 2081 } 2082 break; 2083 } 2084 2085 case IRP_MN_QUERY_DEVICE_RELATIONS: 2086 { 2087 /* Call our main routine */ 2088 Status = RamdiskQueryDeviceRelations(IoStackLocation-> 2089 Parameters. 2090 QueryDeviceRelations.Type, 2091 DeviceObject, 2092 Irp); 2093 goto ReleaseAndReturn; 2094 } 2095 2096 case IRP_MN_QUERY_CAPABILITIES: 2097 { 2098 /* Are we a drive? */ 2099 if (DeviceExtension->Type == RamdiskDrive) 2100 { 2101 Status = RamdiskQueryCapabilities(DeviceObject, Irp); 2102 } 2103 break; 2104 } 2105 2106 case IRP_MN_QUERY_RESOURCES: 2107 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 2108 { 2109 /* Complete immediately without touching it */ 2110 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2111 goto ReleaseAndReturn; 2112 } 2113 2114 default: 2115 DPRINT1("Illegal IRP: %lx\n", Minor); 2116 break; 2117 } 2118 2119 /* Are we the bus? */ 2120 if (DeviceExtension->Type == RamdiskBus) 2121 { 2122 /* Do we have an attached device? */ 2123 if (DeviceExtension->AttachedDevice) 2124 { 2125 /* Forward the IRP */ 2126 IoSkipCurrentIrpStackLocation(Irp); 2127 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); 2128 } 2129 } 2130 2131 /* Release the lock and return status */ 2132 ReleaseAndReturn: 2133 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp); 2134 return Status; 2135 } 2136 2137 NTSTATUS 2138 NTAPI 2139 RamdiskPower(IN PDEVICE_OBJECT DeviceObject, 2140 IN PIRP Irp) 2141 { 2142 NTSTATUS Status; 2143 PIO_STACK_LOCATION IoStackLocation; 2144 PRAMDISK_BUS_EXTENSION DeviceExtension; 2145 2146 DeviceExtension = DeviceObject->DeviceExtension; 2147 2148 /* If we have a device extension, take extra caution with the lower driver */ 2149 if (DeviceExtension != NULL) 2150 { 2151 PoStartNextPowerIrp(Irp); 2152 2153 /* Device has not been removed yet, so pass to the attached/lower driver */ 2154 if (DeviceExtension->State < RamdiskStateBusRemoved) 2155 { 2156 IoSkipCurrentIrpStackLocation(Irp); 2157 return PoCallDriver(DeviceExtension->AttachedDevice, Irp); 2158 } 2159 /* Otherwise, simply complete the IRP notifying that deletion is pending */ 2160 else 2161 { 2162 Irp->IoStatus.Status = STATUS_DELETE_PENDING; 2163 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2164 return STATUS_DELETE_PENDING; 2165 } 2166 } 2167 2168 /* Get stack and deal with minor functions */ 2169 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 2170 switch (IoStackLocation->MinorFunction) 2171 { 2172 case IRP_MN_SET_POWER: 2173 { 2174 /* If setting device power state it's all fine and return success */ 2175 if (DevicePowerState) 2176 { 2177 Irp->IoStatus.Status = STATUS_SUCCESS; 2178 } 2179 2180 /* Get appropriate status for return */ 2181 Status = Irp->IoStatus.Status; 2182 PoStartNextPowerIrp(Irp); 2183 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2184 break; 2185 } 2186 2187 case IRP_MN_QUERY_POWER: 2188 { 2189 /* We can obviously accept all states so just return success */ 2190 Status = Irp->IoStatus.Status = STATUS_SUCCESS; 2191 PoStartNextPowerIrp(Irp); 2192 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2193 break; 2194 } 2195 2196 default: 2197 { 2198 /* Just complete and save status for return */ 2199 Status = Irp->IoStatus.Status; 2200 PoStartNextPowerIrp(Irp); 2201 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2202 break; 2203 } 2204 } 2205 2206 return Status; 2207 } 2208 2209 NTSTATUS 2210 NTAPI 2211 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject, 2212 IN PIRP Irp) 2213 { 2214 NTSTATUS Status; 2215 PRAMDISK_BUS_EXTENSION DeviceExtension; 2216 2217 DeviceExtension = DeviceObject->DeviceExtension; 2218 2219 /* If we have a device extension, forward the IRP to the attached device */ 2220 if (DeviceExtension != NULL) 2221 { 2222 IoSkipCurrentIrpStackLocation(Irp); 2223 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); 2224 } 2225 /* Otherwise just complete the request 2226 * And return the status with which we complete it */ 2227 else 2228 { 2229 Status = Irp->IoStatus.Status; 2230 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2231 } 2232 2233 return Status; 2234 } 2235 2236 NTSTATUS 2237 NTAPI 2238 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject, 2239 IN PIRP Irp) 2240 { 2241 NTSTATUS Status; 2242 PRAMDISK_BUS_EXTENSION DeviceExtension; 2243 2244 DeviceExtension = DeviceObject->DeviceExtension; 2245 2246 /* Having a proper device is mandatory */ 2247 if (DeviceExtension->State > RamdiskStateStopped) 2248 { 2249 Status = STATUS_DEVICE_DOES_NOT_EXIST; 2250 goto CompleteIRP; 2251 } 2252 2253 /* Acquire the remove lock */ 2254 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp); 2255 if (!NT_SUCCESS(Status)) 2256 { 2257 goto CompleteIRP; 2258 } 2259 2260 /* Queue the IRP for worker */ 2261 Status = SendIrpToThread(DeviceObject, Irp); 2262 if (Status != STATUS_PENDING) 2263 { 2264 goto CompleteIRP; 2265 } 2266 2267 /* Release the remove lock */ 2268 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp); 2269 goto Quit; 2270 2271 CompleteIRP: 2272 Irp->IoStatus.Information = 0; 2273 Irp->IoStatus.Status = Status; 2274 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2275 2276 Quit: 2277 return Status; 2278 } 2279 2280 NTSTATUS 2281 NTAPI 2282 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject, 2283 IN PIRP Irp) 2284 { 2285 NTSTATUS Status; 2286 PRAMDISK_DRIVE_EXTENSION DeviceExtension; 2287 2288 DeviceExtension = DeviceObject->DeviceExtension; 2289 2290 /* Ensure we have drive extension 2291 * Only perform flush on disks that have been created 2292 * from registry entries */ 2293 if (DeviceExtension->Type != RamdiskDrive || 2294 DeviceExtension->DiskType > RAMDISK_MEMORY_MAPPED_DISK) 2295 { 2296 Irp->IoStatus.Information = 0; 2297 Irp->IoStatus.Status = STATUS_SUCCESS; 2298 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2299 return STATUS_SUCCESS; 2300 } 2301 2302 /* Queue the IRP for worker */ 2303 Status = SendIrpToThread(DeviceObject, Irp); 2304 if (Status != STATUS_PENDING) 2305 { 2306 /* Queuing failed - complete the IRP and return failure */ 2307 Irp->IoStatus.Information = 0; 2308 Irp->IoStatus.Status = Status; 2309 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2310 } 2311 2312 return Status; 2313 } 2314 2315 VOID 2316 NTAPI 2317 RamdiskUnload(IN PDRIVER_OBJECT DriverObject) 2318 { 2319 /* Just release registry path if previously allocated */ 2320 if (DriverRegistryPath.Buffer) 2321 { 2322 ExFreePoolWithTag(DriverRegistryPath.Buffer, 'dmaR'); 2323 } 2324 } 2325 2326 NTSTATUS 2327 NTAPI 2328 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject, 2329 IN PDEVICE_OBJECT PhysicalDeviceObject) 2330 { 2331 PRAMDISK_BUS_EXTENSION DeviceExtension; 2332 PDEVICE_OBJECT AttachedDevice; 2333 NTSTATUS Status; 2334 UNICODE_STRING DeviceName; 2335 PDEVICE_OBJECT DeviceObject; 2336 2337 /* Only create the bus FDO once */ 2338 if (RamdiskBusFdo) return STATUS_DEVICE_ALREADY_ATTACHED; 2339 2340 /* Create the bus FDO */ 2341 RtlInitUnicodeString(&DeviceName, L"\\Device\\Ramdisk"); 2342 Status = IoCreateDevice(DriverObject, 2343 sizeof(RAMDISK_BUS_EXTENSION), 2344 &DeviceName, 2345 FILE_DEVICE_BUS_EXTENDER, 2346 FILE_DEVICE_SECURE_OPEN, 2347 0, 2348 &DeviceObject); 2349 if (NT_SUCCESS(Status)) 2350 { 2351 /* Initialize the bus FDO extension */ 2352 DeviceExtension = DeviceObject->DeviceExtension; 2353 RtlZeroMemory(DeviceExtension, sizeof(*DeviceExtension)); 2354 2355 /* Set bus FDO flags */ 2356 DeviceObject->Flags |= DO_POWER_PAGABLE | DO_DIRECT_IO; 2357 2358 /* Setup the bus FDO extension */ 2359 DeviceExtension->Type = RamdiskBus; 2360 ExInitializeFastMutex(&DeviceExtension->DiskListLock); 2361 IoInitializeRemoveLock(&DeviceExtension->RemoveLock, 'dmaR', 1, 0); 2362 InitializeListHead(&DeviceExtension->DiskList); 2363 DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; 2364 DeviceExtension->DeviceObject = DeviceObject; 2365 2366 /* Register the RAM disk device interface */ 2367 Status = IoRegisterDeviceInterface(PhysicalDeviceObject, 2368 &RamdiskBusInterface, 2369 NULL, 2370 &DeviceExtension->BusDeviceName); 2371 if (!NT_SUCCESS(Status)) 2372 { 2373 /* Fail */ 2374 IoDeleteDevice(DeviceObject); 2375 return Status; 2376 } 2377 2378 /* Attach us to the device stack */ 2379 AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject, 2380 PhysicalDeviceObject); 2381 DeviceExtension->AttachedDevice = AttachedDevice; 2382 if (!AttachedDevice) 2383 { 2384 /* Fail */ 2385 IoSetDeviceInterfaceState(&DeviceExtension->BusDeviceName, 0); 2386 RtlFreeUnicodeString(&DeviceExtension->BusDeviceName); 2387 IoDeleteDevice(DeviceObject); 2388 return STATUS_NO_SUCH_DEVICE; 2389 } 2390 2391 /* Bus FDO is initialized */ 2392 RamdiskBusFdo = DeviceObject; 2393 2394 /* Loop for loader block */ 2395 if (KeLoaderBlock) 2396 { 2397 /* Are we being booted from setup? Not yet supported */ 2398 if (KeLoaderBlock->SetupLdrBlock) 2399 DPRINT1("FIXME: RamdiskAddDevice is UNSUPPORTED when being started from SETUPLDR!\n"); 2400 // ASSERT(!KeLoaderBlock->SetupLdrBlock); 2401 } 2402 2403 /* All done */ 2404 DeviceObject->Flags &= DO_DEVICE_INITIALIZING; 2405 Status = STATUS_SUCCESS; 2406 } 2407 2408 /* Return status */ 2409 return Status; 2410 } 2411 2412 NTSTATUS 2413 NTAPI 2414 DriverEntry(IN PDRIVER_OBJECT DriverObject, 2415 IN PUNICODE_STRING RegistryPath) 2416 { 2417 PCHAR BootDeviceName, CommandLine; 2418 PDEVICE_OBJECT PhysicalDeviceObject = NULL; 2419 NTSTATUS Status; 2420 DPRINT("RAM Disk Driver Initialized\n"); 2421 2422 /* Save the registry path */ 2423 DriverRegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL); 2424 DriverRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, 2425 DriverRegistryPath.MaximumLength, 2426 'dmaR'); 2427 if (!DriverRegistryPath.Buffer) 2428 { 2429 return STATUS_INSUFFICIENT_RESOURCES; 2430 } 2431 RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath); 2432 2433 /* Query ramdisk parameters */ 2434 QueryParameters(&DriverRegistryPath); 2435 2436 /* Set device routines */ 2437 DriverObject->MajorFunction[IRP_MJ_CREATE] = RamdiskOpenClose; 2438 DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamdiskOpenClose; 2439 DriverObject->MajorFunction[IRP_MJ_READ] = RamdiskReadWrite; 2440 DriverObject->MajorFunction[IRP_MJ_WRITE] = RamdiskReadWrite; 2441 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamdiskDeviceControl; 2442 DriverObject->MajorFunction[IRP_MJ_PNP] = RamdiskPnp; 2443 DriverObject->MajorFunction[IRP_MJ_POWER] = RamdiskPower; 2444 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamdiskSystemControl; 2445 DriverObject->MajorFunction[IRP_MJ_SCSI] = RamdiskScsi; 2446 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = RamdiskFlushBuffers; 2447 DriverObject->DriverExtension->AddDevice = RamdiskAddDevice; 2448 DriverObject->DriverUnload = RamdiskUnload; 2449 2450 /* Check for a loader block */ 2451 if (KeLoaderBlock) 2452 { 2453 /* Get the boot device name */ 2454 BootDeviceName = KeLoaderBlock->ArcBootDeviceName; 2455 if (BootDeviceName) 2456 { 2457 /* Check if we're booting from ramdisk */ 2458 if ((strlen(BootDeviceName) >= 10) && 2459 !(_strnicmp(BootDeviceName, "ramdisk(0)", 10))) 2460 { 2461 /* We'll have to tell the PnP Manager */ 2462 ReportDetectedDevice = TRUE; 2463 2464 /* Check for a command line */ 2465 CommandLine = KeLoaderBlock->LoadOptions; 2466 if (CommandLine) 2467 { 2468 /* Check if this is an ISO boot */ 2469 if (strstr(CommandLine, "RDEXPORTASCD")) 2470 { 2471 /* Remember for later */ 2472 ExportBootDiskAsCd = TRUE; 2473 } 2474 2475 /* Check if this is PE boot */ 2476 if (strstr(CommandLine, "MININT")) 2477 { 2478 /* Remember for later */ 2479 IsWinPEBoot = TRUE; 2480 } 2481 } 2482 } 2483 2484 } 2485 } 2486 2487 /* Installing from Ramdisk isn't supported yet */ 2488 if (KeLoaderBlock->SetupLdrBlock) 2489 DPRINT1("FIXME: Installing from RamDisk is UNSUPPORTED!\n"); 2490 // ASSERT(!KeLoaderBlock->SetupLdrBlock); 2491 2492 /* Are we reporting the device */ 2493 if (ReportDetectedDevice) 2494 { 2495 /* Do it */ 2496 Status = IoReportDetectedDevice(DriverObject, 2497 InterfaceTypeUndefined, 2498 0xFFFFFFFF, 2499 0xFFFFFFFF, 2500 NULL, 2501 NULL, 2502 0, 2503 &PhysicalDeviceObject); 2504 if (NT_SUCCESS(Status)) 2505 { 2506 /* Create the device object */ 2507 Status = RamdiskAddDevice(DriverObject, PhysicalDeviceObject); 2508 if (NT_SUCCESS(Status)) 2509 { 2510 /* We are done */ 2511 PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 2512 Status = STATUS_SUCCESS; 2513 } 2514 } 2515 } 2516 else 2517 { 2518 /* Done */ 2519 Status = STATUS_SUCCESS; 2520 } 2521 2522 /* Done */ 2523 return Status; 2524 } 2525