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

📄 ioctl.c

📁 modem driver for windows. Tools: winddk
💻 C
字号:
/*
 * UNIMODEM "Fakemodem" controllerless driver illustrative example
 *
 * (C) 2000 Microsoft Corporation
 * All Rights Reserved
 *
 */

#include "fakemodem.h"

NTSTATUS
FakeModemIoControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

{
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
    NTSTATUS          status=STATUS_UNSUCCESSFUL;
    KIRQL             OldIrql;
    PIO_STACK_LOCATION  IrpSp;

    Irp->IoStatus.Information = 0;

    //  make sure the device is ready for irp's

    status=CheckStateAndAddReference( DeviceObject, Irp);

    if (STATUS_SUCCESS != status) 
    {
        //  not accepting irp's. The irp has already been complted
        return status;

    }

    IrpSp=IoGetCurrentIrpStackLocation(Irp);

    switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {

        case IOCTL_SERIAL_GET_WAIT_MASK: {

            if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 
                    sizeof(ULONG)) 
            {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            *((PULONG)Irp->AssociatedIrp.SystemBuffer)=
                deviceExtension->CurrentMask;

            Irp->IoStatus.Information=sizeof(ULONG);

            break;
        }

        case IOCTL_SERIAL_SET_WAIT_MASK: {

            PIRP    CurrentWaitIrp=NULL;
            ULONG NewMask;

            if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < 
                    sizeof(ULONG)) {

                status = STATUS_BUFFER_TOO_SMALL;
                break;

            } else {

                KeAcquireSpinLock( &deviceExtension->SpinLock, &OldIrql);

                //  get rid of the current wait

                CurrentWaitIrp=deviceExtension->CurrentMaskIrp;

                deviceExtension->CurrentMaskIrp=NULL;

                Irp->IoStatus.Information=sizeof(ULONG);

                //  save the new mask

                NewMask = *((ULONG *)Irp->AssociatedIrp.SystemBuffer);

                deviceExtension->CurrentMask=NewMask;

                D_TRACE(DbgPrint("FAKEMODEM: set wait mask, %08lx\n",NewMask);)

                KeReleaseSpinLock( &deviceExtension->SpinLock, OldIrql);

                if (CurrentWaitIrp != NULL) {

                    D_TRACE(DbgPrint("FAKEMODEM: set wait mask- complete wait\n");)

                    *((PULONG)CurrentWaitIrp->AssociatedIrp.SystemBuffer)=0;

                    CurrentWaitIrp->IoStatus.Information=sizeof(ULONG);

                    RemoveReferenceAndCompleteRequest(
                        deviceExtension->DeviceObject,
                        CurrentWaitIrp, STATUS_SUCCESS);
                }

            }

            break;
        }

        case IOCTL_SERIAL_WAIT_ON_MASK: {

            PIRP    CurrentWaitIrp=NULL;

            if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 
                    sizeof(ULONG)) {

                status = STATUS_BUFFER_TOO_SMALL;
                break;

            }

            D_TRACE(DbgPrint("FAKEMODEM: wait on mask\n");)

            KeAcquireSpinLock(&deviceExtension->SpinLock, &OldIrql);

            //
            //  capture the current irp if any
            //
            CurrentWaitIrp=deviceExtension->CurrentMaskIrp;

            deviceExtension->CurrentMaskIrp=NULL;


            if (deviceExtension->CurrentMask == 0) {
                //
                // can only set if mask is not zero
                //
                status=STATUS_UNSUCCESSFUL;

            } else {

                deviceExtension->CurrentMaskIrp=Irp;

                Irp->IoStatus.Status=STATUS_PENDING;
                IoMarkIrpPending(Irp);
#if DBG
                Irp=NULL;
#endif

                status=STATUS_PENDING;
            }

            KeReleaseSpinLock(
                &deviceExtension->SpinLock,
                OldIrql
                );

            if (CurrentWaitIrp != NULL) {

                D_TRACE(DbgPrint("FAKEMODEM: wait on mask- complete wait\n");)

                *((PULONG)CurrentWaitIrp->AssociatedIrp.SystemBuffer)=0;

                CurrentWaitIrp->IoStatus.Information=sizeof(ULONG);

                RemoveReferenceAndCompleteRequest(
                    deviceExtension->DeviceObject,
                    CurrentWaitIrp, STATUS_SUCCESS);
            }


            break;
        }

        case IOCTL_SERIAL_PURGE: {

            ULONG Mask=*((PULONG)Irp->AssociatedIrp.SystemBuffer);

            if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
                sizeof(ULONG)) {

                status = STATUS_BUFFER_TOO_SMALL;
                break;

            }

            if (Mask & SERIAL_PURGE_RXABORT) {

                PIRP                Irp;


                KeAcquireSpinLock(
                    &deviceExtension->SpinLock,
                    &OldIrql
                    );

                while ( !IsListEmpty(&deviceExtension->ReadQueue)) {

                    PLIST_ENTRY         ListElement;
                    PIRP                Irp;
                    PIO_STACK_LOCATION  IrpSp;
                    KIRQL               CancelIrql;

                    ListElement=RemoveHeadList(
                        &deviceExtension->ReadQueue
                        );

                    Irp=CONTAINING_RECORD(ListElement,IRP,
                            Tail.Overlay.ListEntry);

                    IoAcquireCancelSpinLock(&CancelIrql);

                    if (Irp->Cancel) {
                        //
                        //  this one has been canceled
                        //
                        Irp->IoStatus.Information=STATUS_CANCELLED;

                        IoReleaseCancelSpinLock(CancelIrql);

                        continue;
                    }

                    IoSetCancelRoutine( Irp, NULL);

                    IoReleaseCancelSpinLock(CancelIrql);

                    KeReleaseSpinLock( &deviceExtension->SpinLock, OldIrql);

                    Irp->IoStatus.Information=0;

                    RemoveReferenceAndCompleteRequest(
                        deviceExtension->DeviceObject, Irp, STATUS_CANCELLED);

                    KeAcquireSpinLock( &deviceExtension->SpinLock, &OldIrql);
                }

                Irp=NULL;

                if (deviceExtension->CurrentReadIrp != NULL) 
                {
                    //
                    // get the current one
                    //
                    Irp=deviceExtension->CurrentReadIrp;

                    deviceExtension->CurrentReadIrp=NULL;

                }

                KeReleaseSpinLock( &deviceExtension->SpinLock, OldIrql);

                if (Irp != NULL) {

                    Irp->IoStatus.Information=0;

                    RemoveReferenceAndCompleteRequest(
                        deviceExtension->DeviceObject, Irp, STATUS_CANCELLED);
                }


            }


            break;
        }


        case IOCTL_SERIAL_GET_MODEMSTATUS: {


            if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
                sizeof(ULONG)) {

                status = STATUS_BUFFER_TOO_SMALL;
                break;

            }

            Irp->IoStatus.Information=sizeof(ULONG);

            *((PULONG)Irp->AssociatedIrp.SystemBuffer)=
                deviceExtension->ModemStatus;

            break;
        }

        case IOCTL_SERIAL_SET_TIMEOUTS: {

            PSERIAL_TIMEOUTS NewTimeouts =
                ((PSERIAL_TIMEOUTS)(Irp->AssociatedIrp.SystemBuffer));


            if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
                sizeof(SERIAL_TIMEOUTS)) {

                status = STATUS_BUFFER_TOO_SMALL;
                break;

            }

            RtlCopyMemory(
                &deviceExtension->CurrentTimeouts, NewTimeouts,
                sizeof(PSERIAL_TIMEOUTS));

            Irp->IoStatus.Information = sizeof(PSERIAL_TIMEOUTS);

            break;
        }

        case IOCTL_SERIAL_GET_TIMEOUTS: {

            if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
                sizeof(SERIAL_TIMEOUTS)) {

                status = STATUS_BUFFER_TOO_SMALL;
                break;

            }

            RtlCopyMemory(
                Irp->AssociatedIrp.SystemBuffer,
                &deviceExtension->CurrentTimeouts, sizeof(PSERIAL_TIMEOUTS));

            Irp->IoStatus.Information = sizeof(PSERIAL_TIMEOUTS);


            break;
        }

        case IOCTL_SERIAL_GET_COMMSTATUS: {

            PSERIAL_STATUS SerialStatus=(PSERIAL_STATUS)Irp->AssociatedIrp.SystemBuffer;

            if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
                sizeof(SERIAL_STATUS)) {

                status = STATUS_BUFFER_TOO_SMALL;
                break;

            }

            RtlZeroMemory( SerialStatus, sizeof(SERIAL_STATUS));

            KeAcquireSpinLock( &deviceExtension->SpinLock, &OldIrql);

            SerialStatus->AmountInInQueue=deviceExtension->BytesInReadBuffer;

            KeReleaseSpinLock( &deviceExtension->SpinLock, OldIrql);


            Irp->IoStatus.Information = sizeof(SERIAL_STATUS);

            break;
        }

        case IOCTL_SERIAL_SET_DTR:
        case IOCTL_SERIAL_CLR_DTR: {


            KeAcquireSpinLock( &deviceExtension->SpinLock, &OldIrql);

            if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_SET_DTR) {
                //
                //  raising DTR
                //
                deviceExtension->ModemStatus=SERIAL_DTR_STATE | SERIAL_DSR_STATE;

                D_TRACE(DbgPrint("FAKEMODEM: Set DTR\n");)

            } else {
                //
                //  dropping DTR, drop connection if there is one
                //
                D_TRACE(DbgPrint("FAKEMODEM: Clear DTR\n");)

                if (deviceExtension->CurrentlyConnected == TRUE) {
                    //
                    //  not connected any more
                    //
                    deviceExtension->CurrentlyConnected=FALSE;

                    deviceExtension->ConnectionStateChanged=TRUE;
                }
            }


            KeReleaseSpinLock( &deviceExtension->SpinLock, OldIrql);

            ProcessConnectionStateChange( DeviceObject);


            break;
        }

        default:

            status=STATUS_SUCCESS;

    }

    if (status != STATUS_PENDING) {
        //
        //  complete now if not pending
        //
        RemoveReferenceAndCompleteRequest( DeviceObject, Irp, status);
    }


    RemoveReferenceForDispatch(DeviceObject);

    return status;


}

⌨️ 快捷键说明

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