windows-nt/Source/XPSP1/NT/drivers/storage/ramdisk/ramdisk.c
2020-09-26 16:20:57 +08:00

1257 lines
30 KiB
C

/*++
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