www.pudn.com > ComEmulDrv3.zip > ComEmulDrv.c


// 
// ComEmulDrv serial port bridge driver 
// 
// Copyright (c) 2002  
// MixW team 
// http://www.mixw.net 
// 
 
#ifndef OLDVER 
#include  
 
#else 
#include  
#endif 
 
#include  
 
 
#include "ComEmulDrv.h" 
 
 
#define SERIAL_DEVICE_MAP           L"SERIALCOMM" 
 
//#define COMNUMBER1 L"10" 
//#define COMNUMBER2 L"3" 
 
//#define DEFAULT1 L"10" 
//#define DEFAULT2 L"11" 
 
#define DEVICENAME L"\\Device\\Serial" 
#define DOSDEVICENAME L"\\DosDevices\\COM" 
#define REGNAME L"COM" 
 
/* 
VOID LogMessage(IN PVOID pObj, IN ULONG val1, IN ULONG val2, IN ULONG val3, 
                      IN ULONG val4, IN PVOID dump, IN ULONG dumplength) 
{ 
    PIO_ERROR_LOG_PACKET    pLogEntry; 
 
 
    pLogEntry = IoAllocateErrorLogEntry(pObj, (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + 
                                              4*sizeof(ULONG) + dumplength)); 
 
    if (pLogEntry != NULL ) 
    { 
        pLogEntry->ErrorCode = STATUS_SUCCESS; 
        pLogEntry->SequenceNumber = 0; 
        pLogEntry->MajorFunctionCode = 0; 
        pLogEntry->IoControlCode = 0; 
        pLogEntry->RetryCount = 0; 
        pLogEntry->FinalStatus = STATUS_SUCCESS; 
        pLogEntry->DumpDataSize = 4*sizeof(ULONG) + dumplength; 
 
        pLogEntry->DumpData[0] = val1; 
        pLogEntry->DumpData[1] = val2; 
        pLogEntry->DumpData[2] = val3; 
        pLogEntry->DumpData[3] = val4; 
 
        RtlCopyMemory(&pLogEntry->DumpData[4], dump, dumplength); 
 
        IoWriteErrorLogEntry(pLogEntry); 
    } 
} 
*/ 
 
NTSTATUS 
MixPortDriverDeviceControl( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ); 
 
NTSTATUS 
MixPortDriverWriteDispatch( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP pIrp 
    ); 
 
NTSTATUS 
MixPortDriverReadDispatch( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP pIrp 
    ); 
 
VOID DriverCancelWaitIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp); 
VOID DriverCheckEvent(IN PSERIAL_DEVICE_EXTENSION pExtension, IN ULONG events); 
 
#define UNIBUFLEN 200 
 
WCHAR Name1Buf[MAXPAIR][UNIBUFLEN],Name2Buf[MAXPAIR][UNIBUFLEN]; 
WCHAR DosName1Buf[MAXPAIR][UNIBUFLEN],DosName2Buf[MAXPAIR][UNIBUFLEN]; 
WCHAR Reg1Buf[MAXPAIR][UNIBUFLEN],Reg2Buf[MAXPAIR][UNIBUFLEN]; 
int PairPresent[MAXPAIR]; 
 
int GetStringForCom(int iPair, PWSTR pBuffer, PCWSTR pRegistryPath, PCWSTR pStrPrefix, PCWSTR pKey) 
{ 
	UNICODE_STRING sString; 
 
    NTSTATUS ntStatus; 
    UNICODE_STRING Value; 
	int iValue; 
    RTL_QUERY_REGISTRY_TABLE Table[2]; 
 
	WCHAR swKey[UNIBUFLEN]; 
	UNICODE_STRING sKey, sNr; 
 
	// Prepare output buffer 
 
	sString.MaximumLength = UNIBUFLEN; 
	sString.Length = 0; 
	sString.Buffer = pBuffer; 
 
	RtlZeroMemory(sString.Buffer, UNIBUFLEN*sizeof(WCHAR)); 
 
	RtlAppendUnicodeToString(&sString, pStrPrefix); 
 
	// Prepare key name 
 
	sKey.MaximumLength = UNIBUFLEN; 
	sKey.Length = 0; 
	sKey.Buffer = swKey; 
 
	sNr.MaximumLength = UNIBUFLEN; 
	sNr.Length = 0; 
	sNr.Buffer = swKey+4; 
 
	RtlZeroMemory(sKey.Buffer, UNIBUFLEN*sizeof(WCHAR)); 
 
	RtlAppendUnicodeToString(&sKey, L"Pair"); 
	RtlIntegerToUnicodeString(iPair+1, 10, &sNr); 
	sKey.Length += sNr.Length; 
	RtlAppendUnicodeToString(&sKey, L"-Port"); 
	RtlAppendUnicodeToString(&sKey, pKey); 
 
KdPrint(("GetStringForCom, key= %ws\n",sKey.Buffer)); 
 
	// Read from registry 
 
    RtlInitUnicodeString( &Value, NULL ); 
    RtlZeroMemory( Table, sizeof(Table) ); 
 
    Table[0].Flags        = RTL_QUERY_REGISTRY_DIRECT; 
    Table[0].Name         = sKey.Buffer/*(PWSTR)pKey*/; 
    Table[0].EntryContext = &Value; 
    Table[0].DefaultType  = REG_SZ; 
	Table[0].DefaultData = L"0"; 
 
    ntStatus = RtlQueryRegistryValues( 
                RTL_REGISTRY_ABSOLUTE, 
                pRegistryPath, 
                Table, 
                NULL, 
                NULL ); 
 
	if ( ntStatus == STATUS_SUCCESS ) 
	{ 
		RtlAppendUnicodeStringToString(&sString, &Value); 
KdPrint(("  value= %ws\n",Value.Buffer)); 
		RtlUnicodeStringToInteger(&Value, 10, &iValue); 
		return iValue; 
	} 
	else 
	{ 
		RtlAppendUnicodeToString(&sString, L"0"); 
KdPrint(("  (no) value= %ws\n",Value.Buffer)); 
		return 0; 
	} 
} 
 
VOID MixPortDriverUnload(IN PDRIVER_OBJECT DriverObject) 
{ 
	 
	UNICODE_STRING uniDOSString1; 
	UNICODE_STRING uniDOSString2; 
 
	int i/*, NumDev=0*/; 
	PDEVICE_OBJECT p, k; 
 
KdPrint(("Unload\n")); 
 
	// Delete sym link and registry 
 
KdPrint(("Delete sym and reg:")); 
 
	for (i=0; iDeviceObject->NextDevice); 
	IoDeleteDevice(DriverObject->DeviceObject); 
*/ 
 
	// Delete devices 
 
	p = DriverObject->DeviceObject; 
 
KdPrint(("Delete device: ")); 
	while (p) 
	{ 
		k = p->NextDevice; 
		IoDeleteDevice(p); 
		p = k; 
KdPrint(("*")); 
	} 
KdPrint(("\n")); 
} 
 
//ULONG OpenCnt = 0; 
 
