📄 pnp.c
字号:
/*++
Copyright (c) 1990-2000 Microsoft Corporation, All Rights Reserved
Copyright (c) 2002 QSoft
Module Name:
pnp.c
Abstract:
This is the code for handling PnP, Power and WMI IRPs
Author:
Raju Ramanathan 02/22/2000
Enviroment:
Kernel Mode Only
Revision History:
Code cleaning 04/19/2000
Minor changes 09/28/2002 by QSoft
*/
#include <stdio.h>
#include "ntddk.h"
#include "debug.h"
#include "ramdisk.h"
PCSTR StateTable[] ={
{ "STOPPED" },
{ "WORKING" },
{ "PENDINGSTOP" },
{ "PENDINGREMOVE" },
{ "SURPRISEREMOVED" },
{ "REMOVED" },
{ "UNKNOWN" }
};
NTSTATUS
RamDiskAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
AddDevice routine to create the device object and symbolic link
Arguments:
DriverObject - Supplies the driver object
PhysicalDeviceObject - Supplies the physical device object
Return Value:
NTSTATUS
--*/
{
PRAMDISK_DRIVER_EXTENSION driverExtension;
PDEVICE_OBJECT functionDeviceObject;
PDEVICE_EXTENSION devExt;
UNICODE_STRING uniDeviceName;
UNICODE_STRING uniWin32Name;
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE();
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE, ("AddDevice - IN. DriverObject=(%p) Pdo=(%p) \n",
DriverObject, PhysicalDeviceObject ) );
// Get the Driver object extension
driverExtension = IoGetDriverObjectExtension(DriverObject,
RAMDISK_DRIVER_EXTENSION_KEY);
ASSERT ( driverExtension != NULL );
//
// We are capable of handling only one device. If the we get AddDevice request
// for the next device, reject it
//
if ( driverExtension->DeviceInitialized == TRUE ) {
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_ERROR, ("Device exists\n") );
return STATUS_DEVICE_ALREADY_ATTACHED;
}
//
// Create counted string version of our device name.
//
RtlInitUnicodeString( &uniDeviceName, NT_DEVICE_NAME );
//
// Create the device object
//
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&uniDeviceName,
FILE_DEVICE_DISK , // old value = FILE_DEVICE_VIRTUAL_DISK , // corrected proposed by MS
(FILE_DEVICE_SECURE_OPEN),
FALSE, // This isn't an exclusive device
&functionDeviceObject
);
if (!NT_SUCCESS(status)) {
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_ERROR, ("IoCreateDevice error: 0x%x\n", status) );
return status;
}
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_INFO, ("FDO created successfully (%p)\n",
functionDeviceObject) );
devExt = functionDeviceObject->DeviceExtension;
RtlZeroMemory( devExt, sizeof(DEVICE_EXTENSION) );
// Allocate buffer for storing the drive letter
devExt->DiskRegInfo.DriveLetter.Buffer = ExAllocatePoolWithTag(
PagedPool,
DRIVE_LETTER_LENGTH,
RAMDISK_TAG_GENERAL);
if ( devExt->DiskRegInfo.DriveLetter.Buffer == NULL ) {
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_ERROR, ("Can't allocate memory for drive letter\n") );
RamDiskCleanUp( functionDeviceObject );
return STATUS_INSUFFICIENT_RESOURCES;
}
devExt->DiskRegInfo.DriveLetter.MaximumLength = DRIVE_LETTER_LENGTH;
//
// Get the disk parameters from the registry
//
RamDiskQueryDiskRegParameters( &driverExtension->RegistryPath, &devExt->DiskRegInfo );
devExt->PhysicalDeviceObject = PhysicalDeviceObject; // Save PDO pointer
devExt->DeviceObject = functionDeviceObject; // Save device object pointer
devExt->DevState = STOPPED; // Device starts in Stopped state
IoInitializeRemoveLock ( &devExt->RemoveLock,
REMLOCK_TAG,
REMLOCK_MAXIMUM,
REMLOCK_HIGHWATER);
// Set device flags
functionDeviceObject->Flags |= DO_POWER_PAGABLE;
functionDeviceObject->Flags |= DO_DIRECT_IO;
//
// Allocate the memory for disk image.
//
devExt->DiskImage =
ExAllocatePoolWithTag ( NonPagedPool,
devExt->DiskRegInfo.DiskSize,
RAMDISK_TAG_DISK ) ;
if ( devExt->DiskImage == NULL )
{
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_ERROR, ("Can't allocate memory for disk image\n") );
RamDiskCleanUp( functionDeviceObject );
return STATUS_INSUFFICIENT_RESOURCES;
}
// Format the disk
RamDiskFormatDisk( functionDeviceObject );
// Create symbolic link, which is the drive letter for the ramdisk
devExt->SymbolicLink.Buffer = ExAllocatePoolWithTag(
PagedPool,
DOS_DEVNAME_LENGTH,
RAMDISK_TAG_GENERAL);
if ( devExt->SymbolicLink.Buffer == NULL ) {
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_ERROR, ("Can't allocate memory for symbolic link\n") );
RamDiskCleanUp( functionDeviceObject );
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlInitUnicodeString( &uniWin32Name, DOS_DEVICE_NAME );
devExt->SymbolicLink.MaximumLength = DOS_DEVNAME_LENGTH;
devExt->SymbolicLink.Length = uniWin32Name.Length;
RtlCopyUnicodeString( &(devExt->SymbolicLink), &uniWin32Name );
RtlAppendUnicodeStringToString( &(devExt->SymbolicLink), &(devExt->DiskRegInfo.DriveLetter) );
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_NOTIFY, ("Creating drive letter = %wZ\n",&(devExt->SymbolicLink) ) );
// Create a drive letter from our device name to a name in the Win32 namespace.
status = IoCreateSymbolicLink( &devExt->SymbolicLink, &uniDeviceName );
if (!NT_SUCCESS(status)) {
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_ERROR, ("IoCreateSymbolicLink error: 0x%x\n", status) );
RamDiskCleanUp( functionDeviceObject );
return status;
}
devExt->Flags |= FLAG_LINK_CREATED;
devExt->LowerDeviceObject =
IoAttachDeviceToDeviceStack( functionDeviceObject, PhysicalDeviceObject );
if ( devExt->LowerDeviceObject == NULL ) {
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_ERROR, ("IoAttachDeviceToDeviceStack error\n") );
RamDiskCleanUp( functionDeviceObject );
return STATUS_NO_SUCH_DEVICE;
}
driverExtension->DeviceInitialized = TRUE;
// Clear DO_DEVICE_INITIALIZING flag
functionDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE, ("AddDevice - OUT. Fdo=(%p) LowerDevice=(%p)\n",
functionDeviceObject, devExt->LowerDeviceObject ) );
return status;
} // End of RamDiskAddDevice()
NTSTATUS
RamDiskDispatchPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Dispatch routine for Plug and Play IRPs
Arguments:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
Return Value:
NTSTATUS
--*/
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION devExt;
KEVENT event;
NTSTATUS status = STATUS_SUCCESS;
BOOLEAN lockHeld = TRUE;
PAGED_CODE();
irpStack = IoGetCurrentIrpStackLocation( Irp );
devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
ASSERT( devExt->DevState < MAX_STATE );
DBGPRINT( DBG_COMP_PNP, DBG_LEVEL_INFO, ("DispatchPnP - IN. Fdo=(%p) Irp=(%p) %s Device State=%s\n",
DeviceObject, Irp, GetPnpIrpName(irpStack->MinorFunction), StateTable[devExt->DevState] ) );
status = IoAcquireRemoveLock(&devExt->RemoveLock, Irp);
if (!NT_SUCCESS(status)) {
DBGPRINT( DBG_COMP_PNP, DBG_LEVEL_ERROR, ("Acquire RemoveLock failed\n" ) );
COMPLETE_REQUEST( Irp, status, 0 );
return status;
}
switch (irpStack->MinorFunction) {
case IRP_MN_START_DEVICE: {
KeInitializeEvent( &event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE) RamDiskIoCompletionRoutine,
(PVOID) &event, TRUE, TRUE, TRUE );
status = IoCallDriver( devExt->LowerDeviceObject, Irp );
if (status == STATUS_PENDING) {
KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
}
if ( NT_SUCCESS(status) ) {
//
// Device started successfully by the lower driver
//
devExt->DevState = WORKING;
}
COMPLETE_REQUEST( Irp, status, 0 );
break;
}
case IRP_MN_QUERY_STOP_DEVICE: {
devExt->DevState = PENDINGSTOP;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver( devExt->LowerDeviceObject, Irp );
break;
}
case IRP_MN_CANCEL_STOP_DEVICE: {
//
// Before sending the IRP down make sure we have received
// a IRP_MN_QUERY_STOP_DEVICE. We may get Cancel Stop
// without receiving a Query Stop earlier, if the
// driver on top fails a Query Stop and passes down the
// Cancel Stop.
//
if ( devExt->DevState == PENDINGSTOP ) {
devExt->DevState = WORKING;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver( devExt->LowerDeviceObject, Irp );
} else {
//
// A spurious Cancel Stop request. Just complete it
//
status = STATUS_SUCCESS;
COMPLETE_REQUEST( Irp, status, 0 );
}
break;
}
case IRP_MN_STOP_DEVICE: {
devExt->DevState = STOPPED;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver( devExt->LowerDeviceObject, Irp );
break;
}
case IRP_MN_QUERY_REMOVE_DEVICE: {
devExt->DevState = PENDINGREMOVE;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver( devExt->LowerDeviceObject, Irp );
break;
}
case IRP_MN_CANCEL_REMOVE_DEVICE: {
//
// Before sending the IRP down make sure we have received
// a IRP_MN_QUERY_REMOVE_DEVICE. We may get Cancel Remove
// without receiving a Query Remove earlier, if the
// driver on top fails a Query Remove and passes down the
// Cancel Remove.
//
if ( devExt->DevState == PENDINGREMOVE ) {
devExt->DevState = WORKING;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver( devExt->LowerDeviceObject, Irp );
} else {
//
// A spurious Cancel Remove request. Just complete it
//
status = STATUS_SUCCESS;
COMPLETE_REQUEST( Irp, status, 0 );
}
break;
}
case IRP_MN_SURPRISE_REMOVAL: {
devExt->DevState = SURPRISEREMOVED;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver( devExt->LowerDeviceObject, Irp );
break;
}
case IRP_MN_REMOVE_DEVICE: {
RamDiskRemoveDevice( DeviceObject, Irp );
//
// Remove Lock released by RamDiskRemoveDevice
//
lockHeld = FALSE;
break;
}
default: {
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver( devExt->LowerDeviceObject, Irp );
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -