|
|
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
pnp.c
Abstract:
This module contains the code for a serial imaging devices driver supporting PnP functionality
Author:
Vlad Sadovsky vlads 10-April-1998
Environment:
Kernel mode
Revision History :
vlads 04/10/1998 Created first draft
--*/
#include "serscan.h"
#include "serlog.h"
//#include <ntpoapi.h>
extern ULONG SerScanDebugLevel;
extern const PHYSICAL_ADDRESS PhysicalZero ;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, SerScanPnp)
#pragma alloc_text(PAGE, SerScanPower)
#endif
NTSTATUS SerScanPnp ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) /*++
Routine Description:
This routine handles all PNP IRPs, dispatching them as appropriate .
Arguments:
pDeviceObject - represents a device
pIrp - PNP Irp
Return Value:
STATUS_SUCCESS - if successful. STATUS_UNSUCCESSFUL - otherwise.
--*/ { NTSTATUS Status ; PDEVICE_EXTENSION Extension; PIO_STACK_LOCATION pIrpStack; PVOID pObject; ULONG NewReferenceCount; NTSTATUS ReturnStatus;
pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
Extension = pDeviceObject->DeviceExtension;
Status = STATUS_SUCCESS;
DebugDump(SERINITDEV,("Entering PnP Dispatcher\n"));
switch (pIrpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
//
// Initialize PendingIoEvent. Set the number of pending i/o requests for this device to 1.
// When this number falls to zero, it is okay to remove, or stop the device.
//
DebugDump(SERINITDEV,("Entering Start Device \n"));
KeInitializeEvent(&Extension -> PdoStartEvent, SynchronizationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(pIrp);
Status = WaitForLowerDriverToCompleteIrp( Extension->LowerDevice, pIrp, &Extension->PdoStartEvent);
if (!NT_SUCCESS(Status)) {
pIrp->IoStatus.Status = Status; pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT); return (Status);
}
#ifdef CREATE_SYMBOLIC_NAME
//
// Now setup the symbolic link for windows.
//
Status = IoCreateUnprotectedSymbolicLink(&Extension->SymbolicLinkName, &Extension->ClassName);
if (NT_SUCCESS(Status)) {
// We were able to create the symbolic link, so record this
// value in the extension for cleanup at unload time.
Extension->CreatedSymbolicLink = TRUE;
// Write out the result of the symbolic link to the registry.
Status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, L"Serial Scanners", Extension->ClassName.Buffer, REG_SZ, Extension->SymbolicLinkName.Buffer, Extension->SymbolicLinkName.Length + sizeof(WCHAR)); if (!NT_SUCCESS(Status)) {
//
// It didn't work. Just go to cleanup.
//
DebugDump(SERERRORS, ("SerScan: Couldn't create the device map entry\n" "-------- for port %wZ\n", &Extension->ClassName));
SerScanLogError(pDeviceObject->DriverObject, pDeviceObject, PhysicalZero, PhysicalZero, 0, 0, 0, 6, Status, SER_NO_DEVICE_MAP_CREATED); }
} else {
//
// Couldn't create the symbolic link.
//
Extension->CreatedSymbolicLink = FALSE;
ExFreePool(Extension->SymbolicLinkName.Buffer); Extension->SymbolicLinkName.Buffer = NULL;
DebugDump(SERERRORS, ("SerScan: Couldn't create the symbolic link\n" "-------- for port %wZ\n", &Extension->ClassName));
SerScanLogError(pDeviceObject->DriverObject, pDeviceObject, PhysicalZero, PhysicalZero, 0, 0, 0, 5, Status, SER_NO_SYMLINK_CREATED);
}
#endif
ExFreePool(Extension->ClassName.Buffer); Extension->ClassName.Buffer = NULL;
//
// Ignore status of link registry write - always succeed
//
//
// Clear InInit flag to indicate device object can be used
//
pDeviceObject->Flags &= ~(DO_DEVICE_INITIALIZING);
pIrp->IoStatus.Status = Status; pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT); return (Status);
break;
case IRP_MN_QUERY_REMOVE_DEVICE: //
// Always pass to lower device in stack after indicating that we don't object
//
DebugDump(SERALWAYS,("IRP_MN_QUERY_REMOVE_DEVICE\n"));
Extension->Removing = TRUE;
IoCopyCurrentIrpStackLocationToNext( pIrp ); return (IoCallDriver(Extension->LowerDevice, pIrp));
break;
case IRP_MN_CANCEL_REMOVE_DEVICE: //
// Always pass to lower device in stack , reset indicator as somebody canceled
//
DebugDump(SERALWAYS,("IRP_MN_CANCEL_REMOVE_DEVICE\n"));
Extension->Removing = FALSE;
//
// Kill symbolic link
//
if (Extension->CreatedSymbolicLink) { IoDeleteSymbolicLink(&Extension->SymbolicLinkName); Extension->CreatedSymbolicLink = FALSE; }
IoCopyCurrentIrpStackLocationToNext( pIrp ); return (IoCallDriver(Extension->LowerDevice, pIrp));
break;
case IRP_MN_SURPRISE_REMOVAL: //
// Should not ever happen with us, but still process
//
DebugDump(SERALWAYS,("IRP_MN_SURPRISE_REMOVAL\n"));
Extension->Removing = TRUE;
//
// Get rid of the symbolic link
//
SerScanHandleSymbolicLink( Extension->Pdo, &Extension->InterfaceNameString, FALSE );
#ifdef USE_EXECUTIVE_RESOURCE
ExAcquireResourceExclusiveLite( &Extension->Resource, TRUE ); #else
ExAcquireFastMutex(&Extension->Mutex); #endif
pObject = InterlockedExchangePointer(&Extension->AttachedFileObject,NULL); if (pObject) { ObDereferenceObject(pObject); }
pObject = InterlockedExchangePointer(&Extension->AttachedDeviceObject,NULL); if (pObject) { ObDereferenceObject(pObject); }
#ifdef USE_EXECUTIVE_RESOURCE
ExReleaseResourceLite(&Extension->Resource); #else
ExReleaseFastMutex(&Extension->Mutex); #endif
IoCopyCurrentIrpStackLocationToNext( pIrp ); return (IoCallDriver(Extension->LowerDevice, pIrp));
break;
case IRP_MN_REMOVE_DEVICE:
DebugDump(SERALWAYS,("IRP_MN_REMOVE_DEVICE\n"));
DebugDump(SERINITDEV,("Entering PnP Remove Device\n"));
//
// Stop new requests - device is being removed
//
Extension->Removing = TRUE;
//
// Get rid of the symbolic link
//
SerScanHandleSymbolicLink( Extension->Pdo, &Extension->InterfaceNameString, FALSE );
#ifdef USE_EXECUTIVE_RESOURCE
ExAcquireResourceExclusiveLite( &Extension->Resource, TRUE ); #else
ExAcquireFastMutex(&Extension->Mutex); #endif
pObject = InterlockedExchangePointer(&Extension->AttachedFileObject,NULL); if (pObject) { ObDereferenceObject(pObject); }
pObject = InterlockedExchangePointer(&Extension->AttachedDeviceObject,NULL); if (pObject) { ObDereferenceObject(pObject); }
#ifdef USE_EXECUTIVE_RESOURCE
ExReleaseResourceLite(&Extension->Resource); #else
ExReleaseFastMutex(&Extension->Mutex); #endif
//
// Send IRP down to lower device
//
IoCopyCurrentIrpStackLocationToNext( pIrp ); ReturnStatus = IoCallDriver(Extension->LowerDevice, pIrp);
//
// Decrement ref count
//
NewReferenceCount = InterlockedDecrement(&Extension->ReferenceCount);
if (NewReferenceCount != 0) { //
// Wait for any io requests pending in our driver to
// complete before finishing the remove
//
KeWaitForSingleObject(&Extension -> RemoveEvent, Suspended, KernelMode, FALSE, NULL); }
// ASSERT(&Extension->ReferenceCount == 0);
#ifdef USE_EXECUTIVE_RESOURCE
ExDeleteResourceLite(&Extension->Resource); #endif
DebugDump(SERALWAYS,("IRP_MN_QUERY_REMOVE_DEVICE - Calling IoDeleteDevice - gone\n"));
IoDetachDevice(Extension->LowerDevice);
//
// Free allocated resource.
//
if(NULL != Extension->ClassName.Buffer){ ExFreePool(Extension->ClassName.Buffer); } // if(NULL != Extension->ClassName.Buffer)
if(NULL != Extension->SymbolicLinkName.Buffer){ ExFreePool(Extension->SymbolicLinkName.Buffer); } // if(NULL != Extension->SymbolicLinkName.Buffer)
IoDeleteDevice(pDeviceObject);
return ReturnStatus;
break;
case IRP_MN_STOP_DEVICE: //
// Pass down
//
DebugDump(SERALWAYS,("IRP_MN_STOP_DEVICE\n"));
IoCopyCurrentIrpStackLocationToNext( pIrp ); return (IoCallDriver(Extension->LowerDevice, pIrp));
break;
case IRP_MN_QUERY_STOP_DEVICE: //
// Check open counts
//
DebugDump(SERALWAYS,("IRP_MN_QUERY_STOP_DEVICE\n"));
if (Extension->OpenCount > 0 ) { DebugDump(SERALWAYS,("Rejecting QUERY_STOP_DEVICE\n"));
pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL; }
IoCopyCurrentIrpStackLocationToNext( pIrp ); return (IoCallDriver(Extension->LowerDevice, pIrp));
break;
case IRP_MN_CANCEL_STOP_DEVICE: //
// Nothing to do here, but pass to lower
//
DebugDump(SERALWAYS,("IRP_MN_CANCEL_STOP_DEVICE\n"));
IoCopyCurrentIrpStackLocationToNext( pIrp ); return (IoCallDriver(Extension->LowerDevice, pIrp));
break;
case IRP_MN_QUERY_CAPABILITIES: {
ULONG i; KEVENT WaitEvent;
//
// Send this down to the PDO first
//
KeInitializeEvent(&WaitEvent, SynchronizationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(pIrp);
Status=WaitForLowerDriverToCompleteIrp( Extension->LowerDevice, pIrp, &WaitEvent );
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
for (i = PowerSystemUnspecified; i < PowerSystemMaximum; i++) {
Extension->SystemPowerStateMap[i]=PowerDeviceD3; }
for (i = PowerSystemUnspecified; i < PowerSystemHibernate; i++) {
Extension->SystemPowerStateMap[i]=pIrpStack->Parameters.DeviceCapabilities.Capabilities->DeviceState[i]; }
Extension->SystemPowerStateMap[PowerSystemWorking]=PowerDeviceD0;
Extension->SystemWake=pIrpStack->Parameters.DeviceCapabilities.Capabilities->SystemWake; Extension->DeviceWake=pIrpStack->Parameters.DeviceCapabilities.Capabilities->DeviceWake;
IoCompleteRequest( pIrp, IO_NO_INCREMENT ); return Status; }
break;
default:
//
// Unknown function - pass down
//
DebugDump(SERALWAYS,("Passing Pnp Irp down. MnFunc=%x , status = %x\n",pIrpStack->MinorFunction, Status));
IoCopyCurrentIrpStackLocationToNext( pIrp ); return (IoCallDriver(Extension->LowerDevice, pIrp));
break; }
//
// Complete the IRP...
//
if (!NT_SUCCESS(Status)) { pIrp -> IoStatus.Status = Status; pIrp->IoStatus.Information = 0; IoCompleteRequest( pIrp, IO_NO_INCREMENT ); } else {
DebugDump(SERALWAYS,("Passing Pnp Irp down, status = %x\n", Status));
IoCopyCurrentIrpStackLocationToNext(pIrp); Status = IoCallDriver(Extension->LowerDevice, pIrp); }
return( Status );
}
VOID DevicePowerCompleteRoutine( PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus ) {
return; }
NTSTATUS SerScanPower( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) /*++
Routine Description:
Process the Power IRPs sent to the PDO for this device.
Arguments:
pDeviceObject - pointer to the functional device object (FDO) for this device. pIrp - pointer to an I/O Request Packet
Return Value:
NT status code
--*/ { NTSTATUS Status; PDEVICE_EXTENSION Extension = pDeviceObject->DeviceExtension; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); POWER_STATE PowerState;
PAGED_CODE();
Status = STATUS_SUCCESS;
switch (pIrpStack->MinorFunction) {
case IRP_MN_SET_POWER:
if (pIrpStack->Parameters.Power.Type == SystemPowerState) { //
// system power state change
//
//
// request the change in device power state based on systemstate map
//
PowerState.DeviceState=Extension->SystemPowerStateMap[pIrpStack->Parameters.Power.State.SystemState];
PoRequestPowerIrp( Extension->Pdo, IRP_MN_SET_POWER, PowerState, DevicePowerCompleteRoutine, pIrp, NULL );
} else { //
// changing device state
//
PoSetPowerState( Extension->Pdo, pIrpStack->Parameters.Power.Type, pIrpStack->Parameters.Power.State );
}
break;
case IRP_MN_QUERY_POWER:
pIrp->IoStatus.Status = STATUS_SUCCESS;
break;
default:
break;
}
PoStartNextPowerIrp(pIrp);
IoSkipCurrentIrpStackLocation(pIrp);
Status=PoCallDriver(Extension->LowerDevice, pIrp);
return Status;
}
|