NTSTATUS MixPortDriverCreateDispatch( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
{ 
 
	PSERIAL_DEVICE_EXTENSION pExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 
//	OpenCnt++; 
 
KdPrint(("Create\n")); 
 
	// Init the device extension 
	 
	pExtension->BaudRate = 1200; 
	pExtension->RTSstate = 0; 
	pExtension->DTRstate = 0; 
 
	pExtension->Timeouts.ReadIntervalTimeout = 0; 
	pExtension->Timeouts.ReadTotalTimeoutMultiplier = 0; 
	pExtension->Timeouts.ReadTotalTimeoutConstant = 0; 
	pExtension->Timeouts.WriteTotalTimeoutMultiplier = 0; 
	pExtension->Timeouts.WriteTotalTimeoutConstant = 0; 
	//pExtension->Lc 
 
	pExtension->BufHead = 0; 
	pExtension->BufTail = 0; 
	pExtension->pOther->BufHead = 0; 
	pExtension->pOther->BufTail = 0; 
 
	pExtension->IsOpen = TRUE; 
 
    KeInitializeSpinLock(&pExtension->WriteSpinLock); 
    KeInitializeSpinLock(&pExtension->IoctlSpinLock); 
 
	pExtension->EventMask = 0; 
	pExtension->HistoryEvents = 0; 
 
	pExtension->pWaitIrp = NULL; 
	pExtension->pReadIrp = NULL; 
 
	Irp->IoStatus.Information = 0; 
	Irp->IoStatus.Status = STATUS_SUCCESS; 
 
	IoCompleteRequest(Irp, IO_NO_INCREMENT); 
 
//LogMessage(DeviceObject,0xAA,0,0,0,0,0); 
	return STATUS_SUCCESS; 
} 
 
 
NTSTATUS MixPortDriverCloseDispatch( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
{ 
 
	PSERIAL_DEVICE_EXTENSION pExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 
//	OpenCnt--; 
 
KdPrint(("Close\n")); 
 
	pExtension->pWaitIrp = NULL; 
	pExtension->pReadIrp = NULL; 
 
	pExtension->IsOpen = FALSE; 
 
	Irp->IoStatus.Information = 0; 
	Irp->IoStatus.Status = STATUS_SUCCESS; 
 
	IoCompleteRequest(Irp, IO_NO_INCREMENT); 
 
	return STATUS_SUCCESS; 
} 
 
 
NTSTATUS DriverEntry( 
    IN PDRIVER_OBJECT DriverObject, 
    IN PUNICODE_STRING RegistryPath 
    ) 
{ 
	PDEVICE_OBJECT deviceObject1; 
	PDEVICE_OBJECT deviceObject2; 
 
	NTSTATUS status; 
 
	UNICODE_STRING uniNameString1, uniDOSString1; 
	UNICODE_STRING uniNameString2, uniDOSString2; 
 
	PSERIAL_DEVICE_EXTENSION pExtension1; 
	PSERIAL_DEVICE_EXTENSION pExtension2; 
 
	int i; 
	int cnt; 
 
KdPrint(("DriverEntry, path= %ws\n",RegistryPath->Buffer)); 
 
KdPrint(("Create devices:")); 
 
	for (i=0; iBuffer, DEVICENAME, L"1"); 
		cnt += GetStringForCom(i, Name2Buf[i], RegistryPath->Buffer, DEVICENAME, L"2"); 
 
		cnt += GetStringForCom(i, DosName1Buf[i], RegistryPath->Buffer, DOSDEVICENAME, L"1"); 
		cnt += GetStringForCom(i, DosName2Buf[i], RegistryPath->Buffer, DOSDEVICENAME, L"2"); 
 
		cnt += GetStringForCom(i, Reg1Buf[i], RegistryPath->Buffer, REGNAME, L"1"); 
		cnt += GetStringForCom(i, Reg2Buf[i], RegistryPath->Buffer, REGNAME, L"2"); 
 
		if (cnt < 4) 
		{ 
			continue; 
		} 
 
KdPrint(("Creating: %i",i)); 
 
		RtlInitUnicodeString(&uniNameString1, Name1Buf[i]); 
		RtlInitUnicodeString(&uniNameString2, Name2Buf[i]); 
 
		RtlInitUnicodeString(&uniDOSString1, DosName1Buf[i]); 
		RtlInitUnicodeString(&uniDOSString2, DosName2Buf[i]); 
 
		status = IoCreateDevice(DriverObject,  
					sizeof(SERIAL_DEVICE_EXTENSION), 
					&uniNameString1, 
					FILE_DEVICE_SERIAL_PORT, 
					FILE_DEVICE_SECURE_OPEN,  
					TRUE,  
					&deviceObject1); 
 
		if(!NT_SUCCESS(status)) 
		{ 
			MixPortDriverUnload(DriverObject); 
			return status; 
		} 
 
		status = IoCreateDevice(DriverObject,  
					sizeof(SERIAL_DEVICE_EXTENSION), 
					&uniNameString2, 
					FILE_DEVICE_SERIAL_PORT, 
					FILE_DEVICE_SECURE_OPEN,  
					TRUE,  
					&deviceObject2); 
 
		if(!NT_SUCCESS(status)) 
		{ 
			MixPortDriverUnload(DriverObject); 
			return status; 
		} 
 
		PairPresent[i] = TRUE; 
 
		deviceObject1->Flags |= DO_BUFFERED_IO; // Buffered I/O only! 
		deviceObject2->Flags |= DO_BUFFERED_IO; // Buffered I/O only! 
 
		status = IoCreateSymbolicLink (&uniDOSString1, &uniNameString1); 
 
//		if (!NT_SUCCESS(status)) 
//			return status; 
		 
		status = IoCreateSymbolicLink (&uniDOSString2, &uniNameString2); 
 
//		if (!NT_SUCCESS(status)) 
//			return status; 
 
		status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP, Name1Buf[i]/*DEVICENAME COMNUMBER1*/, REG_SZ, 
									   Reg1Buf[i]/*REGNAME COMNUMBER1*/, (wcslen(Reg1Buf[i]/*REGNAME COMNUMBER1*/) + 1) * sizeof(WCHAR)); 
 
//		if (!NT_SUCCESS(status)) 
//			return status; 
 
		status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP, Name2Buf[i]/*DEVICENAME COMNUMBER2*/, REG_SZ, 
									   Reg2Buf[i]/*REGNAME COMNUMBER2*/, (wcslen(Reg2Buf[i]/*REGNAME COMNUMBER2*/) + 1) * sizeof(WCHAR)); 
 
//		if (!NT_SUCCESS(status)) 
//			return status; 
 
		// Link 
 
		((PSERIAL_DEVICE_EXTENSION)deviceObject1->DeviceExtension)->pOther = ((PSERIAL_DEVICE_EXTENSION)deviceObject2->DeviceExtension); 
		((PSERIAL_DEVICE_EXTENSION)deviceObject2->DeviceExtension)->pOther = ((PSERIAL_DEVICE_EXTENSION)deviceObject1->DeviceExtension); 
 
		((PSERIAL_DEVICE_EXTENSION)deviceObject1->DeviceExtension)->IsOpen = FALSE; 
		((PSERIAL_DEVICE_EXTENSION)deviceObject2->DeviceExtension)->IsOpen = FALSE; 
 
	} 
 
