www.gusucode.com > VC写的VirtualCOM虚拟串口驱动,基于DDK,在VC环境下打开工程文 > VC写的VirtualCOM虚拟串口驱动,基于DDK,在VC环境下打开工程文件直接编译,可以扩充功能/HelloWDM.cpp
#include "HelloWDM.h" /************************************************************************ * 函数名称:DriverEntry * 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象 * 参数列表: pDriverObject:从I/O管理器中传进来的驱动对象 pRegistryPath:驱动程序在注册表的中的路径 * 返回 值:返回初始化驱动状态 *************************************************************************/ #pragma INITCODE extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath) { KdPrint(("Enter DriverEntry\n")); pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice; pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp; pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HelloWDMDispatchControlp; pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloWDMCreate; pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloWDMClose; pDriverObject->MajorFunction[IRP_MJ_READ] = HelloWDMRead; pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMWrite; pDriverObject->DriverUnload = HelloWDMUnload; KdPrint(("Leave DriverEntry\n")); return STATUS_SUCCESS; } /************************************************************************ * 函数名称:HelloWDMAddDevice * 功能描述:添加新设备 * 参数列表: DriverObject:从I/O管理器中传进来的驱动对象 PhysicalDeviceObject:从I/O管理器中传进来的物理设备对象 * 返回 值:返回添加新设备状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject) { PAGED_CODE(); KdPrint(("Enter HelloWDMAddDevice\n")); NTSTATUS status; PDEVICE_OBJECT fdo; UNICODE_STRING devName; RtlInitUnicodeString(&devName,L"\\Device\\MyWDMDevice"); status = IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), &(UNICODE_STRING)devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo); if( !NT_SUCCESS(status)) return status; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension; pdx->fdo = fdo; pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject); UNICODE_STRING symLinkName; RtlInitUnicodeString(&symLinkName,L"\\DosDevices\\COM7"); pdx->ustrDeviceName = devName; pdx->ustrSymLinkName = symLinkName; status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,&(UNICODE_STRING)devName); if( !NT_SUCCESS(status)) { IoDeleteSymbolicLink(&pdx->ustrSymLinkName); status = IoCreateSymbolicLink(&symLinkName,&devName); if( !NT_SUCCESS(status)) { return status; } } fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; fdo->Flags &= ~DO_DEVICE_INITIALIZING; KdPrint(("Leave HelloWDMAddDevice\n")); return STATUS_SUCCESS; } #pragma PAGEDCODE NTSTATUS HelloWDMCreate(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { PAGED_CODE(); KdPrint(("HelloWDMCreate()\n")); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; // Init the device extension pdx->BaudRate = 1200; pdx->RTSstate = 0; pdx->DTRstate = 0; pdx->Timeouts.ReadIntervalTimeout = 0; pdx->Timeouts.ReadTotalTimeoutMultiplier = 0; pdx->Timeouts.ReadTotalTimeoutConstant = 0; pdx->Timeouts.WriteTotalTimeoutMultiplier = 0; pdx->Timeouts.WriteTotalTimeoutConstant = 0; //pdx->Lc pdx->IsOpen = TRUE; KeInitializeSpinLock(&pdx->WriteSpinLock); KeInitializeSpinLock(&pdx->IoctlSpinLock); pdx->EventMask = 0; pdx->HistoryEvents = 0; pdx->pWaitIrp = NULL; pdx->pReadIrp = NULL; Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } /************************************************************************ * 函数名称:DefaultPnpHandler * 功能描述:对PNP IRP进行缺省处理 * 参数列表: pdx:设备对象的扩展 Irp:从IO请求包 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp) { PAGED_CODE(); KdPrint(("Enter DefaultPnpHandler\n")); IoSkipCurrentIrpStackLocation(Irp); KdPrint(("Leave DefaultPnpHandler\n")); return IoCallDriver(pdx->NextStackDevice, Irp); } /************************************************************************ * 函数名称:HandleRemoveDevice * 功能描述:对IRP_MN_REMOVE_DEVICE IRP进行处理 * 参数列表: fdo:功能设备对象 Irp:从IO请求包 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp) { PAGED_CODE(); KdPrint(("Enter HandleRemoveDevice\n")); Irp->IoStatus.Status = STATUS_SUCCESS; NTSTATUS status = DefaultPnpHandler(pdx, Irp); IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName); //调用IoDetachDevice()把fdo从设备栈中脱开: if (pdx->NextStackDevice) IoDetachDevice(pdx->NextStackDevice); //删除fdo: IoDeleteDevice(pdx->fdo); KdPrint(("Leave HandleRemoveDevice\n")); return status; } /************************************************************************ * 函数名称:HelloWDMPnp * 功能描述:对即插即用IRP进行处理 * 参数列表: fdo:功能设备对象 Irp:从IO请求包 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { PAGED_CODE(); KdPrint(("Enter HelloWDMPnp\n")); NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) = { DefaultPnpHandler, // IRP_MN_START_DEVICE DefaultPnpHandler, // IRP_MN_QUERY_REMOVE_DEVICE HandleRemoveDevice, // IRP_MN_REMOVE_DEVICE DefaultPnpHandler, // IRP_MN_CANCEL_REMOVE_DEVICE DefaultPnpHandler, // IRP_MN_STOP_DEVICE DefaultPnpHandler, // IRP_MN_QUERY_STOP_DEVICE DefaultPnpHandler, // IRP_MN_CANCEL_STOP_DEVICE DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_RELATIONS DefaultPnpHandler, // IRP_MN_QUERY_INTERFACE DefaultPnpHandler, // IRP_MN_QUERY_CAPABILITIES DefaultPnpHandler, // IRP_MN_QUERY_RESOURCES DefaultPnpHandler, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_TEXT DefaultPnpHandler, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS DefaultPnpHandler, // DefaultPnpHandler, // IRP_MN_READ_CONFIG DefaultPnpHandler, // IRP_MN_WRITE_CONFIG DefaultPnpHandler, // IRP_MN_EJECT DefaultPnpHandler, // IRP_MN_SET_LOCK DefaultPnpHandler, // IRP_MN_QUERY_ID DefaultPnpHandler, // IRP_MN_QUERY_PNP_DEVICE_STATE DefaultPnpHandler, // IRP_MN_QUERY_BUS_INFORMATION DefaultPnpHandler, // IRP_MN_DEVICE_USAGE_NOTIFICATION DefaultPnpHandler, // IRP_MN_SURPRISE_REMOVAL }; ULONG fcn = stack->MinorFunction; if (fcn >= arraysize(fcntab)) { // 未知的子功能代码 status = DefaultPnpHandler(pdx, Irp); // some function we don't know about return status; } #if DBG static char* fcnname[] = { "IRP_MN_START_DEVICE", "IRP_MN_QUERY_REMOVE_DEVICE", "IRP_MN_REMOVE_DEVICE", "IRP_MN_CANCEL_REMOVE_DEVICE", "IRP_MN_STOP_DEVICE", "IRP_MN_QUERY_STOP_DEVICE", "IRP_MN_CANCEL_STOP_DEVICE", "IRP_MN_QUERY_DEVICE_RELATIONS", "IRP_MN_QUERY_INTERFACE", "IRP_MN_QUERY_CAPABILITIES", "IRP_MN_QUERY_RESOURCES", "IRP_MN_QUERY_RESOURCE_REQUIREMENTS", "IRP_MN_QUERY_DEVICE_TEXT", "IRP_MN_FILTER_RESOURCE_REQUIREMENTS", "", "IRP_MN_READ_CONFIG", "IRP_MN_WRITE_CONFIG", "IRP_MN_EJECT", "IRP_MN_SET_LOCK", "IRP_MN_QUERY_ID", "IRP_MN_QUERY_PNP_DEVICE_STATE", "IRP_MN_QUERY_BUS_INFORMATION", "IRP_MN_DEVICE_USAGE_NOTIFICATION", "IRP_MN_SURPRISE_REMOVAL", }; KdPrint(("PNP Request (%s)\n", fcnname[fcn])); #endif // DBG status = (*fcntab[fcn])(pdx, Irp); KdPrint(("Leave HelloWDMPnp\n")); return status; } /************************************************************************ * 函数名称:HelloWDMUnload * 功能描述:负责驱动程序的卸载操作 * 参数列表: DriverObject:驱动对象 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject) { PAGED_CODE(); KdPrint(("Enter HelloWDMUnload\n")); KdPrint(("Leave HelloWDMUnload\n")); } void PrintIoControlCode(ULONG code) { switch(code) { case IOCTL_SERIAL_CLEAR_STATS: KdPrint(("IOCTL code: IOCTL_SERIAL_CLEAR_STATS\n")); break; case IOCTL_SERIAL_CLR_DTR: KdPrint(("IOCTL code: IOCTL_SERIAL_CLR_DTR\n")); break; case IOCTL_SERIAL_CLR_RTS: KdPrint(("IOCTL code: IOCTL_SERIAL_CLR_RTS\n")); break; case IOCTL_SERIAL_CONFIG_SIZE: KdPrint(("IOCTL code: IOCTL_SERIAL_CONFIG_SIZE\n")); break; case IOCTL_SERIAL_GET_BAUD_RATE: KdPrint(("IOCTL code: IOCTL_SERIAL_GET_BAUD_RATE\n")); break; case IOCTL_SERIAL_GET_CHARS: KdPrint(("IOCTL code: IOCTL_SERIAL_GET_CHARS\n")); break; case IOCTL_SERIAL_GET_COMMSTATUS: KdPrint(("IOCTL code: IOCTL_SERIAL_GET_COMMSTATUS\n")); break; case IOCTL_SERIAL_GET_DTRRTS: KdPrint(("IOCTL code: IOCTL_SERIAL_GET_DTRRTS\n")); break; case IOCTL_SERIAL_GET_HANDFLOW: KdPrint(("IOCTL code: IOCTL_SERIAL_GET_HANDFLOW\n")); break; case IOCTL_SERIAL_GET_LINE_CONTROL: KdPrint(("IOCTL code: IOCTL_SERIAL_GET_LINE_CONTROL\n")); break; case IOCTL_SERIAL_GET_MODEM_CONTROL: KdPrint(("IOCTL code: IOCTL_SERIAL_GET_MODEM_CONTROL\n")); break; case IOCTL_SERIAL_GET_MODEMSTATUS: KdPrint(("IOCTL code: IOCTL_SERIAL_GET_MODEMSTATUS\n")); break; case IOCTL_SERIAL_GET_PROPERTIES: KdPrint(("IOCTL code: IOCTL_SERIAL_GET_PROPERTIES\n")); break; case IOCTL_SERIAL_GET_STATS: KdPrint(("IOCTL code: IOCTL_SERIAL_GET_STATS\n")); break; case IOCTL_SERIAL_GET_TIMEOUTS: KdPrint(("IOCTL code: IOCTL_SERIAL_GET_TIMEOUTS\n")); break; case IOCTL_SERIAL_GET_WAIT_MASK: KdPrint(("IOCTL code: IOCTL_SERIAL_GET_WAIT_MASK\n")); break; case IOCTL_SERIAL_IMMEDIATE_CHAR: KdPrint(("IOCTL code: IOCTL_SERIAL_IMMEDIATE_CHAR\n")); break; case IOCTL_SERIAL_LSRMST_INSERT: KdPrint(("IOCTL code: IOCTL_SERIAL_LSRMST_INSERT\n")); break; case IOCTL_SERIAL_PURGE: KdPrint(("IOCTL code: IOCTL_SERIAL_PURGE\n")); break; case IOCTL_SERIAL_RESET_DEVICE: KdPrint(("IOCTL code: IOCTL_SERIAL_RESET_DEVICE\n")); break; case IOCTL_SERIAL_SET_BAUD_RATE: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_BAUD_RATE\n")); break; case IOCTL_SERIAL_SET_BREAK_OFF: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_BREAK_OFF\n")); break; case IOCTL_SERIAL_SET_BREAK_ON: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_BREAK_ON\n")); break; case IOCTL_SERIAL_SET_CHARS: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_CHARS\n")); break; case IOCTL_SERIAL_SET_DTR: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_DTR\n")); break; case IOCTL_SERIAL_SET_FIFO_CONTROL: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_FIFO_CONTROL\n")); break; case IOCTL_SERIAL_SET_HANDFLOW: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_HANDFLOW\n")); break; case IOCTL_SERIAL_SET_LINE_CONTROL: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_LINE_CONTROL\n")); break; case IOCTL_SERIAL_SET_MODEM_CONTROL: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_MODEM_CONTROL\n")); break; case IOCTL_SERIAL_SET_QUEUE_SIZE: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_QUEUE_SIZE\n")); break; case IOCTL_SERIAL_SET_RTS: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_RTS\n")); break; case IOCTL_SERIAL_SET_TIMEOUTS: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_TIMEOUTS\n")); break; case IOCTL_SERIAL_SET_WAIT_MASK: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_WAIT_MASK\n")); break; case IOCTL_SERIAL_SET_XOFF: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_XOFF\n")); break; case IOCTL_SERIAL_SET_XON: KdPrint(("IOCTL code: IOCTL_SERIAL_SET_XON\n")); break; case IOCTL_SERIAL_WAIT_ON_MASK: KdPrint(("IOCTL code: IOCTL_SERIAL_WAIT_ON_MASK\n")); break; case IOCTL_SERIAL_XOFF_COUNTER: KdPrint(("IOCTL code: IOCTL_SERIAL_XOFF_COUNTER\n")); break; default: KdPrint(("IOCTL code: unkown\n")); } } VOID DriverCancelWaitIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { KdPrint(("DriverCancelWaitIrp\n")); PDEVICE_EXTENSION pExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; KIRQL OldIrql; IoReleaseCancelSpinLock(Irp->CancelIrql); KeAcquireSpinLock(&pExtension->IoctlSpinLock, &OldIrql); pExtension->pWaitIrp = NULL; KeReleaseSpinLock(&pExtension->IoctlSpinLock, OldIrql); Irp->IoStatus.Status = STATUS_CANCELLED; IoCompleteRequest(Irp, IO_NO_INCREMENT); } VOID DriverCheckEvent(IN PDEVICE_EXTENSION pExtension, IN ULONG events) { KdPrint(("DriverCheckEvent\n")); PIRP pOldWaitIrp = NULL; PDRIVER_CANCEL pOldCancelRoutine; KIRQL OldIrql; KeAcquireSpinLock(&pExtension->IoctlSpinLock, &OldIrql); pExtension->HistoryEvents |= events; events &= pExtension->EventMask; //相当于设置触发事件 if ((pExtension->pWaitIrp != NULL) && (events != 0)) { pOldWaitIrp = pExtension->pWaitIrp; pOldCancelRoutine = IoSetCancelRoutine(pOldWaitIrp, NULL); //是否已经被cancel掉? if (pOldCancelRoutine != NULL) { // Nein, also Request beenden pOldWaitIrp->IoStatus.Information = sizeof(ULONG); *(PULONG)pOldWaitIrp->AssociatedIrp.SystemBuffer = events; pOldWaitIrp->IoStatus.Status = STATUS_SUCCESS; pExtension->pWaitIrp = NULL; pExtension->HistoryEvents = 0; } else { //如果cancel掉,就不用IoCompleteRequest了 pOldWaitIrp = NULL; } } KeReleaseSpinLock(&pExtension->IoctlSpinLock, OldIrql); if (pOldWaitIrp != NULL) { KdPrint(("complete the wait irp\n")); IoCompleteRequest(pOldWaitIrp, IO_NO_INCREMENT); } } #pragma PAGEDCODE NTSTATUS HelloWDMDispatchControlp(PDEVICE_OBJECT fdo, PIRP Irp) { PAGED_CODE(); NTSTATUS ntStatus = STATUS_SUCCESS;// Assume success PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp ); KIRQL OldIrql; Irp->IoStatus.Information = 0; ntStatus = STATUS_SUCCESS; PrintIoControlCode(irpSp->Parameters.DeviceIoControl.IoControlCode); switch ( irpSp->Parameters.DeviceIoControl.IoControlCode ) { case IOCTL_SERIAL_SET_BAUD_RATE: { pdx->BaudRate = ((PSERIAL_BAUD_RATE)(Irp->AssociatedIrp.SystemBuffer))->BaudRate; Irp->IoStatus.Information = 0; break; } case IOCTL_SERIAL_GET_BAUD_RATE: { PSERIAL_BAUD_RATE Br = (PSERIAL_BAUD_RATE)Irp->AssociatedIrp.SystemBuffer; Br->BaudRate = pdx->BaudRate; Irp->IoStatus.Information = sizeof(SERIAL_BAUD_RATE); break; } case IOCTL_SERIAL_SET_RTS: { pdx->RTSstate = 1; break; } case IOCTL_SERIAL_CLR_RTS: { pdx->RTSstate = 0; break; } case IOCTL_SERIAL_SET_DTR: { pdx->DTRstate = 1; break; } case IOCTL_SERIAL_CLR_DTR: { pdx->DTRstate = 0; break; } case IOCTL_SERIAL_GET_DTRRTS: { ULONG ModemControl; ModemControl = pdx->DTRstate + (pdx->RTSstate<<1); *(PULONG)Irp->AssociatedIrp.SystemBuffer = ModemControl; Irp->IoStatus.Information = sizeof(ULONG); break; } case IOCTL_SERIAL_GET_MODEMSTATUS: { ULONG Cts, Dsr, Dcd; Cts = 1; //对方传送请求 //pdx->pOther->RTSstate; Dsr = 1; //对方数据终端是否准备好 //pdx->pOther->DTRstate; Dcd = 1; //对方设备是否打开 //pdx->pOther->IsOpen; *(PULONG)Irp->AssociatedIrp.SystemBuffer = (Cts ? SERIAL_CTS_STATE : 0) | (Dsr ? SERIAL_DSR_STATE : 0) | (Dcd ? SERIAL_DCD_STATE : 0); Irp->IoStatus.Information = sizeof(ULONG); break; } case IOCTL_SERIAL_SET_TIMEOUTS: { pdx->Timeouts = *((PSERIAL_TIMEOUTS)(Irp->AssociatedIrp.SystemBuffer)); break; } case IOCTL_SERIAL_GET_TIMEOUTS: { *((PSERIAL_TIMEOUTS)Irp->AssociatedIrp.SystemBuffer) = pdx->Timeouts; Irp->IoStatus.Information = sizeof(SERIAL_TIMEOUTS); break; } case IOCTL_SERIAL_RESET_DEVICE: { break; } case IOCTL_SERIAL_PURGE: { break; } case IOCTL_SERIAL_SET_LINE_CONTROL: { pdx->Lc = *((PSERIAL_LINE_CONTROL)(Irp->AssociatedIrp.SystemBuffer)); break; } case IOCTL_SERIAL_GET_LINE_CONTROL: { *((PSERIAL_LINE_CONTROL)(Irp->AssociatedIrp.SystemBuffer)) = pdx->Lc; Irp->IoStatus.Information = sizeof(SERIAL_LINE_CONTROL); break; } case IOCTL_SERIAL_SET_WAIT_MASK: { PIRP pOldWaitIrp; PDRIVER_CANCEL pOldCancelRoutine; pdx->EventMask = *(PULONG)Irp->AssociatedIrp.SystemBuffer; KeAcquireSpinLock(&pdx->IoctlSpinLock, &OldIrql); pOldWaitIrp = pdx->pWaitIrp; if (pOldWaitIrp != NULL) { pOldCancelRoutine = IoSetCancelRoutine(pOldWaitIrp, NULL); //对以前没有进行完成例程的等待irp,进行完成 if (pOldCancelRoutine != NULL) { pOldWaitIrp->IoStatus.Information = sizeof(ULONG); *(PULONG)pOldWaitIrp->AssociatedIrp.SystemBuffer = 0; pOldWaitIrp->IoStatus.Status = STATUS_SUCCESS; pdx->pWaitIrp = NULL; } else { pOldWaitIrp = NULL; } } KeReleaseSpinLock(&pdx->IoctlSpinLock, OldIrql); if (pOldWaitIrp != NULL) { IoCompleteRequest(pOldWaitIrp, IO_NO_INCREMENT); } break; } case IOCTL_SERIAL_GET_WAIT_MASK: { *(PULONG)Irp->AssociatedIrp.SystemBuffer = pdx->EventMask; Irp->IoStatus.Information = sizeof(ULONG); break; } case IOCTL_SERIAL_WAIT_ON_MASK: { PDRIVER_CANCEL pOldCancelRoutine; KeAcquireSpinLock(&pdx->IoctlSpinLock, &OldIrql); //等待irp一定被清除,且eventMask一定不为0 if ((pdx->pWaitIrp != NULL) || (pdx->EventMask == 0)) ntStatus = STATUS_INVALID_PARAMETER; else if ((pdx->EventMask & pdx->HistoryEvents) != 0) { // Some events happened Irp->IoStatus.Information = sizeof(ULONG); *(PULONG)Irp->AssociatedIrp.SystemBuffer = pdx->EventMask & pdx->HistoryEvents; pdx->HistoryEvents = 0; ntStatus = STATUS_SUCCESS; }else { pdx->pWaitIrp = Irp; ntStatus = STATUS_PENDING; IoSetCancelRoutine(Irp, DriverCancelWaitIrp); if (Irp->Cancel) { pOldCancelRoutine = IoSetCancelRoutine(Irp, NULL); if (pOldCancelRoutine != NULL) { ntStatus = STATUS_CANCELLED; pdx->pWaitIrp = NULL; } else { IoMarkIrpPending(Irp); } } else { IoMarkIrpPending(Irp); } } KeReleaseSpinLock(&pdx->IoctlSpinLock, OldIrql); break; } case IOCTL_SERIAL_GET_COMMSTATUS: { PSERIAL_STATUS pStatus = (PSERIAL_STATUS)Irp->AssociatedIrp.SystemBuffer; ULONG InputLen; KeAcquireSpinLock(&pdx->WriteSpinLock, &OldIrql); InputLen = pdx->uReadWrite; KeReleaseSpinLock(&pdx->WriteSpinLock, OldIrql); RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, sizeof(SERIAL_STATUS)); pStatus->AmountInInQueue = InputLen; pStatus->AmountInOutQueue = 0; Irp->IoStatus.Information = sizeof(SERIAL_STATUS); break; } case IOCTL_SERIAL_GET_CHARS: { RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, sizeof(SERIAL_CHARS)); Irp->IoStatus.Information = sizeof(SERIAL_CHARS); break; } case IOCTL_SERIAL_GET_HANDFLOW: { break; } default: { break; } } Irp->IoStatus.Status = ntStatus; if (ntStatus!=STATUS_PENDING) IoCompleteRequest( Irp, IO_NO_INCREMENT ); return ntStatus; } #pragma PAGEDCODE NTSTATUS HelloWDMClose(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { PAGED_CODE(); KdPrint(("HelloWDMClose()\n")); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; pdx->pWaitIrp = NULL; pdx->pReadIrp = NULL; pdx->IsOpen = FALSE; pdx->uReadWrite = 0; Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } VOID DriverCancelCurrentReadIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp) { PDEVICE_EXTENSION pExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; KIRQL OldIrql; IoReleaseCancelSpinLock(pIrp->CancelIrql); KeAcquireSpinLock(&pExtension->WriteSpinLock, &OldIrql); pExtension->pReadIrp = NULL; KeReleaseSpinLock(&pExtension->WriteSpinLock, OldIrql); pIrp->IoStatus.Status = STATUS_CANCELLED; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } NTSTATUS HelloWDMRead(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { KdPrint(("HelloWDMRead\n")); NTSTATUS ntStatus = STATUS_SUCCESS;// Assume success PDEVICE_EXTENSION pExtension = (PDEVICE_EXTENSION)fdo->DeviceExtension; PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp ); ULONG BufLen = irpSp->Parameters.Read.Length; PCHAR pBuf = (PCHAR)Irp->AssociatedIrp.SystemBuffer; KIRQL OldIrql; PDRIVER_CANCEL pOldCancelRoutine; Irp->IoStatus.Information = 0; DbgPrint("DeviceObject:%08X Read\n",fdo); if (BufLen == 0) { ntStatus = STATUS_SUCCESS; } else { KeAcquireSpinLock(&pExtension->WriteSpinLock, &OldIrql); RtlCopyMemory(pBuf,pExtension->Buffer,BufLen); Irp->IoStatus.Information = BufLen; if (BufLen==0 && pExtension->pReadIrp==NULL) // nothing, store { pExtension->pReadIrp = Irp; Irp->IoStatus.Status = ntStatus = STATUS_PENDING; IoSetCancelRoutine(Irp, DriverCancelCurrentReadIrp); if (Irp->Cancel) { pOldCancelRoutine = IoSetCancelRoutine(Irp, NULL); if (pOldCancelRoutine != NULL) { // Nein, also IRP hier abbrechen Irp->IoStatus.Status = ntStatus = STATUS_CANCELLED; pExtension->pReadIrp = NULL; } else { // Ja, Cancel-Routine wird Request beenden IoMarkIrpPending(Irp); } } else { IoMarkIrpPending(Irp); } } KeReleaseSpinLock(&pExtension->WriteSpinLock, OldIrql); } Irp->IoStatus.Status = ntStatus; if (ntStatus != STATUS_PENDING) IoCompleteRequest( Irp, IO_NO_INCREMENT ); return ntStatus; } NTSTATUS HelloWDMWrite(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { KdPrint(("HelloWDMWrite\n")); NTSTATUS ntStatus = STATUS_SUCCESS;// Assume success PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension; PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp ); ULONG DataLen = irpSp->Parameters.Write.Length; PUCHAR pData = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; KIRQL OldIrql; PIRP pOldReadIrp = NULL; PDRIVER_CANCEL pOldCancelRoutine; Irp->IoStatus.Information = 0; ntStatus = STATUS_SUCCESS; if (DataLen == 0) { ntStatus = STATUS_SUCCESS; }else if (DataLen>COMBUFLEN) { ntStatus = STATUS_INVALID_PARAMETER; } else { KdPrint(("Write\n")); KeAcquireSpinLock(&pdx->WriteSpinLock, &OldIrql); RtlCopyMemory(pdx->Buffer,pData,DataLen); pdx->uReadWrite = DataLen; if (pdx->pReadIrp != NULL) // drop it out { pOldReadIrp = pdx->pReadIrp; pOldCancelRoutine = IoSetCancelRoutine(pOldReadIrp, NULL); if (pOldCancelRoutine != NULL) { pOldReadIrp->IoStatus.Information = 0; pOldReadIrp->IoStatus.Status = STATUS_SUCCESS; pdx->pReadIrp = NULL; } else { pOldReadIrp = NULL; } } DriverCheckEvent(pdx, SERIAL_EV_RXCHAR | SERIAL_EV_RX80FULL); // DriverCheckEvent(pdx, SERIAL_EV_TXEMPTY); KeReleaseSpinLock(&pdx->WriteSpinLock, OldIrql); if (pOldReadIrp != NULL) IoCompleteRequest(pOldReadIrp, IO_NO_INCREMENT); } Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = DataLen; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return ntStatus; }