pnp.c
资源名称:虚拟串口驱动程序.rar [点击查看]
上传用户:zanmei2
上传日期:2010-03-06
资源大小:775k
文件大小:17k
源码类别:
通讯编程文档
开发平台:
C/C++
- /*++
- Copyright (c) 2005 Changzhi Zhou All Rights Reserved
- Module Name:
- pnp.c
- Abstract:
- This module works for the handles Plug&Play dispatch.
- Environment:
- Kernel mode
- Revision History:
- Changzhi Zhou Dec 20 2004
- --*/
- #include <ntddk.h>
- #include <initguid.h>
- #include "main.h"
- #include "tdiclient.h"
- #include "..incwdmioctl.h"
- NTSTATUS
- SamplePnpDispatch (
- 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;
- KIRQL oldIrql;
- PAGED_CODE();
- deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
- irpStack = IoGetCurrentIrpStackLocation(Irp);
- DebugPrint(("Sample %s IRP:0x%x n", PnPMinorFunctionString(irpStack->MinorFunction), Irp));
- if ( Removed == deviceExtension->DevicePnPState) {
- status = STATUS_DELETE_PENDING;
- return CompleteRequest(Irp, status, 0 );
- }
- status = STATUS_SUCCESS;
- SampleIoIncrement( deviceExtension );
- switch (irpStack->MinorFunction) {
- case IRP_MN_START_DEVICE:
- status = PnpStartDevice( DeviceObject, Irp);
- break;
- case IRP_MN_QUERY_STOP_DEVICE:
- status = PnpQueryStopDevice( DeviceObject, Irp );
- return status;
- case IRP_MN_CANCEL_STOP_DEVICE:
- status = PnpCancelStopDevice( DeviceObject, Irp );
- break;
- case IRP_MN_STOP_DEVICE:
- SET_NEW_PNP_STATE(deviceExtension, Stopped);
- SampleIoDecrement( deviceExtension );
- status = DefaultPnpHandler( DeviceObject, Irp );
- return status;
- case IRP_MN_QUERY_REMOVE_DEVICE:
- status = PnpQueryRemoveDevice( DeviceObject, Irp );
- return status;
- case IRP_MN_CANCEL_REMOVE_DEVICE:
- status = PnpCancelRemoveDevice( DeviceObject, Irp );
- break;
- case IRP_MN_REMOVE_DEVICE:
- status = PnpRemoveDevice( DeviceObject, Irp );
- return status;
- case IRP_MN_SURPRISE_REMOVAL:
- status = PnpSurpriseRemoval( DeviceObject, Irp );
- SampleIoDecrement( deviceExtension );
- return status;
- case IRP_MN_QUERY_CAPABILITIES:
- return PnpQueryCapabilities( DeviceObject, Irp );
- default:
- IoSkipCurrentIrpStackLocation(Irp);
- status = IoCallDriver(deviceExtension->NextLowerDriver, Irp);
- SampleIoDecrement(deviceExtension);
- return status;
- }
- CompleteRequest( Irp, status, 0 );
- SampleIoDecrement(deviceExtension);
- return status;
- }
- NTSTATUS PnpStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
- /*++
- Routine Description:
- Pnp handler to IRP_MN_START_DEVICE.
- Arguments:
- deviceExtension - pointer to a device object extension.
- Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
- Return Value:
- NT status code.
- --*/
- {
- NTSTATUS status;
- PDEVICE_EXTENSION deviceExtension;
- PIO_STACK_LOCATION irpStack;
- KIRQL oldIrql;
- deviceExtension = DeviceObject->DeviceExtension;
- status = ForwardAndWait( DeviceObject, Irp);
- if ( !NT_SUCCESS( status ) )
- return CompleteRequest(Irp, status, Irp->IoStatus.Information);
- irpStack = IoGetCurrentIrpStackLocation( Irp );
- //status = CreateWorkThread( deviceExtension );
- // Open transport address, set clienteventhandler and initialize recvContext.
- status = InitializeConnection( deviceExtension );
- if( NT_SUCCESS( status ) && NT_SUCCESS( Irp->IoStatus.Status ) ){
- status = IoSetDeviceInterfaceState( &deviceExtension->InterfaceName, TRUE );
- if( !NT_SUCCESS( status )){
- DebugPrint(( "StartDevice: IoSetDeviceInterfaceState failed (%x)n", status ));
- }
- SET_NEW_PNP_STATE( deviceExtension, Working );
- }
- return status;
- }
- NTSTATUS
- PnpQueryStopDevice(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
- /*++
- Routine Description:
- Pnp handler to IRP_MN_QUERY_STOP_DEVICE.
- Arguments:
- deviceExtension - pointer to a device object extension.
- Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
- Return Value:
- NT status code.
- --*/
- {
- KIRQL oldIrql;
- NTSTATUS status;
- PDEVICE_EXTENSION deviceExtension;
- deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
- //
- // If we can stop the device, we need to set the QueueState to
- // PendingStop so further requests will be queued.
- //
- SET_NEW_PNP_STATE(deviceExtension, PendingStop);
- SampleIoDecrement( deviceExtension );
- KeWaitForSingleObject(&deviceExtension->StopEvent,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- status = DefaultPnpHandler( DeviceObject, Irp );
- return status;
- }
- NTSTATUS
- PnpCancelStopDevice(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
- /*++
- Routine Description:
- Pnp handler to IRP_MN_CANCEL_STOP_DEVICE.
- Arguments:
- deviceExtension - pointer to a device object extension.
- Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
- Return Value:
- NT status code.
- --*/
- {
- KIRQL oldIrql;
- KEVENT event;
- NTSTATUS status;
- PDEVICE_EXTENSION deviceExtension;
- deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
- //
- // Send this IRP down and wait for it to come back.
- // Set the QueueState flag to AllowRequests,
- // and process all the previously queued up IRPs.
- //
- //
- // First 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(PendingStop == deviceExtension->DevicePnPState) {
- status = ForwardAndWait( DeviceObject, Irp );
- if(NT_SUCCESS( status )) {
- RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
- }
- }
- else {
- status = STATUS_SUCCESS;
- }
- return status;
- }
- NTSTATUS
- PnpQueryRemoveDevice(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
- /*++
- Routine Description:
- Pnp handler to IRP_MN_QUERY_REMOVE_DEVICE.
- Arguments:
- deviceExtension - pointer to a device object extension.
- Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
- Return Value:
- NT status code.
- --*/
- {
- #define WDM_DELAY_VALUE (ULONG)(-1 * 20000 * 1000) // 2s
- KIRQL oldIrql;
- NTSTATUS status;
- PDEVICE_EXTENSION deviceExtension;
- LARGE_INTEGER deltaTime;
- deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
- SampleIoDecrement( deviceExtension );
- deltaTime.LowPart = WDM_DELAY_VALUE;
- deltaTime.HighPart = -1;
- //
- // Wait deltaTime for all the requests to be completed.
- // If timeout, that means some Irps haven't be completed.
- // So we will simply return Device_Busy and not pass down to lower driver.
- //
- status = KeWaitForSingleObject(&deviceExtension->StopEvent,
- Executive,
- KernelMode,
- FALSE,
- &deltaTime);
- if( STATUS_TIMEOUT == status )
- return CompleteRequest( Irp, STATUS_DEVICE_BUSY, 0 );
- //
- // If we can allow removal of the device, we should set the QueueState
- // to HoldRequests so further requests will be queued. This is required
- // so that we can process queued up requests in cancel-remove just in
- // case somebody else in the stack fails the query-remove.
- //
- SET_NEW_PNP_STATE(deviceExtension, PendingRemove );
- status = DefaultPnpHandler( DeviceObject, Irp );
- return status;
- }
- NTSTATUS
- PnpCancelRemoveDevice(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
- /*++
- Routine Description:
- Pnp handler to IRP_MN_CANEL_REMOVE_DEVICE.
- Arguments:
- deviceExtension - pointer to a device object extension.
- Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
- Return Value:
- NT status code.
- --*/
- {
- NTSTATUS status;
- PDEVICE_EXTENSION deviceExtension;
- KIRQL oldIrql;
- //
- // initialize variables
- //
- deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
- //
- // We need to reset the QueueState flag to ProcessRequest,
- // since the device resume its normal activities.
- //
- //
- // First 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(PendingRemove == deviceExtension->DevicePnPState) {
- status = ForwardAndWait( DeviceObject, Irp );
- if(NT_SUCCESS( status )) {
- RESTORE_PREVIOUS_PNP_STATE( deviceExtension );
- }
- // Re-start workthread. omit now.
- //
- }
- else {
- //
- // spurious cancel-remove
- //
- status = STATUS_SUCCESS;
- }
- return status;
- }
- NTSTATUS PnpRemoveDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
- /*++
- Routine Description:
- Pnp handler to IRP_MN_REMOVE_DEVICE.
- Arguments:
- deviceExtension - pointer to a device object extension.
- Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
- Return Value:
- NT status code.
- --*/
- {
- NTSTATUS status;
- PDEVICE_EXTENSION deviceExtension;
- KIRQL oldIrql;
- ULONG requestCount;
- DebugPrint(("+Enter RemoveDevice routinen" ));
- deviceExtension = DeviceObject->DeviceExtension;
- // TODO: handle our remove work at first
- if ( SurpriseRemoved != deviceExtension->DevicePnPState )
- {
- //
- // If the device is not surprise removed, we should call set interface to FALSE.
- // If surprise removed, This step has been called in SurprisedRemoved handle.
- //
- status = IoSetDeviceInterfaceState( &deviceExtension->InterfaceName, FALSE );
- if( !NT_SUCCESS( status ) ){
- DebugPrint(( "RemoveDevice: IoSetDeviceInterfaceState failed (%x)n", status ));
- }
- }
- // set new PNP state
- SET_NEW_PNP_STATE(deviceExtension, Removed );
- requestCount = SampleIoDecrement( deviceExtension );
- ASSERT(requestCount > 0);
- requestCount = SampleIoDecrement( deviceExtension );
- KeWaitForSingleObject(&deviceExtension->RemoveEvent,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Disconnection( deviceExtension );
- // Unregister serial DosName and delete register
- SerialUndoExternalNaming( deviceExtension );
- // delete buffer pool used for device name , dos name and others.
- SerialRemoveDevObj( DeviceObject );
- RtlFreeUnicodeString( &deviceExtension->InterfaceName );
- Disconnection( deviceExtension );
- if ( deviceExtension->RxBuffer )
- ExFreePool ( deviceExtension->RxBuffer );
- if ( deviceExtension->recvContext.RemainderBuffer )
- ExFreePool ( deviceExtension->recvContext.RemainderBuffer );
- // Pass down the IRP
- status = DefaultPnpHandler( DeviceObject, Irp );
- IoDetachDevice( deviceExtension->NextLowerDriver );
- //
- // Free up interface memory
- //
- IoDeleteDevice( DeviceObject );
- DebugPrint(("-Exit RemoveDevice routinen"));
- return status;
- }
- NTSTATUS
- PnpSurpriseRemoval(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
- /*++
- Routine Description:
- Pnp handler to IRP_MN_SURPRISE_REMOVAL.
- Arguments:
- deviceExtension - pointer to a device object extension.
- Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
- Return Value:
- NT status code.
- --*/
- {
- KIRQL oldIrql;
- NTSTATUS status;
- PDEVICE_EXTENSION deviceExtension;
- deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
- // set new PNP state
- SET_NEW_PNP_STATE(deviceExtension, SurpriseRemoved );
- status = IoSetDeviceInterfaceState( &deviceExtension->InterfaceName, FALSE );
- if( !NT_SUCCESS( status ) ){
- DebugPrint(( "RemoveDevice: IoSetDeviceInterfaceState failed (%x)n", status ));
- }
- status = DefaultPnpHandler( DeviceObject, Irp );
- return status;
- }
- NTSTATUS PnpQueryCapabilities( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
- /*++
- Routine Description:
- Pnp handler to IRP_MN_QUERY_CAPABILITIES.
- Arguments:
- deviceExtension - pointer to a device object extension.
- Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
- Return Value:
- NT status code.
- --*/
- {
- NTSTATUS status;
- PIO_STACK_LOCATION stack;
- PDEVICE_CAPABILITIES deviceCapabilities;
- PAGED_CODE ();
- status = ForwardAndWait( DeviceObject, Irp );
- stack = IoGetCurrentIrpStackLocation (Irp);
- //
- // add our device's capabilities.
- //
- deviceCapabilities = stack->Parameters.DeviceCapabilities.Capabilities;
- //
- // thess mean the device is Removeable and NOT surprise removed.
- // If user force to surprise remove the device, "Unsafe remove device" dialog will appear.
- //
- deviceCapabilities->SurpriseRemovalOK = FALSE;
- //deviceCapabilities->Removable = TRUE;
- status = CompleteRequest( Irp, status, Irp->IoStatus.Information );
- SampleIoDecrement( DeviceObject->DeviceExtension );
- return status;
- }
- NTSTATUS DefaultPnpHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
- {
- PDEVICE_EXTENSION deviceExtension;
- deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
- IoSkipCurrentIrpStackLocation( Irp );
- return IoCallDriver( deviceExtension->NextLowerDriver, Irp);
- }
- NTSTATUS ForwardAndWait(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
- /*++
- Routine Description:
- pass down Irp to lower driver and wait for its completion.
- Arguments:
- deviceExtension - pointer to a device object extension.
- Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
- Return Value:
- NT status code.
- --*/
- {
- KEVENT event;
- NTSTATUS status;
- PDEVICE_EXTENSION deviceExtension;
- deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;
- KeInitializeEvent(&event, NotificationEvent, FALSE);
- IoCopyCurrentIrpStackLocationToNext( Irp );
- IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)
- OnRequestComplete, (PVOID) &event, TRUE, TRUE, TRUE);
- status = IoCallDriver( deviceExtension->NextLowerDriver, Irp);
- if (status == STATUS_PENDING)
- { // wait for completion
- KeWaitForSingleObject(
- &event,
- Executive, // Waiting for reasion of a driver
- KernelMode, // Waiting in kernel mode
- FALSE, // No alert
- NULL); // No timeout
- status = Irp->IoStatus.Status;
- } // wait for completion
- return status;
- }
- NTSTATUS OnRequestComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
- IN PKEVENT event)
- {
- KeSetEvent( event, 0, FALSE);
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- #if DBG
- PCHAR
- PnPMinorFunctionString (
- UCHAR MinorFunction
- )
- /*++
- Routine Description:
- Print PnP Irp's minor function informaion.
- Arguments:
- deviceExtension - pointer to a device object extension.
- Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
- Return Value:
- NT status code.
- --*/
- {
- switch (MinorFunction)
- {
- case IRP_MN_START_DEVICE:
- return "IRP_MN_START_DEVICE";
- case IRP_MN_QUERY_REMOVE_DEVICE:
- return "IRP_MN_QUERY_REMOVE_DEVICE";
- case IRP_MN_REMOVE_DEVICE:
- return "IRP_MN_REMOVE_DEVICE";
- case IRP_MN_CANCEL_REMOVE_DEVICE:
- return "IRP_MN_CANCEL_REMOVE_DEVICE";
- case IRP_MN_STOP_DEVICE:
- return "IRP_MN_STOP_DEVICE";
- case IRP_MN_QUERY_STOP_DEVICE:
- return "IRP_MN_QUERY_STOP_DEVICE";
- case IRP_MN_CANCEL_STOP_DEVICE:
- return "IRP_MN_CANCEL_STOP_DEVICE";
- case IRP_MN_QUERY_DEVICE_RELATIONS:
- return "IRP_MN_QUERY_DEVICE_RELATIONS";
- case IRP_MN_QUERY_INTERFACE:
- return "IRP_MN_QUERY_INTERFACE";
- case IRP_MN_QUERY_CAPABILITIES:
- return "IRP_MN_QUERY_CAPABILITIES";
- case IRP_MN_QUERY_RESOURCES:
- return "IRP_MN_QUERY_RESOURCES";
- case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
- return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS";
- case IRP_MN_QUERY_DEVICE_TEXT:
- return "IRP_MN_QUERY_DEVICE_TEXT";
- case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
- return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS";
- case IRP_MN_READ_CONFIG:
- return "IRP_MN_READ_CONFIG";
- case IRP_MN_WRITE_CONFIG:
- return "IRP_MN_WRITE_CONFIG";
- case IRP_MN_EJECT:
- return "IRP_MN_EJECT";
- case IRP_MN_SET_LOCK:
- return "IRP_MN_SET_LOCK";
- case IRP_MN_QUERY_ID:
- return "IRP_MN_QUERY_ID";
- case IRP_MN_QUERY_PNP_DEVICE_STATE:
- return "IRP_MN_QUERY_PNP_DEVICE_STATE";
- case IRP_MN_QUERY_BUS_INFORMATION:
- return "IRP_MN_QUERY_BUS_INFORMATION";
- case IRP_MN_DEVICE_USAGE_NOTIFICATION:
- return "IRP_MN_DEVICE_USAGE_NOTIFICATION";
- case IRP_MN_SURPRISE_REMOVAL:
- return "IRP_MN_SURPRISE_REMOVAL";
- default:
- return "IRP_MN_?????";
- }
- }
- #endif