KdPrint(("\n")); 
 
	DriverObject->MajorFunction[IRP_MJ_CREATE] = MixPortDriverCreateDispatch; 
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = MixPortDriverCloseDispatch; 
	 
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MixPortDriverDeviceControl; 
    DriverObject->MajorFunction[IRP_MJ_WRITE] = MixPortDriverWriteDispatch; 
    DriverObject->MajorFunction[IRP_MJ_READ] = MixPortDriverReadDispatch; 
	 
	DriverObject->DriverUnload = MixPortDriverUnload; 
 
	return STATUS_SUCCESS; 
} 
 
 
#define IOCTL_SERIAL_IS_OPENED   CTL_CODE(FILE_DEVICE_SERIAL_PORT,50,METHOD_BUFFERED,FILE_ANY_ACCESS) 
#define IOCTL_SERIAL_GETDATA     CTL_CODE(FILE_DEVICE_SERIAL_PORT,51,METHOD_BUFFERED,FILE_ANY_ACCESS) 
#define IOCTL_SERIAL_SETDATA     CTL_CODE(FILE_DEVICE_SERIAL_PORT,52,METHOD_BUFFERED,FILE_ANY_ACCESS) 
 
NTSTATUS 
MixPortDriverDeviceControl( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP pIrp 
    ) 
 
