/*++ Copyright (c) 1993-2001 Microsoft Corporation Module Name: ramdisk.c Abstract: This is the RAM disk driver for Windows. Author: Chuck Lenzmeier (ChuckL) 2001 based on prototype XIP driver by DavePr based on NT4 DDK ramdisk by RobertN Environment: Kernel mode only. Notes: Revision History: --*/ #include "precomp.h" #pragma hdrstop #include #include #include // // ISSUE: 2000/10/11-DavePr -- haven't decided how to define DO_XIP appropriately. // #ifndef DO_XIP #define DO_XIP 0x00020000 #endif // // Data declarations. // PDEVICE_OBJECT RamdiskBusFdo = NULL; BOOLEAN ReportDetectedDevice; ULONG MinimumViewCount; ULONG DefaultViewCount; ULONG MaximumViewCount; ULONG MinimumViewLength; ULONG DefaultViewLength; ULONG MaximumViewLength; ULONG MaximumPerDiskViewLength; UNICODE_STRING DriverRegistryPath; BOOLEAN MarkRamdisksAsRemovable; #if SUPPORT_DISK_NUMBERS ULONG DiskNumbersBitmapSize; #endif // SUPPORT_DISK_NUMBERS #if DBG ULONG BreakOnEntry = DEFAULT_BREAK_ON_ENTRY; ULONG DebugComponents = DEFAULT_DEBUG_COMPONENTS; ULONG DebugLevel = DEFAULT_DEBUG_LEVEL; BOOLEAN DontLoad = FALSE; #endif // // Local functions. // NTSTATUS DriverEntry ( IN OUT PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ); NTSTATUS RamdiskCreateClose ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS RamdiskFlushBuffers ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS RamdiskFlushBuffersReal ( IN PDISK_EXTENSION DiskExtension ); NTSTATUS RamdiskSystemControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); VOID RamdiskUnload ( IN PDRIVER_OBJECT DriverObject ); VOID QueryParameters ( IN PUNICODE_STRING RegistryPath ); #if DBG NTSTATUS RamdiskInvalidDeviceRequest ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); VOID QueryDebugParameters ( IN PUNICODE_STRING RegistryPath ); #endif // // Declare pageable routines. // #ifdef ALLOC_PRAGMA #pragma alloc_text( INIT, DriverEntry ) #pragma alloc_text( INIT, QueryParameters ) #pragma alloc_text( PAGE, RamdiskCreateClose ) #pragma alloc_text( PAGE, RamdiskFlushBuffers ) #pragma alloc_text( PAGE, RamdiskFlushBuffersReal ) #pragma alloc_text( PAGE, RamdiskSystemControl ) #pragma alloc_text( PAGE, RamdiskUnload ) #pragma alloc_text( PAGE, RamdiskWorkerThread ) #if DBG #pragma alloc_text( INIT, QueryDebugParameters ) #endif // DBG #endif // ALLOC_PRAGMA NTSTATUS DriverEntry ( IN OUT PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) /*++ Routine Description: This routine is called by the operating system to initialize the driver. Arguments: DriverObject - a pointer to a driver object for the driver RegistryPath - a pointer to our Services key in the registry Return Value: NTSTATUS --*/ { NTSTATUS status; HANDLE handle; ULONG i; PDEVICE_OBJECT pdo = NULL; PLOADER_PARAMETER_BLOCK loaderBlock; // // Initialize pool debugging, if enabled. // #if defined(POOL_DBG) RamdiskInitializePoolDebug(); #endif // // Get debugging parameters from the registry. // #if DBG QueryDebugParameters( RegistryPath ); #endif DBGPRINT( DBG_INIT, DBG_VERBOSE, ("DriverEntry: DriverObject = %x, RegistryPath = %ws\n", DriverObject, RegistryPath->Buffer) ); // // If requested, break into the debugger. // #if DBG if ( BreakOnEntry ) { KdBreakPoint(); } #endif // // If requested, fail the driver load. // #if DBG if ( DontLoad ) { return STATUS_INVALID_DEVICE_REQUEST; } #endif // // Get non-debug parameters from the registry. // QueryParameters( RegistryPath ); // // Save the path to the driver's registry key. // DriverRegistryPath.Length = RegistryPath->Length; DriverRegistryPath.MaximumLength = (USHORT)(RegistryPath->Length + sizeof(WCHAR)); DriverRegistryPath.Buffer = ALLOCATE_POOL( PagedPool, DriverRegistryPath.MaximumLength, TRUE ); if ( DriverRegistryPath.Buffer == NULL ) { return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyUnicodeString( &DriverRegistryPath, RegistryPath ); ASSERT( DriverRegistryPath.Length == RegistryPath->Length ); // // Initialize the driver object with this driver's entry points. // #if DBG for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction[i] = RamdiskInvalidDeviceRequest; } #endif DriverObject->MajorFunction[IRP_MJ_CREATE] = RamdiskCreateClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamdiskCreateClose; DriverObject->MajorFunction[IRP_MJ_READ] = RamdiskReadWrite; DriverObject->MajorFunction[IRP_MJ_WRITE] = RamdiskReadWrite; DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = RamdiskFlushBuffers; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamdiskDeviceControl; DriverObject->MajorFunction[IRP_MJ_PNP] = RamdiskPnp; DriverObject->MajorFunction[IRP_MJ_POWER] = RamdiskPower; DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamdiskSystemControl; DriverObject->MajorFunction[IRP_MJ_SCSI] = RamdiskScsi; DriverObject->DriverUnload = RamdiskUnload; DriverObject->DriverExtension->AddDevice = RamdiskAddDevice; // // If the registry tells us to do so, or if textmode setup is running and // virtual floppy RAM disks are specified in the registry, call // IoReportDetectedDevice to hook us up to PnP, then call RamdiskAddDevice // directly. This is necessary during textmode in order to get any virtual // floppy RAM disks created -- our AddDevice routine is not normally called // during textmode. Calling IoReportDetectedDevice is also necessary during // a boot from a RAM disk in order to get the device plumbed early enough. // // We don't want to call IoReportDetectedDevice during textmode setup if // no virtual floppies exist, because calling IoReportDetectedDevice // causes a devnode for the controller device to be written to the // registry, and textmode setup only deletes the devnode if virtual // floppies exist. If we leave the devnode in the registry, then GUI setup // installs ramdisk.sys on the machine, even though we don't really want // it to. // loaderBlock = *(PLOADER_PARAMETER_BLOCK *)KeLoaderBlock; if ( ReportDetectedDevice || ( (loaderBlock != NULL) && (loaderBlock->SetupLoaderBlock != NULL) && CreateRegistryDisks( TRUE ) ) ) { // // Inform PnP that we have detected the bus enumerator device and will be // doing the AddDevice ourselves. // status = IoReportDetectedDevice( DriverObject, InterfaceTypeUndefined, -1, -1, NULL, //allocatedResources, NULL, //ioResourceReq, FALSE, &pdo ); if (!NT_SUCCESS(status)) { DBGPRINT( DBG_ALL, DBG_ERROR, ("RamdiskDriverEntry: IoReportDetectedDevice failed: %x\n", status) ); return status; } // // Attach a device object to the pdo // status = RamdiskAddDevice(DriverObject, pdo); if ( !NT_SUCCESS(status) ) { DBGPRINT( DBG_ALL, DBG_ERROR, ("RamdiskDriverEntry: RamdiskAddDevice failed: %x\n", status) ); return status; } // // Indicate that the device is done initializing. // pdo->Flags &= ~DO_DEVICE_INITIALIZING; } // // Indicate that the driver has loaded successfully. // DBGPRINT( DBG_INIT, DBG_VERBOSE, ("%s", "DriverEntry: succeeded\n") ); return STATUS_SUCCESS; } // DriverEntry NTSTATUS RamdiskCreateClose ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine is called by the I/O system when a device owned by the driver is opened or closed. No action is performed other than completing the request successfully. Arguments: DeviceObject - a pointer to the object that represents the device on which I/O is to be performed Irp - a pointer to the I/O Request Packet for this request Return Value: NTSTATUS - STATUS_SUCCESS --*/ { PAGED_CODE(); COMPLETE_REQUEST( STATUS_SUCCESS, FILE_OPENED, Irp ); return STATUS_SUCCESS; } // RamdiskCreateClose NTSTATUS RamdiskFlushBuffers ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine is called by the I/O system when a FLUSH_BUFFERS IRP is issued. Arguments: DeviceObject - a pointer to the object that represents the device on which I/O is to be performed Irp - a pointer to the I/O Request Packet for this request Return Value: NTSTATUS - the status of the operation --*/ { NTSTATUS status; PDISK_EXTENSION diskExtension = DeviceObject->DeviceExtension; PAGED_CODE(); // // If the target RAM disk is not file-backed, there's nothing to do. If it // is file-backed, we need to do the work in a thread. // if ( (diskExtension->DeviceType != RamdiskDeviceTypeDiskPdo) || !RAMDISK_IS_FILE_BACKED(diskExtension->DiskType) ) { COMPLETE_REQUEST( STATUS_SUCCESS, 0, Irp ); return STATUS_SUCCESS; } status = SendIrpToThread( DeviceObject, Irp ); if ( status != STATUS_PENDING ) { COMPLETE_REQUEST( status, 0, Irp ); } return status; } // RamdiskFlushBuffers NTSTATUS RamdiskFlushBuffersReal ( IN PDISK_EXTENSION DiskExtension ) /*++ Routine Description: This routine is called in a thread in the system process to handle a FLUSH_BUFFERS IRP. Arguments: DiskExtension - a pointer to the device object extension for the target device Return Value: NTSTATUS - the status of the operation --*/ { PAGED_CODE(); // // Flush the virtual memory associated with the RAM disk. // return RamdiskFlushViews( DiskExtension ); } // RamdiskFlushBuffersReal NTSTATUS RamdiskSystemControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine is called by the I/O system when a SYSTEM_CONTROL IRP is issued. Arguments: DeviceObject - a pointer to the object that represents the device on which I/O is to be performed Irp - a pointer to the I/O Request Packet for this request Return Value: NTSTATUS - the status of the operation --*/ { PCOMMON_EXTENSION commonExtension; NTSTATUS status; PAGED_CODE(); // // If the target device is a bus FDO, pass the IRP down to the next // device in the stack. Otherwise, the target is a disk PDO, in which // case we just complete the IRP with the current status. // commonExtension = DeviceObject->DeviceExtension; if ( commonExtension->DeviceType == RamdiskDeviceTypeBusFdo ) { IoSkipCurrentIrpStackLocation( Irp ); return IoCallDriver( commonExtension->LowerDeviceObject, Irp ); } status = Irp->IoStatus.Status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } // RamdiskSystemControl VOID RamdiskUnload ( IN PDRIVER_OBJECT DriverObject ) /*++ Routine Description: This routine is called by the I/O system to unload the driver. Any resources previously allocated must be freed. Arguments: DriverObject - a pointer to the object that represents our driver Return Value: None. --*/ { PAGED_CODE(); if ( DriverRegistryPath.Buffer != NULL ) { FREE_POOL( DriverRegistryPath.Buffer, TRUE ); } // // ISSUE: What other cleanup is needed here? // return; } // RamdiskUnload VOID RamdiskWorkerThread ( IN PDEVICE_OBJECT DeviceObject, IN PVOID Context ) /*++ Routine Description: This routine executes thread-based operations for the RAM disk driver. It runs in the context of the system process. Arguments: DeviceObject - a pointer to the object that represents the device on which I/O is to be performed Context - a pointer to the IRP for the I/O operation Return Value: None. --*/ { NTSTATUS status; PLIST_ENTRY listEntry; PIRP irp; PIO_STACK_LOCATION irpSp; PCOMMON_EXTENSION commonExtension; PBUS_EXTENSION busExtension; PDISK_EXTENSION diskExtension; PSCSI_REQUEST_BLOCK srb; ULONG controlCode; PUCHAR originalDataBuffer; PUCHAR mappedDataBuffer; PUCHAR inputDataBuffer; PUCHAR systemAddress; ULONG originalDataBufferOffset; PAGED_CODE(); // // Get a pointer to the IRP. // irp = Context; irpSp = IoGetCurrentIrpStackLocation( irp ); // // Free the work item. // IoFreeWorkItem( irp->Tail.Overlay.DriverContext[0] ); // // Get pointers to the device extension. // commonExtension = DeviceObject->DeviceExtension; busExtension = DeviceObject->DeviceExtension; diskExtension = DeviceObject->DeviceExtension; // // Acquire the remove lock for the device. If this fails, bail out. // status = IoAcquireRemoveLock( &commonExtension->RemoveLock, irp ); if ( !NT_SUCCESS(status) ) { COMPLETE_REQUEST( status, 0, irp ); return; } // // Dispatch based on the IRP function. // switch ( irpSp->MajorFunction ) { case IRP_MJ_READ: case IRP_MJ_WRITE: status = RamdiskReadWriteReal( irp, diskExtension ); break; case IRP_MJ_FLUSH_BUFFERS: status = RamdiskFlushBuffersReal( diskExtension ); irp->IoStatus.Information = 0; break; case IRP_MJ_DEVICE_CONTROL: switch (irpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_DISK_GET_DRIVE_LAYOUT: status = RamdiskGetDriveLayout( irp, diskExtension ); break; case IOCTL_DISK_GET_PARTITION_INFO: status = RamdiskGetPartitionInfo( irp, diskExtension ); break; case IOCTL_DISK_SET_PARTITION_INFO: status = RamdiskSetPartitionInfo( irp, diskExtension ); break; case FSCTL_CREATE_RAM_DISK: status = RamdiskCreateRamDisk( DeviceObject, irp, FALSE ); break; default: DBGPRINT( DBG_IOCTL, DBG_ERROR, ("RamdiskThread: bogus IOCTL IRP with code %x received\n", irpSp->Parameters.DeviceIoControl.IoControlCode) ); ASSERT( FALSE ); status = STATUS_INVALID_DEVICE_REQUEST; break; } break; case IRP_MJ_SCSI: srb = irpSp->Parameters.Scsi.Srb; controlCode = irpSp->Parameters.DeviceIoControl.IoControlCode; // // Remember the original data buffer pointer. We might have to // change the pointer. // originalDataBuffer = srb->DataBuffer; status = STATUS_SUCCESS; if ( irp->MdlAddress != NULL ) { // // There is an MDL in the IRP. Get a usable system address for // the data buffer based on the MDL. // systemAddress = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority ); if ( systemAddress != NULL ) { // // The SRB data buffer might be at an offset from the // start of the MDL. Calculate that offset and add it // to the system address just obtained. This is the // data buffer address that we will use. // originalDataBufferOffset = (ULONG)(originalDataBuffer - (PCHAR)MmGetMdlVirtualAddress( irp->MdlAddress )); mappedDataBuffer = systemAddress + originalDataBufferOffset; srb->DataBuffer = mappedDataBuffer; } else { // // Couldn't get a system address. Abort. // srb->SrbStatus = SRB_STATUS_ABORTED; status = STATUS_INSUFFICIENT_RESOURCES; } } if ( NT_SUCCESS(status) ) { // // Remember the data buffer address that we're sending down. // If it doesn't change, we'll need to reset the address to // that which was passed in to us. // inputDataBuffer = srb->DataBuffer; // // Dispatch based on the I/O type in the SRB. // if ( controlCode == IOCTL_SCSI_EXECUTE_NONE ) { status = RamdiskScsiExecuteNone( diskExtension->Pdo, irp, srb, controlCode ); } else { status = RamdiskScsiExecuteIo( diskExtension->Pdo, irp, srb, controlCode ); } // // If the data buffer address didn't change, put the original // address back in the SRB. // if ( srb->DataBuffer == inputDataBuffer ) { srb->DataBuffer = originalDataBuffer; } } // // If the I/O worked, write the transfer length into the IRP. // if ( NT_SUCCESS(status) ) { irp->IoStatus.Information = srb->DataTransferLength; } else { irp->IoStatus.Information = 0; } break; default: DBGPRINT( DBG_IOCTL, DBG_ERROR, ("RamdiskThread: bogus IRP with major function %x received\n", irpSp->MajorFunction) ); ASSERT( FALSE ); status = STATUS_INVALID_DEVICE_REQUEST; } // // Release the remove lock and complete the request. // IoReleaseRemoveLock( &commonExtension->RemoveLock, irp ); ASSERT( status != STATUS_PENDING ); irp->IoStatus.Status = status; IoCompleteRequest( irp, IO_DISK_INCREMENT ); return; } // RamdiskWorkerThread VOID QueryParameters ( IN PUNICODE_STRING RegistryPath ) /*++ Routine Description: This routine is called from DriverEntry() to get driver parameters from the registry. If the registry query fails, then default values are used. Arguments: RegistryPath - a pointer to the service path for the registry parameters Return Value: None. --*/ { NTSTATUS status; RTL_QUERY_REGISTRY_TABLE queryTable[12]; PRTL_QUERY_REGISTRY_TABLE queryEntry; PAGED_CODE(); DBGPRINT( DBG_INIT, DBG_VERBOSE, ("%s", "QueryParameters\n") ); ASSERT( RegistryPath->Buffer != NULL ); // // Set the default values. // ReportDetectedDevice = FALSE; MarkRamdisksAsRemovable = FALSE; MinimumViewCount = MINIMUM_MINIMUM_VIEW_COUNT; DefaultViewCount = DEFAULT_DEFAULT_VIEW_COUNT; MaximumViewCount = DEFAULT_MAXIMUM_VIEW_COUNT; MinimumViewLength = MINIMUM_MINIMUM_VIEW_LENGTH; DefaultViewLength = DEFAULT_DEFAULT_VIEW_LENGTH; MaximumViewLength = DEFAULT_MAXIMUM_VIEW_LENGTH; MaximumPerDiskViewLength = DEFAULT_MAXIMUM_PER_DISK_VIEW_LENGTH; #if SUPPORT_DISK_NUMBERS DiskNumbersBitmapSize = DEFAULT_DISK_NUMBERS_BITMAP_SIZE; #endif // SUPPORT_DISK_NUMBERS // // Set up the query table. // RtlZeroMemory( queryTable, sizeof(queryTable) ); // // We're looking for subkey "Parameters" under the given registry key. // queryEntry = &queryTable[0]; queryEntry->Flags = RTL_QUERY_REGISTRY_SUBKEY; queryEntry->Name = L"Parameters"; queryEntry->EntryContext = NULL; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; // // These are the values we want to read. // queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"ReportDetectedDevice"; queryEntry->EntryContext = &ReportDetectedDevice; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"MarkRamdisksAsRemovable"; queryEntry->EntryContext = &MarkRamdisksAsRemovable; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"MinimumViewCount"; queryEntry->EntryContext = &MinimumViewCount; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"DefaultViewCount"; queryEntry->EntryContext = &DefaultViewCount; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"MaximumViewCount"; queryEntry->EntryContext = &MaximumViewCount; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"MinimumViewLength"; queryEntry->EntryContext = &MinimumViewLength; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"DefaultViewLength"; queryEntry->EntryContext = &DefaultViewLength; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"MaximumViewLength"; queryEntry->EntryContext = &MaximumViewLength; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"MaximumPerDiskViewLength"; queryEntry->EntryContext = &MaximumPerDiskViewLength; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; #if SUPPORT_DISK_NUMBERS queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"DiskNumbersBitmapSize"; queryEntry->EntryContext = &DiskNumbersBitmapSize; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; #endif // SUPPORT_DISK_NUMBERS // // Do the query. // status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, RegistryPath->Buffer, queryTable, NULL, NULL ); // // Check the validity of the parameters. // if ( MinimumViewCount < MINIMUM_MINIMUM_VIEW_COUNT ) { MinimumViewCount = MINIMUM_MINIMUM_VIEW_COUNT; } else if ( MinimumViewCount > MAXIMUM_MINIMUM_VIEW_COUNT ) { MinimumViewCount = MAXIMUM_MINIMUM_VIEW_COUNT; } if ( DefaultViewCount < MinimumViewCount ) { DefaultViewCount = MinimumViewCount; } else if ( DefaultViewCount > MAXIMUM_DEFAULT_VIEW_COUNT ) { DefaultViewCount = MAXIMUM_DEFAULT_VIEW_COUNT; } if ( MaximumViewCount < DefaultViewCount ) { MaximumViewCount = DefaultViewCount; } else if ( MaximumViewCount > MAXIMUM_MAXIMUM_VIEW_COUNT ) { MaximumViewCount = MAXIMUM_MAXIMUM_VIEW_COUNT; } if ( MinimumViewLength < MINIMUM_MINIMUM_VIEW_LENGTH ) { MinimumViewLength = MINIMUM_MINIMUM_VIEW_LENGTH; } else if ( MinimumViewLength > MAXIMUM_MINIMUM_VIEW_LENGTH ) { MinimumViewLength = MAXIMUM_MINIMUM_VIEW_LENGTH; } if ( DefaultViewLength < MinimumViewLength ) { DefaultViewLength = MinimumViewLength; } else if ( DefaultViewLength > MAXIMUM_DEFAULT_VIEW_LENGTH ) { DefaultViewLength = MAXIMUM_DEFAULT_VIEW_LENGTH; } if ( MaximumViewLength < DefaultViewLength ) { MaximumViewLength = DefaultViewLength; } else if ( MaximumViewLength > MAXIMUM_MAXIMUM_VIEW_LENGTH ) { MaximumViewLength = MAXIMUM_MAXIMUM_VIEW_LENGTH; } if ( MaximumPerDiskViewLength < MINIMUM_MAXIMUM_PER_DISK_VIEW_LENGTH ) { MaximumPerDiskViewLength = MINIMUM_MAXIMUM_PER_DISK_VIEW_LENGTH; } else if ( MaximumViewLength > MAXIMUM_MAXIMUM_PER_DISK_VIEW_LENGTH ) { MaximumPerDiskViewLength = MAXIMUM_MAXIMUM_PER_DISK_VIEW_LENGTH; } #if SUPPORT_DISK_NUMBERS if ( DiskNumbersBitmapSize < MINIMUM_DISK_NUMBERS_BITMAP_SIZE ) { DiskNumbersBitmapSize = MINIMUM_DISK_NUMBERS_BITMAP_SIZE; } else if ( DiskNumbersBitmapSize > MAXIMUM_DISK_NUMBERS_BITMAP_SIZE ) { DiskNumbersBitmapSize = MAXIMUM_DISK_NUMBERS_BITMAP_SIZE; } #endif // SUPPORT_DISK_NUMBERS DBGPRINT( DBG_INIT, DBG_INFO, ("DefaultViewCount = 0x%x\n", DefaultViewCount) ); DBGPRINT( DBG_INIT, DBG_INFO, ("MaximumViewCount = 0x%x\n", MaximumViewCount) ); DBGPRINT( DBG_INIT, DBG_INFO, ("DefaultViewLength = 0x%x\n", DefaultViewLength) ); DBGPRINT( DBG_INIT, DBG_INFO, ("MaximumViewLength = 0x%x\n", MaximumViewLength) ); DBGPRINT( DBG_INIT, DBG_INFO, ("MaximumPerDiskViewLength = 0x%x\n", MaximumPerDiskViewLength) ); #if SUPPORT_DISK_NUMBERS DBGPRINT( DBG_INIT, DBG_INFO, ("DiskNumbersBitmapSize = 0x%x\n", DiskNumbersBitmapSize) ); #endif // SUPPORT_DISK_NUMBERS return; } // QueryParameters #if DBG NTSTATUS RamdiskInvalidDeviceRequest ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine is called by the I/O system when an IRP that we don't process is issued. Arguments: DeviceObject - a pointer to the object that represents the device on which I/O is to be performed Irp - a pointer to the I/O Request Packet for this request Return Value: NTSTATUS - STATUS_INVALID_DEVICE_REQUEST --*/ { // // We really do recognize CLEANUP and SHUTDOWN IRPs. For any other IRP, // print a message and break into the debugger. // switch ( IoGetCurrentIrpStackLocation(Irp)->MajorFunction ) { case IRP_MJ_CLEANUP: case IRP_MJ_SHUTDOWN: break; default: DBGPRINT( DBG_IOCTL, DBG_ERROR, ("Ramdisk: Unrecognized IRP: major/minor = %x/%x\n", IoGetCurrentIrpStackLocation(Irp)->MajorFunction, IoGetCurrentIrpStackLocation(Irp)->MinorFunction) ); ASSERT( FALSE ); } // // If this is a power IRP, we need to start the next one. // if ( IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_POWER ) { PoStartNextPowerIrp( Irp ); } // // Tell the I/O system that we don't recognize this IRP. // Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_INVALID_DEVICE_REQUEST; } // RamdiskInvalidDeviceRequest VOID QueryDebugParameters ( IN PUNICODE_STRING RegistryPath ) /*++ Routine Description: This routine is called from DriverEntry() to get the debug parameters from the registry. If the registry query fails, then default values are used. Arguments: RegistryPath - a pointer to the service path for the registry parameters Return Value: None. --*/ { NTSTATUS status; RTL_QUERY_REGISTRY_TABLE queryTable[5]; PRTL_QUERY_REGISTRY_TABLE queryEntry; PAGED_CODE(); DBGPRINT( DBG_INIT, DBG_VERBOSE, ("%s", "QueryDebugParameters\n") ); ASSERT( RegistryPath->Buffer != NULL ); // // Set the default values. // BreakOnEntry = DEFAULT_BREAK_ON_ENTRY; DebugComponents = DEFAULT_DEBUG_COMPONENTS; DebugLevel = DEFAULT_DEBUG_LEVEL; // // Set up the query table. // RtlZeroMemory( queryTable, sizeof(queryTable) ); // // We're looking for subkey "Debug" under the given registry key. // queryEntry = &queryTable[0]; queryEntry->Flags = RTL_QUERY_REGISTRY_SUBKEY; queryEntry->Name = L"Debug"; queryEntry->EntryContext = NULL; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; // // These are the values we want to read. // queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"BreakOnEntry"; queryEntry->EntryContext = &BreakOnEntry; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"DebugComponents"; queryEntry->EntryContext = &DebugComponents; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; queryEntry++; queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT; queryEntry->Name = L"DebugLevel"; queryEntry->EntryContext = &DebugLevel; queryEntry->DefaultType = REG_NONE; queryEntry->DefaultData = NULL; queryEntry->DefaultLength = 0; // // Do the query. // status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, RegistryPath->Buffer, queryTable, NULL, NULL ); DBGPRINT( DBG_INIT, DBG_INFO, ("BreakOnEntry = 0x%x\n", BreakOnEntry) ); DBGPRINT( DBG_INIT, DBG_INFO, ("DebugComponents = 0x%x\n", DebugComponents) ); DBGPRINT( DBG_INIT, DBG_INFO, ("DebugLevel = 0x%x\n", DebugLevel) ); return; } // QueryDebugParameters #endif