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

📄 functions.c

📁 Introduction to the Transport Device Interface-f
💻 C
📖 第 1 页 / 共 3 页
字号:
     * Each time the IRP is passed down the driver stack a new stack location is added
     * specifying certain parameters for the IRP to the driver.
     */
    pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);    
    
    pTdiExampleContext = (PTDI_EXAMPLE_CONTEXT)pIoStackIrp->FileObject->FsContext;

/*    
     To keep the example simple we will allow read requests to be queued before
     the user is connected so that we can get any initial data that is sent to us.
     
     if(pTdiExampleContext->csConnectionState == CS_CONNECTED)
    {*/
        /*
         * We can use the "Overlay.DriverContext" data on the IRP to use driver specific contexts
         * onto an IRP but only WHILE WE OWN THE IRP.  Since we will be owning this IRP
         * we can use this as the context we can find in our cancel routine.  The problem
         * is that we cannot use teh IO_STACK_LOCATION in the cancel routine since we 
         * can't be guarentteed what the current stack location is when the cancel
         * routine is called.
         *
         * We then add our IRP to the list.
         */
        Irp->Tail.Overlay.DriverContext[0] = (PVOID)pTdiExampleContext->pReadIrpListHead;
        NtStatus = HandleIrp_AddIrp(pTdiExampleContext->pReadIrpListHead, Irp, TdiExample_CancelRoutine, TdiExample_IrpCleanUp, NULL);

        if(NT_SUCCESS(NtStatus))
        {
            NtStatus = STATUS_PENDING;
        }

  /*  }
    else
    {
    
        Irp->IoStatus.Status      = NtStatus;
        Irp->IoStatus.Information = 0;
    
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
    } */

    DbgPrint("TdiExample_Read Exit 0x%0x \r\n", NtStatus);

    return NtStatus;
}


/**********************************************************************
 * 
 *  TdiExample_Close
 *
 *    This function is called to close the handle
 *
 **********************************************************************/
NTSTATUS TdiExample_Close(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    NTSTATUS NtStatus = STATUS_SUCCESS;
    DbgPrint("TdiExample_Close Called \r\n");


    Irp->IoStatus.Status      = NtStatus;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    DbgPrint("TdiExample_Close Exit 0x%0x \r\n", NtStatus);    
    
    return NtStatus;
}

/**********************************************************************
 * 
 *  TdiExample_UnSupportedFunction
 *
 *    This is called when a major function is issued that isn't supported.
 *
 **********************************************************************/
NTSTATUS TdiExample_UnSupportedFunction(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    NTSTATUS NtStatus = STATUS_NOT_SUPPORTED;
    DbgPrint("TdiExample_UnSupportedFunction Called \r\n");


    Irp->IoStatus.Status      = NtStatus;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    DbgPrint("TdiExample_UnSupportedFunction Exit 0x%0x \r\n", NtStatus);    
    
    return NtStatus;
}


/**********************************************************************
 * 
 *  TdiExample_CancelRoutine
 *
 *    This function is called if the IRP is ever canceled
 *
 *    CancelIo() from user mode, IoCancelIrp() from the Kernel
 *
 **********************************************************************/
VOID TdiExample_CancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
    PIRPLISTHEAD pIrpListHead = NULL;

    /*
     * We must release the cancel spin lock
     */

    IoReleaseCancelSpinLock(pIrp->CancelIrql);
    
    DbgPrint("TdiExample_CancelRoutine Called IRP = 0x%0x \r\n", pIrp);

    /*
     * We stored the IRPLISTHEAD context in our DriverContext on the IRP
     * before adding it to the queue so it should not be NULL here.
     */

    pIrpListHead = (PIRPLISTHEAD)pIrp->Tail.Overlay.DriverContext[0];
    pIrp->Tail.Overlay.DriverContext[0] = NULL;
    
    /*
     * We can then just throw the IRP to the PerformCancel
     * routine since it will find it in the queue, remove it and
     * then call our clean up routine.  Our clean up routine
     * will then complete the IRP.  If this does not occur then
     * our completion of the IRP will occur in another context
     * since it is not in the list.
     */
    HandleIrp_PerformCancel(pIrpListHead, pIrp);

}



/**********************************************************************
 * 
 *  TdiExample_Connect
 *
 *    This function connects to a server.
 *
 **********************************************************************/
NTSTATUS TdiExample_Connect(PTDI_EXAMPLE_CONTEXT pTdiExampleContext, PVOID pAddressContext, UINT uiLength)
{
    NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
    PNETWORK_ADDRESS pNetworkAddress = (PNETWORK_ADDRESS)pAddressContext;

    /*
     * Enter Critical Section
     *
     */
    KeWaitForMutexObject(&pTdiExampleContext->kConnectionLock, Executive, KernelMode, FALSE, NULL);

    if(uiLength >= sizeof(NETWORK_ADDRESS) && pTdiExampleContext->csConnectionState == CS_NOT_CONNECTED)
    {
        /*
         * We are not connected, we need to connect so we set an intermediate state
         * so that while the mutex is released any other threads checking the state will know
         * we are in a connecting state.
         *
         */

        pTdiExampleContext->csConnectionState = CS_CONNECTING;

        KeReleaseMutex(&pTdiExampleContext->kConnectionLock, FALSE);

        NtStatus = TdiFuncs_Connect(pTdiExampleContext->TdiHandle.pfoConnection, pNetworkAddress->ulAddress, pNetworkAddress->usPort);

        KeWaitForMutexObject(&pTdiExampleContext->kConnectionLock, Executive, KernelMode, FALSE, NULL);

        if(NT_SUCCESS(NtStatus))
        {
            pTdiExampleContext->csConnectionState = CS_CONNECTED;
        }
        else
        {
            pTdiExampleContext->csConnectionState = CS_NOT_CONNECTED;
        }
    }

    KeReleaseMutex(&pTdiExampleContext->kConnectionLock, FALSE);

    return NtStatus;
}