{ 
 
    NTSTATUS            ntStatus = STATUS_SUCCESS;// Assume success 
 
	PSERIAL_DEVICE_EXTENSION pExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 
 
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( pIrp ); 
    KIRQL                       OldIrql; 
 
	pIrp->IoStatus.Information = 0; 
	ntStatus = STATUS_SUCCESS; 
 
//LogMessage(DeviceObject,0xD0,irpSp->Parameters.DeviceIoControl.IoControlCode,0,0,0,0);			 
 
//DbgPrint("IOCTL code: %X\n",irpSp->Parameters.DeviceIoControl.IoControlCode); 
 
    switch ( irpSp->Parameters.DeviceIoControl.IoControlCode ) 
 
     { 
/* 
		case IOCTL_SERIAL_IS_OPENED: 
		{ 
            *((ULONG*)pIrp->AssociatedIrp.SystemBuffer) = (OpenCnt>1); 
 
            pIrp->IoStatus.Information = sizeof(ULONG); 
			break; 
		} 
*/ 
 
        case IOCTL_SERIAL_SET_BAUD_RATE:  
		{ 
//DbgPrint("SetBaudRate\n"); 
			pExtension->BaudRate = ((PSERIAL_BAUD_RATE)(pIrp->AssociatedIrp.SystemBuffer))->BaudRate; 
 
			pIrp->IoStatus.Information = 0; 
			break; 
		} 
 
        case IOCTL_SERIAL_GET_BAUD_RATE:  
		{ 
            PSERIAL_BAUD_RATE Br = (PSERIAL_BAUD_RATE)pIrp->AssociatedIrp.SystemBuffer; 
			Br->BaudRate = pExtension->BaudRate; 
 
            pIrp->IoStatus.Information = sizeof(SERIAL_BAUD_RATE); 
			break; 
		} 
 
        case IOCTL_SERIAL_SET_RTS: 
		{ 
//DbgPrint("SetRTS\n"); 
			pExtension->RTSstate = 1; 
			break; 
		} 
 
        case IOCTL_SERIAL_CLR_RTS:  
		{ 
//DbgPrint("ClrRTS\n"); 
			pExtension->RTSstate = 0; 
			break; 
		} 
 
        case IOCTL_SERIAL_SET_DTR: 
		{ 
//DbgPrint("SetDTR\n"); 
			pExtension->DTRstate = 1; 
			break; 
		} 
 
        case IOCTL_SERIAL_CLR_DTR:  
		{ 
//DbgPrint("ClrDTR\n"); 
			pExtension->DTRstate = 0; 
			break; 
		} 
 
        case IOCTL_SERIAL_GET_DTRRTS:  
		{ 
            ULONG ModemControl; 
            ModemControl = pExtension->DTRstate + (pExtension->RTSstate<<1); 
             
			*(PULONG)pIrp->AssociatedIrp.SystemBuffer = ModemControl; 
            pIrp->IoStatus.Information = sizeof(ULONG); 
			 
			break; 
		} 
 
        case IOCTL_SERIAL_GET_MODEMSTATUS: 
		{ 
			ULONG Cts, Dsr, Dcd; 
 
			Cts = pExtension->pOther->RTSstate; 
			Dsr = pExtension->pOther->DTRstate; 
			//Dcd = OpenCnt==2; 
			Dcd = pExtension->pOther->IsOpen; 
 
			*(PULONG)pIrp->AssociatedIrp.SystemBuffer =  
				(Cts ? SERIAL_CTS_STATE : 0) | (Dsr ? SERIAL_DSR_STATE : 0) /*|  
				(Dcd ? SERIAL_DCD_STATE : 0)*/; 
            pIrp->IoStatus.Information = sizeof(ULONG); 
 
			break; 
		} 
 
        case IOCTL_SERIAL_SET_TIMEOUTS:  
		{ 
//DbgPrint("SetTimeouts\n"); 
			pExtension->Timeouts = *((PSERIAL_TIMEOUTS)(pIrp->AssociatedIrp.SystemBuffer)); 
			break; 
		} 
 
        case IOCTL_SERIAL_GET_TIMEOUTS:  
		{ 
            *((PSERIAL_TIMEOUTS)pIrp->AssociatedIrp.SystemBuffer) = pExtension->Timeouts; 
            pIrp->IoStatus.Information = sizeof(SERIAL_TIMEOUTS); 
			break; 
		} 
 
        case IOCTL_SERIAL_RESET_DEVICE:  
		{ 
//DbgPrint("ResetDevice\n"); 
			break; 
		} 
 
        case IOCTL_SERIAL_PURGE: 
        { 
			// ??? 
			break; 
		} 
 
        case IOCTL_SERIAL_SET_LINE_CONTROL:  
		{ 
			pExtension->Lc = *((PSERIAL_LINE_CONTROL)(pIrp->AssociatedIrp.SystemBuffer)); 
			break; 
		} 
 
        case IOCTL_SERIAL_GET_LINE_CONTROL:  
		{ 
			*((PSERIAL_LINE_CONTROL)(pIrp->AssociatedIrp.SystemBuffer)) = pExtension->Lc; 
 
            pIrp->IoStatus.Information = sizeof(SERIAL_LINE_CONTROL); 
			break; 
		} 
 
        case IOCTL_SERIAL_SET_WAIT_MASK: 
        { 
            PIRP            pOldWaitIrp; 
            PDRIVER_CANCEL  pOldCancelRoutine; 
 
			pExtension->EventMask = *(PULONG)pIrp->AssociatedIrp.SystemBuffer; 
 
//LogMessage(DeviceObject,0xD1,0,0,0,0,0);			 
            KeAcquireSpinLock(&pExtension->IoctlSpinLock, &OldIrql); 
 
            // ggf. anhôngigen Wait-Request beenden 
            pOldWaitIrp = pExtension->pWaitIrp; 
            if (pOldWaitIrp != NULL) 
            { 
                pOldCancelRoutine = IoSetCancelRoutine(pOldWaitIrp, NULL); 
 
                // wurde Cancel-Routine schon aufgerufen? 
                if (pOldCancelRoutine != NULL) 
                { 
                    // Nein, also Request beenden 
                    pOldWaitIrp->IoStatus.Information = sizeof(ULONG); 
                    *(PULONG)pOldWaitIrp->AssociatedIrp.SystemBuffer = 0; 
 
                    pOldWaitIrp->IoStatus.Status = STATUS_SUCCESS; 
 
                    pExtension->pWaitIrp = NULL; 
                } 
                else 
                { 
                    // Ja, Cancel-Routine wird Request beenden 
                    pOldWaitIrp = NULL; 
                } 
            } 
 
 
            KeReleaseSpinLock(&pExtension->IoctlSpinLock, OldIrql); 
 
            if (pOldWaitIrp != NULL) 
                IoCompleteRequest(pOldWaitIrp, IO_NO_INCREMENT); 
 
			break; 
		} 
 
        case IOCTL_SERIAL_GET_WAIT_MASK: 
		{ 
			 
            *(PULONG)pIrp->AssociatedIrp.SystemBuffer = pExtension->EventMask; 
 
            pIrp->IoStatus.Information = sizeof(ULONG); 
			break; 
		} 
 
        case IOCTL_SERIAL_WAIT_ON_MASK: 
        { 
            PDRIVER_CANCEL  pOldCancelRoutine; 
 
//LogMessage(DeviceObject,0xD2,0,0,0,0,0);			 
            KeAcquireSpinLock(&pExtension->IoctlSpinLock, &OldIrql); 
 
            if ((pExtension->pWaitIrp != NULL) || (pExtension->EventMask == 0)) 
                ntStatus = STATUS_INVALID_PARAMETER; 
            else  
			if ((pExtension->EventMask & pExtension->HistoryEvents) != 0) 
            { 
                // Some events happened 
                pIrp->IoStatus.Information = sizeof(ULONG); 
                *(PULONG)pIrp->AssociatedIrp.SystemBuffer = pExtension->EventMask & pExtension->HistoryEvents; 
                pExtension->HistoryEvents = 0; 
                ntStatus = STATUS_SUCCESS; 
            } 
            else 
            { 
//LogMessage(DeviceObject,0x55,0,0,0,0,0); 
                pExtension->pWaitIrp = pIrp; 
 
                ntStatus = STATUS_PENDING; 
 
                IoSetCancelRoutine(pIrp, DriverCancelWaitIrp); 
 
                // soll IRP abgebrochen werden? 
                if (pIrp->Cancel) 
                { 
                    pOldCancelRoutine = IoSetCancelRoutine(pIrp, NULL); 
 
                    // wurde Cancel-Routine schon aufgerufen? 
                    if (pOldCancelRoutine != NULL) 
                    { 
                        // Nein, also IRP hier abbrechen 
                        ntStatus = STATUS_CANCELLED; 
 
                        pExtension->pWaitIrp = NULL; 
                    } 
                    else 
                    { 
                        // Ja, Cancel-Routine wird Request beenden 
                        IoMarkIrpPending(pIrp); 
                    } 
                } 
                else 
                    IoMarkIrpPending(pIrp); 
            } 
 
            KeReleaseSpinLock(&pExtension->IoctlSpinLock, OldIrql); 
			break; 
		} 
 
        case IOCTL_SERIAL_GET_COMMSTATUS: 
		{ 
            PSERIAL_STATUS  pStatus = (PSERIAL_STATUS)pIrp->AssociatedIrp.SystemBuffer; 
 
			ULONG InputLen; 
 
//LogMessage(DeviceObject,0xD3,0,0,0,0,0);			 
            KeAcquireSpinLock(&pExtension->pOther->WriteSpinLock, &OldIrql); 
 
			InputLen = pExtension->pOther->BufHead - pExtension->pOther->BufTail; 
			if (pExtension->pOther->BufHead < pExtension->pOther->BufTail) 
				InputLen += COMBUFLEN; 
 
            KeReleaseSpinLock(&pExtension->pOther->WriteSpinLock, OldIrql); 
 
            RtlZeroMemory(pIrp->AssociatedIrp.SystemBuffer, sizeof(SERIAL_STATUS)); 
            pStatus->AmountInInQueue  = InputLen; 
            pStatus->AmountInOutQueue = 0; 
 
            pIrp->IoStatus.Information = sizeof(SERIAL_STATUS); 
			break; 
		} 
 
        case IOCTL_SERIAL_GET_CHARS: 
		{ 
            RtlZeroMemory(pIrp->AssociatedIrp.SystemBuffer, sizeof(SERIAL_CHARS)); 
            pIrp->IoStatus.Information = sizeof(SERIAL_CHARS); 
			break; 
		} 
 
        case IOCTL_SERIAL_GET_HANDFLOW: 
		{ 
			// ? 
			break; 
		} 
 
		default: 
		{ 
//			LogMessage(DeviceObject,0xE1,irpSp->Parameters.DeviceIoControl.IoControlCode,0,0,0,0); 
			break; 
		} 
/* 
		case IOCTL_SERIAL_GETDATA: 
		{ 
			ULONG BufLen = *((ULONG*)pIrp->AssociatedIrp.SystemBuffer); 
			ULONG i = 0; 
//LogMessage(DeviceObject,0x44,BufLen,0,0,0,0); 
 
			while (iBufHead!=pExtension->BufTail) 
			{ 
				((CHAR*)pIrp->AssociatedIrp.SystemBuffer)[i] =  
					pExtension->Buffer[pExtension->BufTail]; 
				i++; 
				pExtension->BufTail++; 
				pExtension->BufTail %= COMBUFLEN; 
			} 
 
            pIrp->IoStatus.Information = i;			 
		} 
*/ 
		  
	} 
 
    pIrp->IoStatus.Status = ntStatus; 
 
	if (ntStatus!=STATUS_PENDING) 
		IoCompleteRequest( pIrp, IO_NO_INCREMENT ); 
 
    return ntStatus; 
} 
 
 
NTSTATUS 
MixPortDriverWriteDispatch( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP pIrp 
    ) 
 
{ 
 
    NTSTATUS ntStatus = STATUS_SUCCESS;// Assume success 
 
	PSERIAL_DEVICE_EXTENSION pExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 
 
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( pIrp ); 
 
	ULONG DataLen = irpSp->Parameters.Write.Length; 
	PCHAR pData = pIrp->AssociatedIrp.SystemBuffer; 
 
	ULONG i; 
    KIRQL OldIrql; 
 
    PIRP            pOldReadIrp = NULL; 
    PDRIVER_CANCEL  pOldCancelRoutine; 
 
	pIrp->IoStatus.Information = 0; 
	ntStatus = STATUS_SUCCESS; 
 
//LogMessage(DeviceObject,0xC2,0,0,0,0,0); 
 
	if (DataLen == 0) 
    { 
		ntStatus = STATUS_SUCCESS; 
    } 
	else 
	{ 
 
//DbgPrint("Write\n"); 
         
		KeAcquireSpinLock(&pExtension->WriteSpinLock, &OldIrql); 
 
		//LogMessage(DeviceObject,0x33,DataLen,0,0,pData,DataLen); 
 
		for (i=0; iBuffer[pExtension->BufHead] = pData[i]; 
			pExtension->BufHead++; 
			pExtension->BufHead %= COMBUFLEN; 
		} 
 
		if (pExtension->pOther->pReadIrp != NULL) // drop it out 
		{ 
 
			pOldReadIrp = pExtension->pOther->pReadIrp; 
 
			pOldCancelRoutine = IoSetCancelRoutine(pOldReadIrp, NULL); 
 
			// wurde Cancel-Routine schon aufgerufen? 
			if (pOldCancelRoutine != NULL) 
			{ 
				// Nein, also Request beenden 
				pOldReadIrp->IoStatus.Information = 0; 
 
				pOldReadIrp->IoStatus.Status = STATUS_SUCCESS; 
 
				pExtension->pOther->pReadIrp      = NULL; 
			} 
			else 
			{ 
				// Ja, Cancel-Routine wird Request beenden 
				pOldReadIrp = NULL; 
			} 
 
		} 
 
		DriverCheckEvent(pExtension->pOther, SERIAL_EV_RXCHAR | SERIAL_EV_RX80FULL); 
 
		DriverCheckEvent(pExtension, SERIAL_EV_TXEMPTY); 
 
        KeReleaseSpinLock(&pExtension->WriteSpinLock, OldIrql); 
 
	    if (pOldReadIrp != NULL) 
		    IoCompleteRequest(pOldReadIrp, IO_NO_INCREMENT); 
	} 
 
    pIrp->IoStatus.Status = ntStatus; 
    pIrp->IoStatus.Information = DataLen; 
    IoCompleteRequest( pIrp, IO_NO_INCREMENT ); 
 
    return ntStatus; 
} 
 
VOID DriverCancelCurrentReadIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp) 
{ 
	PSERIAL_DEVICE_EXTENSION pExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 
    KIRQL                   OldIrql; 
 
 
    IoReleaseCancelSpinLock(pIrp->CancelIrql); 
 
    KeAcquireSpinLock(&pExtension->pOther->WriteSpinLock, &OldIrql); 
 
    pExtension->pReadIrp = NULL;         
 
    KeReleaseSpinLock(&pExtension->pOther->WriteSpinLock, OldIrql); 
 
    pIrp->IoStatus.Status = STATUS_CANCELLED; 
    IoCompleteRequest(pIrp, IO_NO_INCREMENT); 
} 
 
 
NTSTATUS 
MixPortDriverReadDispatch( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP pIrp 
    ) 
 
{ 
 
    NTSTATUS ntStatus = STATUS_SUCCESS;// Assume success 
 
	PSERIAL_DEVICE_EXTENSION pExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 
 
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( pIrp ); 
 
	ULONG BufLen = irpSp->Parameters.Read.Length; 
	PCHAR pBuf = pIrp->AssociatedIrp.SystemBuffer; 
 
	ULONG i = 0; 
    KIRQL OldIrql; 
 
    PDRIVER_CANCEL              pOldCancelRoutine; 
 
	pIrp->IoStatus.Information = 0; 
 
//LogMessage(DeviceObject,0xC0,0,0,0,0,0); 
 
	if (BufLen == 0) 
    { 
		ntStatus = STATUS_SUCCESS; 
    } 
	else 
	{ 
//DbgPrint("Read\n"); 
 
        KeAcquireSpinLock(&pExtension->pOther->WriteSpinLock, &OldIrql); 
 
		//LogMessage(DeviceObject,0x33,DataLen,0,0,pData,DataLen); 
 
		while ( ipOther->BufHead != pExtension->pOther->BufTail) ) 
		{ 
			pBuf[i] = pExtension->pOther->Buffer[pExtension->pOther->BufTail]; 
			i++; 
			pExtension->pOther->BufTail++; 
			pExtension->pOther->BufTail %= COMBUFLEN; 
		} 
 
		pIrp->IoStatus.Information = i; 
 
		if (i==0 && pExtension->pReadIrp==NULL) // nothing, store 
		{ 
//LogMessage(DeviceObject,0xC1,0,0,0,0,0); 
			pExtension->pReadIrp = pIrp; 
			pIrp->IoStatus.Status = ntStatus = STATUS_PENDING; 
 
            IoSetCancelRoutine(pIrp, DriverCancelCurrentReadIrp); 
 
            if (pIrp->Cancel) 
            { 
                pOldCancelRoutine = IoSetCancelRoutine(pIrp, NULL); 
 
                if (pOldCancelRoutine != NULL) 
                { 
                    // Nein, also IRP hier abbrechen 
                    pIrp->IoStatus.Status = ntStatus = STATUS_CANCELLED; 
 
                    pExtension->pReadIrp = NULL; 
                } 
                else 
                { 
                    // Ja, Cancel-Routine wird Request beenden 
                    IoMarkIrpPending(pIrp); 
                } 
			} 
			else 
			{ 
                    IoMarkIrpPending(pIrp); 
			} 
		} 
 
        KeReleaseSpinLock(&pExtension->pOther->WriteSpinLock, OldIrql); 
	 
//if (i) 
//LogMessage(DeviceObject,0x77,i,0,0,0,0); 
	} 
 
    pIrp->IoStatus.Status = ntStatus; 
	if (ntStatus != STATUS_PENDING) 
		IoCompleteRequest( pIrp, IO_NO_INCREMENT ); 
 
