⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comemuldrv.c

📁 虚拟串口程序源代码 使用Vc开发的
💻 C
📖 第 1 页 / 共 2 页
字号:
			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鬾gigen 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 (i<BufLen && pExtension->BufHead!=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; i<DataLen; i++)
		{
			pExtension->Buffer[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 ( i<BufLen && 
			(pExtension->pOther->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);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -