|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: ramdisk.c ! 8: ! 9: Abstract: ! 10: ! 11: This is the Ram Disk driver. ! 12: ! 13: Author: ! 14: ! 15: Robert Nelson (RobertN) 10-Mar-1993. ! 16: ! 17: Environment: ! 18: ! 19: Kernel mode only. ! 20: ! 21: Notes: ! 22: ! 23: Revision History: ! 24: Added the IOCTL_DISK_GET_PARTITION_INFO query to make it work with NTFS ! 25: driver loaded (thanks Robert Vierthaler (RobertVi)). ! 26: ! 27: --*/ ! 28: ! 29: ! 30: // ! 31: // Include files. ! 32: // ! 33: ! 34: #include <ntddk.h> // various NT definitions ! 35: #include <ntdddisk.h> // disk device driver I/O control codes ! 36: #include <ntiologc.h> ! 37: ! 38: #include <string.h> ! 39: ! 40: #include "ramdisk.h" ! 41: ! 42: #if DBG ! 43: ULONG RamDiskDebugLevel = 0; ! 44: #endif ! 45: ! 46: ! 47: NTSTATUS ! 48: DriverEntry( ! 49: IN OUT PDRIVER_OBJECT DriverObject, ! 50: IN PUNICODE_STRING RegistryPath ! 51: ) ! 52: /*++ ! 53: ! 54: Routine Description: ! 55: This routine is called by the Operating System to initialize the driver. ! 56: ! 57: It fills in the dispatch entry points in the driver object. Then ! 58: RamDiskInitializeDisk is called to create the device object and complete ! 59: the initialization. ! 60: ! 61: Arguments: ! 62: DriverObject - a pointer to the object that represents this device ! 63: driver. ! 64: ! 65: RegistryPath - a pointer to our Services key in the registry. ! 66: ! 67: Return Value: ! 68: STATUS_SUCCESS if this disk is initialized; an error otherwise. ! 69: ! 70: --*/ ! 71: ! 72: { ! 73: NTSTATUS ntStatus; ! 74: UNICODE_STRING paramPath; ! 75: static WCHAR SubKeyString[] = L"\\Parameters"; ! 76: ! 77: // ! 78: // The registry path parameter points to our key, we will append ! 79: // the Parameters key and look for any additional configuration items ! 80: // there. We add room for a trailing NUL for those routines which ! 81: // require it. ! 82: ! 83: paramPath.MaximumLength = RegistryPath->Length + sizeof(SubKeyString); ! 84: paramPath.Buffer = ExAllocatePool(PagedPool, paramPath.MaximumLength); ! 85: ! 86: if (paramPath.Buffer != NULL) ! 87: { ! 88: RtlMoveMemory( ! 89: paramPath.Buffer, RegistryPath->Buffer, RegistryPath->Length); ! 90: ! 91: RtlMoveMemory( ! 92: ¶mPath.Buffer[RegistryPath->Length / 2], SubKeyString, ! 93: sizeof(SubKeyString)); ! 94: ! 95: paramPath.Length = paramPath.MaximumLength; ! 96: } ! 97: else ! 98: { ! 99: return STATUS_INSUFFICIENT_RESOURCES; ! 100: } ! 101: ! 102: #if DBG ! 103: { ! 104: // ! 105: // We use this to query into the registry as to whether we ! 106: // should break at driver entry. ! 107: // ! 108: ! 109: RTL_QUERY_REGISTRY_TABLE paramTable[3]; ! 110: ULONG zero = 0; ! 111: ! 112: ULONG debugLevel = 0; ! 113: ULONG shouldBreak = 0; ! 114: ! 115: RtlZeroMemory(¶mTable[0], sizeof(paramTable)); ! 116: ! 117: paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 118: paramTable[0].Name = L"BreakOnEntry"; ! 119: paramTable[0].EntryContext = &shouldBreak; ! 120: paramTable[0].DefaultType = REG_DWORD; ! 121: paramTable[0].DefaultData = &zero; ! 122: paramTable[0].DefaultLength = sizeof(ULONG); ! 123: ! 124: paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 125: paramTable[1].Name = L"DebugLevel"; ! 126: paramTable[1].EntryContext = &debugLevel; ! 127: paramTable[1].DefaultType = REG_DWORD; ! 128: paramTable[1].DefaultData = &zero; ! 129: paramTable[1].DefaultLength = sizeof(ULONG); ! 130: ! 131: if (!NT_SUCCESS(RtlQueryRegistryValues( ! 132: RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, ! 133: paramPath.Buffer, ¶mTable[0], NULL, NULL))) ! 134: { ! 135: shouldBreak = 0; ! 136: debugLevel = 0; ! 137: } ! 138: ! 139: RamDiskDebugLevel = debugLevel; ! 140: ! 141: if (shouldBreak) ! 142: { ! 143: DbgBreakPoint(); ! 144: } ! 145: } ! 146: #endif ! 147: ! 148: // ! 149: // Initialize the driver object with this driver's entry points. ! 150: // ! 151: ! 152: DriverObject->MajorFunction[IRP_MJ_CREATE] = RamDiskCreateClose; ! 153: DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamDiskCreateClose; ! 154: DriverObject->MajorFunction[IRP_MJ_READ] = RamDiskReadWrite; ! 155: DriverObject->MajorFunction[IRP_MJ_WRITE] = RamDiskReadWrite; ! 156: DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamDiskDeviceControl; ! 157: ! 158: // ! 159: // We'll enable unload when the Filesystem drivers support it ! 160: // ! 161: // DriverObject->DriverUnload = RamDiskUnloadDriver; ! 162: ! 163: ntStatus = RamDiskInitializeDisk(DriverObject, ¶mPath); ! 164: ! 165: // ! 166: // We don't need that path anymore. ! 167: // ! 168: ! 169: if (paramPath.Buffer) ! 170: { ! 171: ExFreePool( paramPath.Buffer ); ! 172: } ! 173: ! 174: return ntStatus; ! 175: } ! 176: ! 177: NTSTATUS ! 178: RamDiskInitializeDisk( ! 179: IN PDRIVER_OBJECT DriverObject, ! 180: IN PUNICODE_STRING ParamPath ! 181: ) ! 182: ! 183: /*++ ! 184: ! 185: Routine Description: ! 186: This routine is called at initialization time by DriverEntry(). ! 187: ! 188: It creates and initializes a device object for the disk. Memory for the ! 189: Ram Disk is allocated from the non-paged Pool. RamDiskFormatFat is called ! 190: to create a FAT filesystem in the memory buffer allocated. ! 191: ! 192: Two parameters may be configured using the registry. DiskSize specifies ! 193: the desired size (in bytes). If the requested memory is not available in ! 194: the nonpaged pool then STATUS_INSUFFICIENT_RESOURCES is returned. The ! 195: default value is 0x00100000 (1MB). ! 196: ! 197: DriveLetter is used to indicate the drive letter for the RamDisk. The ! 198: string must be a letter, optionally followed by :. ! 199: ! 200: Arguments: ! 201: DriverObject - a pointer to the object that represents this device ! 202: driver. ! 203: ! 204: ParamPath - a pointer to the Parameters key under our key in the Services ! 205: section of the registry. ! 206: ! 207: Return Value: ! 208: STATUS_SUCCESS if this disk is initialized; an error otherwise. ! 209: ! 210: --*/ ! 211: ! 212: { ! 213: STRING ntNameString; // NT Device Name "\Device\RamDisk" ! 214: UNICODE_STRING ntUnicodeString; // Unicode version of ntNameString ! 215: UNICODE_STRING Win32PathString; // Win32 Name "\DosDevices\Z:" ! 216: ! 217: PDEVICE_OBJECT deviceObject = NULL; // ptr to device object ! 218: PRAMDISK_EXTENSION diskExtension = NULL; // ptr to device extension ! 219: ! 220: NTSTATUS ntStatus; ! 221: ! 222: RTL_QUERY_REGISTRY_TABLE paramTable[3]; ! 223: ! 224: ULONG defaultDiskSize = DEFAULT_DISK_SIZE; ! 225: ULONG diskSize = DEFAULT_DISK_SIZE; ! 226: UNICODE_STRING driveLetterString; ! 227: WCHAR driveLetterBuffer[sizeof(WCHAR) * 10]; ! 228: ! 229: RtlInitUnicodeString( &driveLetterString, NULL ); ! 230: ! 231: driveLetterString.MaximumLength = sizeof(WCHAR) * 9; ! 232: driveLetterString.Buffer = driveLetterBuffer; ! 233: ! 234: RtlZeroMemory(¶mTable[0], sizeof(paramTable)); ! 235: RtlZeroMemory(&driveLetterBuffer[0], sizeof(driveLetterBuffer)); ! 236: ! 237: paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 238: paramTable[0].Name = L"DiskSize"; ! 239: paramTable[0].EntryContext = &diskSize; ! 240: paramTable[0].DefaultType = REG_DWORD; ! 241: paramTable[0].DefaultData = &defaultDiskSize; ! 242: paramTable[0].DefaultLength = sizeof(ULONG); ! 243: ! 244: paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 245: paramTable[1].Name = L"DriveLetter"; ! 246: paramTable[1].EntryContext = &driveLetterString; ! 247: ! 248: if (!NT_SUCCESS(RtlQueryRegistryValues( ! 249: RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, ! 250: ParamPath->Buffer, ¶mTable[0], NULL, NULL))) ! 251: { ! 252: diskSize = DEFAULT_DISK_SIZE; ! 253: } ! 254: ! 255: ASSERT(sizeof(BOOT_SECTOR) == 512); ! 256: ! 257: RtlInitString( &ntNameString, "\\Device\\Ramdisk" ); ! 258: ! 259: ntStatus = RtlAnsiStringToUnicodeString( ! 260: &ntUnicodeString, &ntNameString, TRUE ); ! 261: ! 262: if ( !NT_SUCCESS( ntStatus ) ) ! 263: { ! 264: RamDiskDump( ! 265: RAMDERRORS, ("RAMDISK: Couldn't create the unicode device name\n")); ! 266: goto RamDiskInitializeDiskExit; ! 267: } ! 268: ! 269: ntStatus = IoCreateDevice( ! 270: DriverObject, // Our Driver Object ! 271: sizeof( RAMDISK_EXTENSION ), // Size of state information ! 272: &ntUnicodeString, // Device name "\Device\RamDisk" ! 273: FILE_DEVICE_VIRTUAL_DISK, // Device type ! 274: 0, // Device characteristics ! 275: FALSE, // Exclusive device ! 276: &deviceObject ); // Returned ptr to Device Object ! 277: ! 278: if ( !NT_SUCCESS( ntStatus ) ) ! 279: { ! 280: RamDiskDump( ! 281: RAMDERRORS, ("RAMDISK: Couldn't create the device object\n")); ! 282: goto RamDiskInitializeDiskExit; ! 283: } ! 284: ! 285: // ! 286: // Initialize device object and extension. ! 287: // ! 288: ! 289: deviceObject->Flags |= DO_DIRECT_IO; ! 290: deviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; ! 291: ! 292: diskExtension = (PRAMDISK_EXTENSION)deviceObject->DeviceExtension; ! 293: ! 294: RtlInitUnicodeString( &diskExtension->Win32NameString, NULL ); ! 295: ! 296: // ! 297: // Allocate and zero the memory disk image. ! 298: // ! 299: ! 300: diskExtension->DiskImage = ExAllocatePool( NonPagedPool, diskSize ); ! 301: ! 302: if ( diskExtension->DiskImage == NULL ) ! 303: { ! 304: RamDiskDump( ! 305: RAMDERRORS, ("RAMDISK: Can't allocate memory for disk image\n") ); ! 306: goto RamDiskInitializeDiskExit; ! 307: } ! 308: ! 309: RtlZeroMemory( diskExtension->DiskImage, diskSize ); ! 310: ! 311: // ! 312: // Fill in device-specific numbers based on disk size obtained from the ! 313: // configuration manager. ! 314: // ! 315: ! 316: diskExtension->DeviceObject = deviceObject; ! 317: diskExtension->DiskLength = diskSize; ! 318: diskExtension->BytesPerSector = 512; ! 319: diskExtension->SectorsPerTrack = 32; ! 320: diskExtension->TracksPerCylinder = 2; ! 321: diskExtension->NumberOfCylinders = diskSize / 512 / 32 / 2; ! 322: ! 323: // Format a FAT filesystem in the memory buffer ! 324: ! 325: RamDiskFormatFat(diskExtension, ParamPath); ! 326: ! 327: // ! 328: // Allocate and initialize a Unicode String containing the Win32 name ! 329: // for our device. ! 330: // ! 331: RtlInitUnicodeString( &Win32PathString, WIN32_PATH ); ! 332: ! 333: diskExtension->Win32NameString.Buffer = ExAllocatePool( ! 334: PagedPool, ! 335: sizeof(WIN32_PATH) + 2 * sizeof(WCHAR) ); ! 336: ! 337: if (!diskExtension->Win32NameString.Buffer) { ! 338: RamDiskDump( ! 339: RAMDERRORS, ! 340: ("RAMDISK: Couldn't allocate buffer for the symbolic link\n") ! 341: ); ! 342: ! 343: ntStatus = STATUS_INSUFFICIENT_RESOURCES; ! 344: ! 345: goto RamDiskInitializeDiskExit; ! 346: } ! 347: ! 348: diskExtension->Win32NameString.MaximumLength = sizeof(WIN32_PATH) + sizeof(WCHAR); ! 349: ! 350: // ! 351: // If a drive letter wasn't specified in the registry, use drive Z. ! 352: // ! 353: if (driveLetterBuffer[0] == L'\0') ! 354: { ! 355: driveLetterBuffer[0] = L'Z'; ! 356: } ! 357: ! 358: if (driveLetterBuffer[1] != L':') ! 359: { ! 360: driveLetterBuffer[1] = L':'; ! 361: } ! 362: ! 363: driveLetterBuffer[2] = L'\0'; ! 364: driveLetterString.Length = 2 * sizeof(WCHAR); ! 365: ! 366: ! 367: RtlAppendUnicodeStringToString( ! 368: &diskExtension->Win32NameString, &Win32PathString ); ! 369: ! 370: RtlAppendUnicodeStringToString( ! 371: &diskExtension->Win32NameString, &driveLetterString ); ! 372: ! 373: // ! 374: // Create a symbolic link between our device name "\Device\RamDisk" and ! 375: // the Win32 name (ie "\DosDevices\Z:"). ! 376: // ! 377: ntStatus = IoCreateSymbolicLink( ! 378: &diskExtension->Win32NameString, &ntUnicodeString ); ! 379: ! 380: ! 381: RamDiskInitializeDiskExit: ! 382: ! 383: if (ntUnicodeString.Buffer != NULL) ! 384: { ! 385: RtlFreeUnicodeString( &ntUnicodeString ); ! 386: } ! 387: ! 388: if ( !NT_SUCCESS( ntStatus ) ) ! 389: { ! 390: // ! 391: // Delete everything that this routine has allocated. ! 392: // ! 393: ! 394: if ( deviceObject != NULL ) ! 395: { ! 396: if (diskExtension->DiskImage != NULL) ! 397: { ! 398: ExFreePool( diskExtension->DiskImage ); ! 399: } ! 400: if (diskExtension->Win32NameString.Buffer != NULL) ! 401: { ! 402: ExFreePool( diskExtension->Win32NameString.Buffer ); ! 403: } ! 404: IoDeleteDevice( deviceObject ); ! 405: } ! 406: } ! 407: ! 408: return ntStatus; ! 409: } ! 410: ! 411: VOID ! 412: RamDiskFormatFat( ! 413: IN PRAMDISK_EXTENSION DiskExtension, ! 414: IN PUNICODE_STRING ParamPath ! 415: ) ! 416: /*++ ! 417: ! 418: Routine Description: ! 419: ! 420: This routine is called by RamDiskInitializeDisk to format a FAT filesystem ! 421: on the memory buffer. ! 422: ! 423: Two parameters may be configured using the registry. RootDirEntries ! 424: specifies the desired number of Root Directory entries. If necessary, ! 425: the value is rounded up to an integral number of ROOT_DIR_ENTRIES (16). ! 426: The default value (DEFAULT_ROOT_DIR_ENTRIES) is 512. ! 427: ! 428: SectorsPerCluster determines the number of sectors in each cluster. The ! 429: default value (DEFAULT_SECTORS_PER_CLUSTER) is 2. ! 430: ! 431: Arguments: ! 432: ! 433: DiskExtension - a pointer to the object that represents the device ! 434: that I/O is to be done on. ! 435: ! 436: ParamPath - a pointer to the Parameters key of our key under the Serices ! 437: section of the registry. ! 438: ! 439: Return Value: ! 440: ! 441: None ! 442: ! 443: --*/ ! 444: { ! 445: RTL_QUERY_REGISTRY_TABLE paramTable[3]; ! 446: ! 447: ULONG defaultRootDirEntries = DEFAULT_ROOT_DIR_ENTRIES; ! 448: ULONG rootDirEntries = DEFAULT_ROOT_DIR_ENTRIES; ! 449: ! 450: ULONG defaultSectorsPerCluster = DEFAULT_SECTORS_PER_CLUSTER; ! 451: ULONG sectorsPerCluster = DEFAULT_SECTORS_PER_CLUSTER; ! 452: ! 453: ! 454: PBOOT_SECTOR bootSector = (PBOOT_SECTOR) DiskExtension->DiskImage; ! 455: PUCHAR firstFatSector; ! 456: ! 457: int fatType; // Type of FAT - 12 or 16 ! 458: USHORT fatEntries; // Number of cluster entries in FAT ! 459: USHORT fatSectorCnt; // Number of sectors for FAT ! 460: ! 461: PDIR_ENTRY rootDir; // Pointer to first entry in root dir ! 462: // ! 463: // Retrieve user tunable parameters ! 464: // ! 465: RtlZeroMemory(¶mTable[0], sizeof(paramTable)); ! 466: ! 467: paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 468: paramTable[0].Name = L"RootDirEntries"; ! 469: paramTable[0].EntryContext = &rootDirEntries; ! 470: paramTable[0].DefaultType = REG_DWORD; ! 471: paramTable[0].DefaultData = &defaultRootDirEntries; ! 472: paramTable[0].DefaultLength = sizeof(ULONG); ! 473: ! 474: paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 475: paramTable[1].Name = L"SectorsPerCluster"; ! 476: paramTable[1].EntryContext = §orsPerCluster; ! 477: paramTable[1].DefaultType = REG_DWORD; ! 478: paramTable[1].DefaultData = &defaultSectorsPerCluster; ! 479: paramTable[1].DefaultLength = sizeof(ULONG); ! 480: ! 481: if (!NT_SUCCESS(RtlQueryRegistryValues( ! 482: RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, ! 483: ParamPath->Buffer, ¶mTable[0], NULL, NULL))) ! 484: { ! 485: rootDirEntries = DEFAULT_ROOT_DIR_ENTRIES; ! 486: sectorsPerCluster = DEFAULT_SECTORS_PER_CLUSTER; ! 487: } ! 488: ! 489: // ! 490: // Round Root Directory entries up if necessary ! 491: // ! 492: if (rootDirEntries & (DIR_ENTRIES_PER_SECTOR - 1)) ! 493: { ! 494: RamDiskDump(RAMDDIAG1, ("RAMDISK: Adjusting RootDirEntries\n")); ! 495: ! 496: rootDirEntries = ! 497: (rootDirEntries + ( DIR_ENTRIES_PER_SECTOR - 1 )) & ! 498: ~ ( DIR_ENTRIES_PER_SECTOR - 1 ); ! 499: } ! 500: ! 501: // ! 502: // We need to have the 0xeb and 0x90 since this is one of the ! 503: // checks the file system recognizer uses ! 504: // ! 505: bootSector->bsJump[0] = 0xeb; ! 506: bootSector->bsJump[1] = 0x3c; ! 507: bootSector->bsJump[2] = 0x90; ! 508: ! 509: strncpy(bootSector->bsOemName, "RobertN ", 8); ! 510: bootSector->bsBytesPerSec = (SHORT)DiskExtension->BytesPerSector; ! 511: bootSector->bsResSectors = 1; ! 512: bootSector->bsFATs = 1; ! 513: bootSector->bsRootDirEnts = (USHORT)rootDirEntries; ! 514: ! 515: bootSector->bsSectors = ! 516: (USHORT)( DiskExtension->DiskLength / DiskExtension->BytesPerSector ); ! 517: bootSector->bsMedia = RAMDISK_MEDIA_TYPE; ! 518: ! 519: bootSector->bsSecPerClus = (UCHAR)sectorsPerCluster; ! 520: ! 521: // ! 522: // Calculate number of sectors required for FAT ! 523: // ! 524: fatEntries = ! 525: (bootSector->bsSectors - bootSector->bsResSectors - ! 526: bootSector->bsRootDirEnts / DIR_ENTRIES_PER_SECTOR) / ! 527: bootSector->bsSecPerClus + 2; ! 528: ! 529: // ! 530: // Choose between 12 and 16 bit FAT based on number of clusters we ! 531: // need to map ! 532: // ! 533: if (fatEntries > 4087) ! 534: { ! 535: fatType = 16; ! 536: ! 537: fatSectorCnt = (fatEntries * 2 + 511) / 512; ! 538: ! 539: fatEntries -= fatSectorCnt; ! 540: ! 541: fatSectorCnt = (fatEntries * 2 + 511) / 512; ! 542: } ! 543: else ! 544: { ! 545: fatType = 12; ! 546: ! 547: fatSectorCnt = (((fatEntries * 3 + 1) / 2) + 511) / 512; ! 548: ! 549: fatEntries -= fatSectorCnt; ! 550: ! 551: fatSectorCnt = (((fatEntries * 3 + 1) / 2) + 511) / 512; ! 552: } ! 553: ! 554: bootSector->bsFATsecs = fatSectorCnt; ! 555: bootSector->bsSecPerTrack = (USHORT)DiskExtension->SectorsPerTrack; ! 556: bootSector->bsHeads = (USHORT)DiskExtension->TracksPerCylinder; ! 557: bootSector->bsBootSignature = 0x29; ! 558: bootSector->bsVolumeID = 0x12345678; ! 559: strncpy(bootSector->bsLabel, "RamDisk ", 11); ! 560: strncpy(bootSector->bsFileSystemType, "FAT1? ", 8); ! 561: bootSector->bsFileSystemType[4] = ( fatType == 16 ) ? '6' : '2'; ! 562: ! 563: bootSector->bsSig2[0] = 0x55; ! 564: bootSector->bsSig2[1] = 0xAA; ! 565: ! 566: // ! 567: // The FAT is located immediately following the boot sector. ! 568: // ! 569: firstFatSector = (PUCHAR)(bootSector + 1); ! 570: firstFatSector[0] = RAMDISK_MEDIA_TYPE; ! 571: firstFatSector[1] = 0xFF; ! 572: firstFatSector[2] = 0xFF; ! 573: ! 574: if (fatType == 16) ! 575: firstFatSector[3] = 0xFF; ! 576: ! 577: // ! 578: // The Root Directory follows the FAT ! 579: // ! 580: rootDir = (PDIR_ENTRY)(bootSector + 1 + fatSectorCnt); ! 581: strcpy(rootDir->deName, "MS-RAMDR"); ! 582: strcpy(rootDir->deExtension, "IVE"); ! 583: rootDir->deAttributes = DIR_ATTR_VOLUME; ! 584: } ! 585: ! 586: NTSTATUS ! 587: RamDiskCreateClose( ! 588: IN PDEVICE_OBJECT DeviceObject, ! 589: IN PIRP Irp ! 590: ) ! 591: /*++ ! 592: ! 593: Routine Description: ! 594: ! 595: This routine is called by the I/O system when the RamDisk is opened or ! 596: closed. ! 597: ! 598: No action is performed other than completing the request successfully. ! 599: ! 600: Arguments: ! 601: ! 602: DeviceObject - a pointer to the object that represents the device ! 603: that I/O is to be done on. ! 604: ! 605: Irp - a pointer to the I/O Request Packet for this request. ! 606: ! 607: Return Value: ! 608: ! 609: STATUS_INVALID_PARAMETER if parameters are invalid, ! 610: STATUS_SUCCESS otherwise. ! 611: ! 612: --*/ ! 613: ! 614: { ! 615: Irp->IoStatus.Status = STATUS_SUCCESS; ! 616: Irp->IoStatus.Information = 0; ! 617: ! 618: IoCompleteRequest( Irp, IO_NO_INCREMENT ); ! 619: ! 620: return STATUS_SUCCESS; ! 621: } ! 622: ! 623: NTSTATUS ! 624: RamDiskDeviceControl( ! 625: IN PDEVICE_OBJECT DeviceObject, ! 626: IN PIRP Irp ! 627: ) ! 628: ! 629: /*++ ! 630: ! 631: Routine Description: ! 632: ! 633: This routine is called by the I/O system to perform a device I/O ! 634: control function. ! 635: ! 636: Arguments: ! 637: ! 638: DeviceObject - a pointer to the object that represents the device ! 639: that I/O is to be done on. ! 640: ! 641: Irp - a pointer to the I/O Request Packet for this request. ! 642: ! 643: Return Value: ! 644: ! 645: STATUS_SUCCESS if recognized I/O control code, ! 646: STATUS_INVALID_DEVICE_REQUEST otherwise. ! 647: ! 648: --*/ ! 649: ! 650: { ! 651: PRAMDISK_EXTENSION diskExtension; ! 652: PIO_STACK_LOCATION irpSp; ! 653: NTSTATUS ntStatus; ! 654: ! 655: // ! 656: // Set up necessary object and extension pointers. ! 657: // ! 658: ! 659: diskExtension = DeviceObject->DeviceExtension; ! 660: irpSp = IoGetCurrentIrpStackLocation( Irp ); ! 661: ! 662: // ! 663: // Assume failure. ! 664: // ! 665: ! 666: Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; ! 667: ! 668: // ! 669: // Determine which I/O control code was specified. ! 670: // ! 671: ! 672: switch ( irpSp->Parameters.DeviceIoControl.IoControlCode ) ! 673: { ! 674: ! 675: case IOCTL_DISK_GET_MEDIA_TYPES: ! 676: case IOCTL_DISK_GET_DRIVE_GEOMETRY: ! 677: // ! 678: // Return the drive geometry for the ram disk. Note that ! 679: // we return values which were made up to suit the disk size. ! 680: // ! 681: ! 682: if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength < ! 683: sizeof( DISK_GEOMETRY ) ) ! 684: { ! 685: ! 686: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; ! 687: ! 688: } ! 689: else ! 690: { ! 691: PDISK_GEOMETRY outputBuffer; ! 692: ! 693: outputBuffer = ( PDISK_GEOMETRY ) Irp->AssociatedIrp.SystemBuffer; ! 694: outputBuffer->MediaType = RemovableMedia; ! 695: outputBuffer->Cylinders = RtlConvertUlongToLargeInteger( ! 696: diskExtension->NumberOfCylinders ); ! 697: outputBuffer->TracksPerCylinder = diskExtension->TracksPerCylinder; ! 698: outputBuffer->SectorsPerTrack = diskExtension->SectorsPerTrack; ! 699: outputBuffer->BytesPerSector = diskExtension->BytesPerSector; ! 700: ! 701: Irp->IoStatus.Status = STATUS_SUCCESS; ! 702: Irp->IoStatus.Information = sizeof( DISK_GEOMETRY ); ! 703: } ! 704: break; ! 705: ! 706: case IOCTL_DISK_GET_PARTITION_INFO: ! 707: // ! 708: // Return the information about the partition. ! 709: // ! 710: ! 711: if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( PARTITION_INFORMATION ) ) ! 712: { ! 713: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; ! 714: } ! 715: else ! 716: { ! 717: PPARTITION_INFORMATION outputBuffer; ! 718: PBOOT_SECTOR bootSector = (PBOOT_SECTOR) diskExtension->DiskImage; ! 719: ! 720: outputBuffer = ( PPARTITION_INFORMATION )Irp->AssociatedIrp.SystemBuffer; ! 721: ! 722: outputBuffer->PartitionType = ! 723: (bootSector->bsFileSystemType[4] == '6') ? ! 724: PARTITION_FAT_16 : PARTITION_FAT_12; ! 725: ! 726: outputBuffer->BootIndicator = FALSE; ! 727: ! 728: outputBuffer->RecognizedPartition = TRUE; ! 729: ! 730: outputBuffer->RewritePartition = FALSE; ! 731: ! 732: outputBuffer->StartingOffset = RtlConvertUlongToLargeInteger(0); ! 733: ! 734: outputBuffer->PartitionLength = RtlConvertUlongToLargeInteger(diskExtension->DiskLength); ! 735: ! 736: outputBuffer->HiddenSectors = RtlConvertUlongToLargeInteger(1); ! 737: ! 738: Irp->IoStatus.Status = STATUS_SUCCESS; ! 739: Irp->IoStatus.Information = sizeof( PARTITION_INFORMATION ); ! 740: } ! 741: break; ! 742: ! 743: ! 744: case IOCTL_DISK_VERIFY: ! 745: { ! 746: // ! 747: // Move parameters from the VerifyInformation structure to ! 748: // the READ parameters area, so that we'll find them when ! 749: // we try to treat this like a READ. ! 750: // ! 751: ! 752: PVERIFY_INFORMATION verifyInformation; ! 753: ! 754: verifyInformation = Irp->AssociatedIrp.SystemBuffer; ! 755: ! 756: irpSp->Parameters.Read.ByteOffset.LowPart = ! 757: verifyInformation->StartingOffset.LowPart; ! 758: irpSp->Parameters.Read.ByteOffset.HighPart = ! 759: verifyInformation->StartingOffset.HighPart; ! 760: irpSp->Parameters.Read.Length = verifyInformation->Length; ! 761: ! 762: // ! 763: // A VERIFY is identical to a READ, except for the fact that no ! 764: // data gets transferred. So follow the READ code path. ! 765: // ! 766: ! 767: ntStatus = RamDiskReadWrite( DeviceObject, Irp ); ! 768: } ! 769: return ntStatus; ! 770: ! 771: default: ! 772: // ! 773: // The specified I/O control code is unrecognized by this driver. ! 774: // The I/O status field in the IRP has already been set so just ! 775: // terminate the switch. ! 776: // ! 777: ! 778: RamDiskDump( ! 779: RAMDDIAG1, ! 780: ("RAMDISK: ERROR: unrecognized IOCTL %x\n", ! 781: irpSp->Parameters.DeviceIoControl.IoControlCode)); ! 782: ! 783: break; ! 784: } ! 785: ! 786: // ! 787: // Finish the I/O operation by simply completing the packet and returning ! 788: // the same status as in the packet itself. ! 789: // ! 790: ! 791: ntStatus = Irp->IoStatus.Status; ! 792: ! 793: IoCompleteRequest( Irp, IO_NO_INCREMENT ); ! 794: ! 795: return ntStatus; ! 796: } ! 797: ! 798: NTSTATUS ! 799: RamDiskReadWrite( ! 800: IN PDEVICE_OBJECT DeviceObject, ! 801: IN PIRP Irp ! 802: ) ! 803: /*++ ! 804: ! 805: Routine Description: ! 806: ! 807: This routine is called by the I/O system to read or write to a ! 808: device that we control. It can also be called by ! 809: RamDiskDispatchDeviceControl() to do a VERIFY. ! 810: ! 811: Arguments: ! 812: ! 813: DeviceObject - a pointer to the object that represents the device ! 814: that I/O is to be done on. ! 815: ! 816: Irp - a pointer to the I/O Request Packet for this request. ! 817: ! 818: Return Value: ! 819: ! 820: STATUS_INVALID_PARAMETER if parameters are invalid, ! 821: STATUS_SUCCESS otherwise. ! 822: ! 823: --*/ ! 824: ! 825: { ! 826: PRAMDISK_EXTENSION diskExtension; ! 827: PIO_STACK_LOCATION irpSp; ! 828: PUCHAR CurrentAddress; ! 829: ! 830: // ! 831: // Set up necessary object and extension pointers. ! 832: // ! 833: ! 834: diskExtension = DeviceObject->DeviceExtension; ! 835: ! 836: irpSp = IoGetCurrentIrpStackLocation( Irp ); ! 837: ! 838: // ! 839: // Check for invalid parameters. It is an error for the starting offset ! 840: // + length to go past the end of the buffer, or for the length to ! 841: // not be a proper multiple of the sector size. ! 842: // ! 843: // Others are possible, but we don't check them since we trust the ! 844: // file system and they aren't deadly. ! 845: // ! 846: ! 847: if (RtlLargeIntegerGreaterThan( ! 848: RtlLargeIntegerAdd( ! 849: irpSp->Parameters.Read.ByteOffset, ! 850: RtlConvertUlongToLargeInteger(irpSp->Parameters.Read.Length)), ! 851: RtlConvertUlongToLargeInteger(diskExtension->DiskLength)) || ! 852: (irpSp->Parameters.Read.Length & (diskExtension->BytesPerSector - 1))) ! 853: { ! 854: // ! 855: // Do not give an I/O boost for parameter errors. ! 856: // ! 857: ! 858: RamDiskDump( ! 859: RAMDERRORS, ! 860: ( ! 861: "RAMDISK: Error invalid parameter\n" ! 862: " ByteOffset: %x\n" ! 863: " Length: %d\n" ! 864: " Operation: %x\n", ! 865: Irp, ! 866: irpSp->Parameters.Read.ByteOffset, ! 867: irpSp->Parameters.Read.Length, ! 868: irpSp->MajorFunction ! 869: )); ! 870: ! 871: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; ! 872: IoCompleteRequest( Irp, IO_NO_INCREMENT ); ! 873: ! 874: return STATUS_INVALID_PARAMETER; ! 875: } ! 876: ! 877: // ! 878: // Get a system-space pointer to the user's buffer. A system ! 879: // address must be used because we may already have left the ! 880: // original caller's address space. ! 881: // ! 882: ! 883: if ( Irp->MdlAddress != NULL ) ! 884: { ! 885: CurrentAddress = MmGetSystemAddressForMdl( Irp->MdlAddress ); ! 886: } ! 887: ! 888: RamDiskDump( ! 889: RAMDDIAG2, ! 890: ( ! 891: "RAMDISK: Irp of Request: %x\n" ! 892: " Vmem Address of Transfer: %x - %x\n" ! 893: " Length of Transfer: %d\n" ! 894: " Operation: %x\n" ! 895: " Starting ByteOffset: %x\n", ! 896: Irp, ! 897: CurrentAddress, ! 898: ((PUCHAR)CurrentAddress) + irpSp->Parameters.Read.Length, ! 899: irpSp->Parameters.Read.Length, ! 900: irpSp->MajorFunction, ! 901: irpSp->Parameters.Read.ByteOffset.LowPart ! 902: )); ! 903: ! 904: Irp->IoStatus.Information = irpSp->Parameters.Read.Length; ! 905: ! 906: switch (irpSp->MajorFunction) ! 907: { ! 908: case IRP_MJ_READ: ! 909: RtlMoveMemory( ! 910: CurrentAddress, ! 911: diskExtension->DiskImage + irpSp->Parameters.Read.ByteOffset.LowPart, ! 912: irpSp->Parameters.Read.Length); ! 913: break; ! 914: ! 915: case IRP_MJ_DEVICE_CONTROL: ! 916: // ! 917: // The only way we can get this major code is if the VERIFY ! 918: // ioctl called RamDiskDispatchReadWrite(). ! 919: // ! 920: break; ! 921: ! 922: case IRP_MJ_WRITE: ! 923: RtlMoveMemory( ! 924: diskExtension->DiskImage + irpSp->Parameters.Read.ByteOffset.LowPart, ! 925: CurrentAddress, irpSp->Parameters.Read.Length); ! 926: break; ! 927: ! 928: default: ! 929: Irp->IoStatus.Information = 0; ! 930: break; ! 931: } ! 932: ! 933: Irp->IoStatus.Status = STATUS_SUCCESS; ! 934: IoCompleteRequest( Irp, IO_NO_INCREMENT ); ! 935: ! 936: return STATUS_SUCCESS; ! 937: } ! 938: ! 939: VOID ! 940: RamDiskUnloadDriver( ! 941: IN PDRIVER_OBJECT DriverObject ! 942: ) ! 943: /*++ ! 944: ! 945: Routine Description: ! 946: ! 947: This routine is called by the I/O system to unload the driver. ! 948: ! 949: Any resources previously allocated must be freed. ! 950: ! 951: Arguments: ! 952: ! 953: DriverObject - a pointer to the object that represents our driver. ! 954: ! 955: Return Value: ! 956: ! 957: None ! 958: --*/ ! 959: ! 960: { ! 961: PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject; ! 962: ! 963: if ( deviceObject != NULL ) ! 964: { ! 965: PRAMDISK_EXTENSION diskExtension = deviceObject->DeviceExtension; ! 966: ! 967: if (diskExtension != NULL) ! 968: { ! 969: if (diskExtension->DiskImage != NULL) ! 970: { ! 971: ExFreePool( diskExtension->DiskImage ); ! 972: } ! 973: if (diskExtension->Win32NameString.Buffer != NULL) ! 974: { ! 975: IoDeleteSymbolicLink( &diskExtension->Win32NameString ); ! 976: ! 977: ExFreePool( diskExtension->Win32NameString.Buffer ); ! 978: } ! 979: } ! 980: IoDeleteDevice( deviceObject ); ! 981: } ! 982: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.