//LogMessage(DeviceObject,0xBB,0,0,0,0,0); 
    return ntStatus; 
} 
 
VOID DriverCancelWaitIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp) 
{ 
	PSERIAL_DEVICE_EXTENSION pExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 
    KIRQL                   OldIrql; 
 
//LogMessage(DeviceObject,0x66,0,0,0,0,0); 
     
    IoReleaseCancelSpinLock(pIrp->CancelIrql); 
 
    KeAcquireSpinLock(&pExtension->IoctlSpinLock, &OldIrql); 
 
    pExtension->pWaitIrp = NULL;         
 
    KeReleaseSpinLock(&pExtension->IoctlSpinLock, OldIrql); 
 
    pIrp->IoStatus.Status = STATUS_CANCELLED; 
    IoCompleteRequest(pIrp, IO_NO_INCREMENT); 
} 
 
VOID DriverCheckEvent(IN PSERIAL_DEVICE_EXTENSION pExtension, IN ULONG events) 
{ 
    PIRP            pOldWaitIrp = NULL; 
    PDRIVER_CANCEL  pOldCancelRoutine; 
    KIRQL           OldIrql; 
 
 
//    LOCKED_PAGED_CODE(); 
 
    KeAcquireSpinLock(&pExtension->IoctlSpinLock, &OldIrql); 
 
    pExtension->HistoryEvents |= events; 
 
    events &= pExtension->EventMask; 
 
    if ((pExtension->pWaitIrp != NULL) && (events != 0)) 
    { 
        pOldWaitIrp = pExtension->pWaitIrp; 
 
        pOldCancelRoutine = IoSetCancelRoutine(pOldWaitIrp, NULL); 
 
        // wurde Cancel-Routine schon aufgerufen? 
        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 
        { 
            // Ja, Cancel-Routine wird Request beenden 
            pOldWaitIrp = NULL; 
        } 
    } 
 
    KeReleaseSpinLock(&pExtension->IoctlSpinLock, OldIrql); 
 
    if (pOldWaitIrp != NULL) 
        IoCompleteRequest(pOldWaitIrp, IO_NO_INCREMENT); 
}