/**********************************************************************
 * 
 *  TdiExample_Disconnect
 *
 *    This function disconnects from a server.
 *
 **********************************************************************/
NTSTATUS TdiExample_Disconnect(PTDI_EXAMPLE_CONTEXT pTdiExampleContext)
{
    NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;

    /*
     * Enter Critical Section
     *
     */
    KeWaitForMutexObject(&pTdiExampleContext->kConnectionLock, Executive, KernelMode, FALSE, NULL);

    if(pTdiExampleContext->csConnectionState == CS_CONNECTED)
    {

        /*
         * We are connected, we need to disconnect so we set an intermediate state
         * so that while the mutex is released any other threads checking the state will know
         * we are in a disconnecting state.
         *
         */

        pTdiExampleContext->csConnectionState = CS_DISCONNECTING;

        KeReleaseMutex(&pTdiExampleContext->kConnectionLock, FALSE);
        
        NtStatus = TdiFuncs_Disconnect(pTdiExampleContext->TdiHandle.pfoConnection);
        KeWaitForMutexObject(&pTdiExampleContext->kConnectionLock, Executive, KernelMode, FALSE, NULL);

        pTdiExampleContext->csConnectionState = CS_NOT_CONNECTED;
    }

    KeReleaseMutex(&pTdiExampleContext->kConnectionLock, FALSE);



    return NtStatus;
}

/**********************************************************************
 * 
 *  TdiExample_IrpCleanUp
 *
 *    This function is called to clean up the IRP if it is ever
 *    canceled after we have given it to the queueing routines.
 *
 **********************************************************************/
VOID TdiExample_IrpCleanUp(PIRP pIrp, PVOID pContext)
{
    pIrp->IoStatus.Status      = STATUS_CANCELLED;
    pIrp->IoStatus.Information = 0;
    pIrp->Tail.Overlay.DriverContext[0] = NULL;
    DbgPrint("TdiExample_IrpCleanUp Called IRP = 0x%0x \r\n", pIrp);

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
}



/**********************************************************************
 * 
 *  TdiExample_ClientEventReceive
 *
 *    This function is called when data is recieved.
 *
 **********************************************************************/
NTSTATUS TdiExample_ClientEventReceive(PVOID TdiEventContext, CONNECTION_CONTEXT ConnectionContext, ULONG ReceiveFlags, ULONG  BytesIndicated, ULONG  BytesAvailable, ULONG  *BytesTaken, PVOID  Tsdu, PIRP  *IoRequestPacket)
{
    NTSTATUS NtStatus = STATUS_SUCCESS;
    UINT uiDataRead = 0;
    PTDI_EXAMPLE_CONTEXT pTdiExampleContext = (PTDI_EXAMPLE_CONTEXT)TdiEventContext;
    PIRP pIrp;

    DbgPrint("TdiExample_ClientEventReceive 0x%0x, %i, %i\n", ReceiveFlags, BytesIndicated, BytesAvailable);


    *BytesTaken = BytesAvailable;
    
    /*
     * This implementation is extremely simple.  We do not queue data if we do not have
     * an IRP to put it there.  We also assume we always get the full data packet
     * sent every recieve.  These are Bells and Whistles that can easily be added to
     * any implementation but would help to make the implementation more complex and
     * harder to follow the underlying idea.  Since those essentially are common-sense
     * add ons they are ignored and the general implementation of how to Queue IRP's and 
     * recieve data are implemented.
     *
     */

    pIrp = HandleIrp_RemoveNextIrp(pTdiExampleContext->pReadIrpListHead);

    if(pIrp)
    {
        PIO_STACK_LOCATION pIoStackLocation = IoGetCurrentIrpStackLocation(pIrp);

        uiDataRead = BytesAvailable > pIoStackLocation->Parameters.Read.Length ? pIoStackLocation->Parameters.Read.Length : BytesAvailable;

        pIrp->Tail.Overlay.DriverContext[0] = NULL;

        RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, Tsdu, uiDataRead);

        pIrp->IoStatus.Status      = NtStatus;
        pIrp->IoStatus.Information = uiDataRead;
        DbgPrint("TdiExample_ClientEventReceive Called IRP = 0x%0x \r\n", pIrp);

        IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
    }

    /*
     * The I/O Request can be used to recieve the rest of the data.  We are not using
     * it in this example however and will actually be assuming that we always get
     * all the data.
     *
     */
    *IoRequestPacket = NULL;

    return NtStatus;
}




⌨️ 快捷键说明

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