📄 pnp.c
字号:
/*++
Copyright (c) 1997-1998 Microsoft Corporation, All Rights Reserved
Module Name:
pnp.c
Abstract:
This module contains plug & play code for the serial Mouse Filter Driver,
including code for the creation and removal of serial mouse device contexts.
Environment:
Kernel & user mode.
Revision History:
--*/
#include "mouser.h"
#include "sermlog.h"
#include "debug.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, SerialMouseAddDevice)
#pragma alloc_text(PAGE, SerialMousePnP)
#pragma alloc_text(PAGE, SerialMousePower)
#pragma alloc_text(PAGE, SerialMouseRemoveDevice)
#pragma alloc_text(PAGE, SerialMouseSendIrpSynchronously)
#endif
NTSTATUS
SerialMouseAddDevice (
IN PDRIVER_OBJECT Driver,
IN PDEVICE_OBJECT PDO
)
/*++
Routine Description:
Arguments:
Return Value:
NTSTATUS result code.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
PDEVICE_OBJECT device;
KIRQL oldIrql;
PAGED_CODE();
status = IoCreateDevice(Driver,
sizeof(DEVICE_EXTENSION),
NULL, // no name for this Filter DO
FILE_DEVICE_SERIAL_MOUSE_PORT,
0,
FALSE,
&device);
if (!NT_SUCCESS(status)) {
return status;
}
deviceExtension = (PDEVICE_EXTENSION) device->DeviceExtension;
Print(deviceExtension, DBG_PNP_TRACE, ("enter Add Device\n"));
//
// Initialize the fields.
//
RtlZeroMemory(deviceExtension, sizeof(DEVICE_EXTENSION));
deviceExtension->TopOfStack = IoAttachDeviceToDeviceStack(device, PDO);
if (deviceExtension->TopOfStack == NULL) {
PIO_ERROR_LOG_PACKET errorLogEntry;
//
// Not good; in only extreme cases will this fail
//
errorLogEntry = (PIO_ERROR_LOG_PACKET)
IoAllocateErrorLogEntry(Driver,
(UCHAR) sizeof(IO_ERROR_LOG_PACKET));
if (errorLogEntry) {
errorLogEntry->ErrorCode = SERMOUSE_ATTACH_DEVICE_FAILED;
errorLogEntry->DumpDataSize = 0;
errorLogEntry->SequenceNumber = 0;
errorLogEntry->MajorFunctionCode = 0;
errorLogEntry->IoControlCode = 0;
errorLogEntry->RetryCount = 0;
errorLogEntry->UniqueErrorValue = 0;
errorLogEntry->FinalStatus = STATUS_DEVICE_NOT_CONNECTED;
IoWriteErrorLogEntry(errorLogEntry);
}
IoDeleteDevice(device);
return STATUS_DEVICE_NOT_CONNECTED;
}
ASSERT(deviceExtension->TopOfStack);
deviceExtension->PDO = PDO;
deviceExtension->Self = device;
deviceExtension->Removed = FALSE;
deviceExtension->Started = FALSE;
deviceExtension->Stopped = FALSE;
deviceExtension->PowerState = PowerDeviceD0;
deviceExtension->WaitWakePending = FALSE;
KeInitializeSpinLock(&deviceExtension->PnpStateLock);
KeInitializeEvent(&deviceExtension->StopEvent, SynchronizationEvent, FALSE);
IoInitializeRemoveLock(&deviceExtension->RemoveLock, SERMOU_POOL_TAG, 0, 10);
deviceExtension->ReadIrp = IoAllocateIrp( device->StackSize, FALSE );
if (!deviceExtension->ReadIrp) {
//
// The ReadIrp is critical to this driver, if we can't get one, no use
// in going any further
//
IoDetachDevice(deviceExtension->TopOfStack);
IoDeleteDevice(device);
return STATUS_INSUFFICIENT_RESOURCES;
}
deviceExtension->WmiLibInfo.GuidCount = sizeof(WmiGuidList) /
sizeof(WMIGUIDREGINFO);
deviceExtension->WmiLibInfo.GuidList = WmiGuidList;
deviceExtension->WmiLibInfo.QueryWmiRegInfo = SerialMouseQueryWmiRegInfo;
deviceExtension->WmiLibInfo.QueryWmiDataBlock = SerialMouseQueryWmiDataBlock;
deviceExtension->WmiLibInfo.SetWmiDataBlock = SerialMouseSetWmiDataBlock;
deviceExtension->WmiLibInfo.SetWmiDataItem = SerialMouseSetWmiDataItem;
deviceExtension->WmiLibInfo.ExecuteWmiMethod = NULL;
deviceExtension->WmiLibInfo.WmiFunctionControl = NULL;
IoWMIRegistrationControl(deviceExtension->Self, WMIREG_ACTION_REGISTER);
KeInitializeTimer(&deviceExtension->DelayTimer);
//
// Set all the appropriate device object flags
//
device->Flags &= ~DO_DEVICE_INITIALIZING;
device->Flags |= DO_BUFFERED_IO;
device->Flags |= DO_POWER_PAGABLE;
return status;
}
VOID
SerialMouseRemoveDevice(
PDEVICE_EXTENSION DeviceExtension,
PIRP Irp
)
{
BOOLEAN closePort = FALSE;
PAGED_CODE();
//
// Run the (surprise remove code). If we are surprise removed, then this
// will be called twice. We only run the removal code once.
//
if (!DeviceExtension->SurpriseRemoved) {
DeviceExtension->SurpriseRemoved = TRUE;
//
// Here if we had any outstanding requests in a personal queue we should
// complete them all now.
//
// Note, the device could be GONE so we cannot send it any non-
// PNP IRPS.
//
IoWMIRegistrationControl(DeviceExtension->Self, WMIREG_ACTION_DEREGISTER);
if (DeviceExtension->Started && DeviceExtension->EnableCount > 0) {
Print(DeviceExtension, DBG_PNP_INFO,
("Cancelling and stopping detection for remove\n"));
IoCancelIrp(DeviceExtension->ReadIrp);
//
// Cancel the detection timer, SerialMouseRemoveLockAndWait will
// guarantee that we don't yank the device from under the polling
// routine
//
SerialMouseStopDetection(DeviceExtension);
}
}
//
// The stack is about to be torn down, make sure that the underlying serial
// port is closed. No other piece of code will be looking at EnableCount if
// Remove is true, so there is no need for InterlockedXxx.
//
if (DeviceExtension->Removed && DeviceExtension->EnableCount > 0) {
Print(DeviceExtension, DBG_PNP_INFO | DBG_PNP_ERROR,
("sending final close, enable count %d\n",
DeviceExtension->EnableCount));
DeviceExtension->EnableCount = 0;
SerialMouseClosePort(DeviceExtension, Irp);
}
}
NTSTATUS
SerialMouseCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PKEVENT Event
)
/*++
Routine Description:
The pnp IRP is in the process of completing.
signal
Arguments:
Context set to the device object in question.
--*/
{
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
KeSetEvent(Event, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
SerialMouseSendIrpSynchronously (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN BOOLEAN CopyToNext
)
{
KEVENT event;
NTSTATUS status;
PAGED_CODE();
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
if (CopyToNext) {
IoCopyCurrentIrpStackLocationToNext(Irp);
}
IoSetCompletionRoutine(Irp,
SerialMouseCompletionRoutine,
&event,
TRUE, // on success
TRUE, // on error
TRUE // on cancel
);
status = IoCallDriver(DeviceObject, Irp);
//
// Wait for lower drivers to be done with the Irp
//
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL
);
status = Irp->IoStatus.Status;
}
return status;
}
void
SerialMouseHandleStartStopStart(
IN PDEVICE_EXTENSION DeviceExtension
)
{
KIRQL irql;
KeAcquireSpinLock(&DeviceExtension->PnpStateLock, &irql);
if (DeviceExtension->Stopped) {
DeviceExtension->Stopped = FALSE;
IoReuseIrp(DeviceExtension->ReadIrp, STATUS_SUCCESS);
}
KeReleaseSpinLock(&DeviceExtension->PnpStateLock, irql);
}
void
SerialMouseStopDevice (
IN PDEVICE_EXTENSION DeviceExtension
)
{
KIRQL irql;
KeAcquireSpinLock(&DeviceExtension->PnpStateLock, &irql);
DeviceExtension->Stopped = TRUE;
KeReleaseSpinLock(&DeviceExtension->PnpStateLock, irql);
if (DeviceExtension->Started) {
Print(DeviceExtension, DBG_PNP_INFO,
("Cancelling and stopping detection for stop\n"));
DeviceExtension->Started = FALSE;
//
// Stop detection and cancel the read
//
SerialMouseStopDetection(DeviceExtension);
//
// BUGBUG: should I only wait if IoCancelIrp fails?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -