?? waitmask.c
字號:
/*++
Copyright (c) 2005-2006 E0 Technology,Inc.
Module Name:
waitmask.c
Abstract:
Virtual Com Port Driver for USB to RS232 Converter of E0 Technology,Inc.
Environment:
Kernel mode
Notes:
Revision History:
2006/3/1 : Adapted from the serial DDK sample.
--*/
#include "usb2com.h"
void
SerialCancelCurrentWait( PDEVICE_OBJECT DeviceObject, PIRP pIrp )
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
DbgPrint("SerialCancelCurrentWait Enter Irp = %p\n",pIrp);
ASSERT(pIrp);
irpStack = IoGetCurrentIrpStackLocation(pIrp);
deviceExtension = irpStack->DeviceObject->DeviceExtension;
deviceExtension->CurrentWaitIrp = NULL;
/*
*All Cancel routines must follow these guidelines:
* 1. Call IoReleaseCancelSpinLock to release the system's cancel spin lock
* 2. ...
*/
IoReleaseCancelSpinLock(pIrp->CancelIrql);
pIrp->IoStatus.Status = STATUS_CANCELLED;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
DbgPrint("SerialCancelCurrentWait Exit\n");
}
NTSTATUS
SerialCompleteCurrentWait(PIRP pIrp, ULONG events)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
KIRQL OldIrql;
PDRIVER_CANCEL oldCancelRoutine;
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
PIRP WaitIrp;
DbgPrint("SerialCompleteCurrentWait Irp = %p events = %x\n",pIrp,events);
irpStack = IoGetCurrentIrpStackLocation(pIrp);
deviceExtension = irpStack->DeviceObject->DeviceExtension;
IoAcquireCancelSpinLock(&OldIrql);
oldCancelRoutine = IoSetCancelRoutine(pIrp, NULL);
if (pIrp->Cancel){
// The IRP was canceled. Check whether our cancel routine was called.
if (oldCancelRoutine){
// The cancel routine was NOT called.
irpStack = IoGetCurrentIrpStackLocation(pIrp);
SerialCancelCurrentWait(irpStack->DeviceObject,pIrp);
}else {
// The cancel routine WAS called.
// As soon as we drop our spin lock it will dequeue and complete the IRP.
// So leave the IRP in the queue and otherwise don't touch it.
// Return pending since we're not completing the IRP here.
} //end else
IoReleaseCancelSpinLock(OldIrql);
return STATUS_CANCELLED;
} // endif
deviceExtension->CurrentWaitIrp = NULL;
deviceExtension->HistoryMask &= ~events;
IoReleaseCancelSpinLock(OldIrql);
pIrp->IoStatus.Information = sizeof(ULONG);
pIrp->IoStatus.Status = ntStatus;
*((ULONG *)pIrp->AssociatedIrp.SystemBuffer) = events;
IoCompleteRequest (pIrp,IO_NO_INCREMENT);
DbgPrint("SerialCompleteCurrentWait Exit\n");
return ntStatus;
}
NTSTATUS
SerialSetWaitMask(PIRP pIrp )
{
NTSTATUS ntStatus = STATUS_SUCCESS;
ULONG NewMask;
KIRQL OldIrql;
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
DbgPrint("SerialSetWaitMask Irp = %p\n",pIrp);
ASSERT(pIrp);
irpStack = IoGetCurrentIrpStackLocation(pIrp);
deviceExtension = irpStack->DeviceObject->DeviceExtension;
NewMask = *((ULONG *)pIrp->AssociatedIrp.SystemBuffer);
//
// Make sure that the mask only contains valid
// waitable events.
//
if (NewMask & ~(SERIAL_EV_RXCHAR |
SERIAL_EV_RXFLAG |
SERIAL_EV_TXEMPTY |
SERIAL_EV_CTS |
SERIAL_EV_DSR |
SERIAL_EV_RLSD |
SERIAL_EV_BREAK |
SERIAL_EV_ERR |
SERIAL_EV_RING |
SERIAL_EV_PERR |
SERIAL_EV_RX80FULL |
SERIAL_EV_EVENT1 |
SERIAL_EV_EVENT2)) {
ntStatus = STATUS_INVALID_PARAMETER;
return ntStatus;
}
/*
*If a wait-on-mask request is already pending when a set-wait-mask request is processed,
*the pending wait-on-event request is completed with a status of STATUS_SUCCESS
*and the output wait event mask is set to zero.
*/
IoAcquireCancelSpinLock(&OldIrql);
if(deviceExtension->CurrentWaitIrp)
{
IoReleaseCancelSpinLock(OldIrql);
SerialCompleteCurrentWait(deviceExtension->CurrentWaitIrp,0);
}else
IoReleaseCancelSpinLock(OldIrql);
deviceExtension->WaitMask = NewMask;
DbgPrint("SerialSetWaitMask Exit\n");
return ntStatus;
}
NTSTATUS
SerialWaitOnMask(PIRP pIrp)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
ULONG NewMask;
KIRQL OldIrql;
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
ULONG events;
DbgPrint("SerialWaitOnMask Enter Irp = %p\n",pIrp);
irpStack = IoGetCurrentIrpStackLocation(pIrp);
deviceExtension = irpStack->DeviceObject->DeviceExtension;
//
// First make sure that we have a non-zero mask.
// If the app queues a wait on a zero mask it can't
// be statisfied so it makes no sense to start it.
//
IoAcquireCancelSpinLock(&OldIrql);
if ((!deviceExtension->WaitMask) || (deviceExtension->CurrentWaitIrp))
{
IoReleaseCancelSpinLock(OldIrql);
ntStatus = STATUS_INVALID_PARAMETER;
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = ntStatus;
IoCompleteRequest (
pIrp,
IO_NO_INCREMENT
);
return ntStatus;
}else{
IoReleaseCancelSpinLock(OldIrql);
}
IoAcquireCancelSpinLock(&OldIrql);
events = deviceExtension->WaitMask & deviceExtension->HistoryMask;
if ( events )
{
IoReleaseCancelSpinLock(OldIrql);
ntStatus = SerialCompleteCurrentWait(pIrp,events);
}else
{
deviceExtension->CurrentWaitIrp = pIrp;
IoSetCancelRoutine(
pIrp,
SerialCancelCurrentWait
);
IoReleaseCancelSpinLock(OldIrql);
IoMarkIrpPending(pIrp);
ntStatus = STATUS_PENDING;
}
DbgPrint("SerialWaitOnMask Exit\n");
return ntStatus;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -