📄 pnp.c
字号:
#include <ntddk.h>
#include <ntddser.h>
#include "main.h"
#include "..\inc\wdmioctl.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, DispatchPnp)
#endif
extern DEVICE_ARRAY gDeviceArray[ MAX_NUM_DEV ];
extern KSPIN_LOCK gSpinLock;
NTSTATUS
DispatchPnp (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
The plug and play dispatch routines.
Most of these the driver will completely ignore.
In all cases it must pass on the IRP to the lower driver.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
NTSTATUS status;
KEVENT event;
PAGED_CODE();
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
DebugPrint(("Sample %s IRP:0x%x \n",
PnPMinorFunctionString(irpStack->MinorFunction), Irp));
status = STATUS_SUCCESS;
switch (irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
status = PnpStartDevice( DeviceObject, Irp);
return status;
case IRP_MN_REMOVE_DEVICE:
status = PnpRemoveDevice( DeviceObject, Irp );
return status;
case IRP_MN_QUERY_STOP_DEVICE:
SET_NEW_PNP_STATE(deviceExtension, StopPending);
status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_STOP_DEVICE:
//
// Check to see whether you have received cancel-stop
// without first receiving a query-stop. This could happen if someone
// above us fails a query-stop and passes down the subsequent
// cancel-stop.
//
if(StopPending == deviceExtension->DevicePnPState)
{
//
// We did receive a query-stop, so restore.
//
RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
}
status = STATUS_SUCCESS; // We must not fail this IRP.
break;
case IRP_MN_STOP_DEVICE:
SET_NEW_PNP_STATE(deviceExtension, StopPending);
status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
SET_NEW_PNP_STATE(deviceExtension, RemovePending);
status = STATUS_SUCCESS;
break;
case IRP_MN_SURPRISE_REMOVAL:
SET_NEW_PNP_STATE(deviceExtension, SurpriseRemovePending);
status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
//
// Check to see whether you have received cancel-remove
// without first receiving a query-remove. This could happen if
// someone above us fails a query-remove and passes down the
// subsequent cancel-remove.
//
if(RemovePending == deviceExtension->DevicePnPState)
{
//
// We did receive a query-remove, so restore.
//
RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
}
status = STATUS_SUCCESS; // We must not fail this IRP.
break;
default:
//
// If you don't handle any IRP you must leave the
// status as is.
//
status = Irp->IoStatus.Status;
break;
}
//
// Pass the IRP down and forget it.
//
Irp->IoStatus.Status = status;
return DefaultPnpHandler( DeviceObject, Irp );
}
NTSTATUS PnpStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION stack;
deviceExtension = DeviceObject->DeviceExtension;
status = ForwardAndWait( DeviceObject, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, Irp->IoStatus.Information);
stack = IoGetCurrentIrpStackLocation( Irp );
// TODO: other work to start the device in this layer driver
status = SerialFinishStartDevice( deviceExtension );
if( !NT_SUCCESS( status ) ){
return CompleteRequest( Irp, status, 0 );
}
// 添加Interface,给win32 App提供访问接口
status = AddInterface( deviceExtension );
if( NT_SUCCESS( status ) && NT_SUCCESS( Irp->IoStatus.Status ) ){
SET_NEW_PNP_STATE( deviceExtension, Started );
}
return CompleteRequest(Irp, status, 0);
}
NTSTATUS PnpRemoveDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension;
DebugPrint(("+Enter RemoveDevice routine\n" ));
deviceExtension = DeviceObject->DeviceExtension;
// TODO: handle our remove work at first
SerialUndoExternalNaming( deviceExtension );
// 删除Interface
DelInterface( deviceExtension );
SerialRemoveDevObj( DeviceObject );
// Pass down the IRP
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver( deviceExtension->NextLowerDriver, Irp );
SET_NEW_PNP_STATE(deviceExtension, Deleted);
DebugPrint( ("NextLowerDriver: 0x%x\n", deviceExtension->NextLowerDriver ));
IoDetachDevice( deviceExtension->NextLowerDriver );
gDeviceArray[ deviceExtension->localInstance ].deviceExtension = NULL;
IoDeleteDevice( DeviceObject );
DebugPrint(("-Exit RemoveDevice routine\n"));
return status;
}
NTSTATUS
SerialCreateDevObj(
IN PDRIVER_OBJECT DriverObject,
OUT PDEVICE_OBJECT *NewDeviceObject
)
{
UNICODE_STRING deviceObjName;
UNICODE_STRING instanceStr;
PDEVICE_OBJECT deviceObject = NULL;
PDEVICE_EXTENSION pDevExt;
NTSTATUS status = STATUS_SUCCESS;
WCHAR instanceNumberBuffer[20];
ULONG currentInstance;
PAGED_CODE();
DebugPrint(("Enter SerialCreateDevObj\n"));
for( currentInstance = 0; currentInstance < MAX_NUM_DEV; currentInstance++){
// find the first empty device description in gDeviceArray
if( gDeviceArray[ currentInstance ].deviceExtension == NULL ){
break;
}
}
if( currentInstance == MAX_NUM_DEV ){
DebugPrint(("There is no memory in gDeviceArray\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
*NewDeviceObject = NULL;
return status;
}
// 首先处理deviceObjName,这是一个核心态使用的设备名,形如"\\Device\\SiSerial0"
// Zero out allocated memory pointers so we know if they must be freed
RtlZeroMemory(&deviceObjName, sizeof(UNICODE_STRING));
deviceObjName.MaximumLength = DEVICE_OBJECT_NAME_LENGTH * sizeof(WCHAR);
deviceObjName.Buffer = ExAllocatePool(PagedPool, deviceObjName.MaximumLength + sizeof(WCHAR));
if (deviceObjName.Buffer == NULL) {
DebugPrint(("Couldn't allocate memory for device name\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory( deviceObjName.Buffer, deviceObjName.MaximumLength + sizeof(WCHAR));
// now, the size of deviceObjName.Buffer is (128 + 1)(WCHAR)
RtlAppendUnicodeToString(&deviceObjName, DEVICE_NAME); // L"\\Device\\SiSerial"
// 处理deviceObjName的后缀序号
RtlInitUnicodeString(&instanceStr, NULL);
instanceStr.MaximumLength = sizeof(instanceNumberBuffer);
instanceStr.Buffer = instanceNumberBuffer; // 20 WCHAR
RtlIntegerToUnicodeString( currentInstance, 10, &instanceStr);
RtlAppendUnicodeStringToString( &deviceObjName, &instanceStr);
DebugPrint(("DeviceName:\n"));
DebugPrint(("----------- %ws\n", deviceObjName.Buffer ));
//
// Create the device object
//
status = IoCreateDevice(DriverObject, sizeof( DEVICE_EXTENSION ),
&deviceObjName, FILE_DEVICE_SERIAL_PORT,
FILE_DEVICE_SECURE_OPEN, TRUE, &deviceObject);
if (!NT_SUCCESS(status)) {
DebugPrint(("SerialAddDevice: Create device failed - %x \n", status ));
goto SerialCreateDevObjError;
}
ASSERT(deviceObject != NULL);
gDeviceArray[ currentInstance ].deviceExtension = deviceObject->DeviceExtension;
pDevExt = deviceObject->DeviceExtension;
//
// The device object has a pointer to an area of non-paged
// pool allocated for this device. This will be the device
// extension. Zero it out.
//
RtlZeroMemory( pDevExt, sizeof( DEVICE_EXTENSION ) );
// 在DeviceExtension中保存deviceName
pDevExt->DeviceName.Buffer =
ExAllocatePool(PagedPool, deviceObjName.Length + sizeof(WCHAR));
if (!pDevExt->DeviceName.Buffer) {
DebugPrint(("SERIAL: Couldn't allocate memory for DeviceName\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
goto SerialCreateDevObjError;
}
pDevExt->DeviceName.MaximumLength = deviceObjName.Length + sizeof(WCHAR);
// Zero fill it.
RtlZeroMemory(pDevExt->DeviceName.Buffer, pDevExt->DeviceName.MaximumLength);
RtlAppendUnicodeStringToString(&pDevExt->DeviceName, &deviceObjName);
//++ Initialize common devExtension
// 设置本设备的instance序号和与其相联接的设备序号(目前是没有连接,所以设为Invalid_Instance
pDevExt->localInstance = currentInstance;
pDevExt->remoteInstance = INVALID_INSTANCE;
pDevExt->Self = deviceObject;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -