|
|
/*++
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 <initguid.h>
#include <ntddstor.h>
#include <ntddramd.h>
//
// 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
|