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

📄 ndisbind.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
    }

    NPROT_RELEASE_LOCK(&Globals.GlobalLock);

    return (pOpenContext);
}


NDIS_STATUS
ndisprotQueryOidValue(
    IN  PNDISPROT_OPEN_CONTEXT       pOpenContext,
    OUT PVOID                       pDataBuffer,
    IN  ULONG                       BufferLength,
    OUT PULONG                      pBytesWritten
    )
/*++

Routine Description:

    Query an arbitrary OID value from the miniport.

Arguments:

    pOpenContext - pointer to open context representing our binding to the miniport
    pDataBuffer - place to store the returned value
    BufferLength - length of the above
    pBytesWritten - place to return length returned

Return Value:

    NDIS_STATUS_SUCCESS if we successfully queried the OID.
    NDIS_STATUS_XXX error code otherwise.

--*/
{
    NDIS_STATUS             Status;
    PNDISPROT_QUERY_OID      pQuery;
    NDIS_OID                Oid;

    Oid = 0;

    do
    {
        if (BufferLength < sizeof(NDISPROT_QUERY_OID))
        {
            Status = NDIS_STATUS_BUFFER_TOO_SHORT;
            break;
        }

        pQuery = (PNDISPROT_QUERY_OID)pDataBuffer;
        Oid = pQuery->Oid;

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);

        if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE))
        {
            DEBUGP(DL_WARN,
                ("QueryOid: Open %p/%x is in invalid state\n",
                    pOpenContext, pOpenContext->Flags));

            NPROT_RELEASE_LOCK(&pOpenContext->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }

        //
        //  Make sure the binding doesn't go away.
        //
        NdisInterlockedIncrement((PLONG)&pOpenContext->PendedSendCount);

        NPROT_RELEASE_LOCK(&pOpenContext->Lock);

        Status = ndisprotDoRequest(
                    pOpenContext,
                    NdisRequestQueryInformation,
                    Oid,
                    &pQuery->Data[0],
                    BufferLength - FIELD_OFFSET(NDISPROT_QUERY_OID, Data),
                    pBytesWritten);

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);

        NdisInterlockedDecrement((PLONG)&pOpenContext->PendedSendCount);

        NPROT_RELEASE_LOCK(&pOpenContext->Lock);

        if (Status == NDIS_STATUS_SUCCESS)
        {
            *pBytesWritten += FIELD_OFFSET(NDISPROT_QUERY_OID, Data);
        }

    }
    while (FALSE);

    DEBUGP(DL_LOUD, ("QueryOid: Open %p/%x, OID %x, Status %x\n",
                pOpenContext, pOpenContext->Flags, Oid, Status));

    return (Status);
    
}

NDIS_STATUS
ndisprotSetOidValue(
    IN  PNDISPROT_OPEN_CONTEXT       pOpenContext,
    OUT PVOID                       pDataBuffer,
    IN  ULONG                       BufferLength
    )
/*++

Routine Description:

    Set an arbitrary OID value to the miniport.

Arguments:

    pOpenContext - pointer to open context representing our binding to the miniport
    pDataBuffer - buffer that contains the value to be set
    BufferLength - length of the above

Return Value:

    NDIS_STATUS_SUCCESS if we successfully set the OID
    NDIS_STATUS_XXX error code otherwise.

--*/
{
    NDIS_STATUS             Status;
    PNDISPROT_SET_OID        pSet;
    NDIS_OID                Oid;
    ULONG                   BytesWritten;

    Oid = 0;

    do
    {
        if (BufferLength < sizeof(NDISPROT_SET_OID))
        {
            Status = NDIS_STATUS_BUFFER_TOO_SHORT;
            break;
        }

        pSet = (PNDISPROT_SET_OID)pDataBuffer;
        Oid = pSet->Oid;

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);

        if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE))
        {
            DEBUGP(DL_WARN,
                ("SetOid: Open %p/%x is in invalid state\n",
                    pOpenContext, pOpenContext->Flags));

            NPROT_RELEASE_LOCK(&pOpenContext->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }

        //
        //  Make sure the binding doesn't go away.
        //
        NdisInterlockedIncrement((PLONG)&pOpenContext->PendedSendCount);

        NPROT_RELEASE_LOCK(&pOpenContext->Lock);

        Status = ndisprotDoRequest(
                    pOpenContext,
                    NdisRequestSetInformation,
                    Oid,
                    &pSet->Data[0],
                    BufferLength - FIELD_OFFSET(NDISPROT_SET_OID, Data),
                    &BytesWritten);

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);

        NdisInterlockedDecrement((PLONG)&pOpenContext->PendedSendCount);

        NPROT_RELEASE_LOCK(&pOpenContext->Lock);

    }
    while (FALSE);

    DEBUGP(DL_LOUD, ("SetOid: Open %p/%x, OID %x, Status %x\n",
                pOpenContext, pOpenContext->Flags, Oid, Status));

    return (Status);
}

NTSTATUS
ndisprotQueueStatusIndicationIrp(
    IN  PNDISPROT_OPEN_CONTEXT       pOpenContext,
    IN  PIRP                         pIrp,
    OUT PULONG                       pBytesReturned    
    )
/*++

Routine Description:

    Queue the IRP in the context structure. This IRP will be completed
    one of the following occurs: 1) Status indication is received by
    the bound miniport, 2) IRP is cancelled by the sender, 3) We have
    been asked to unbind from the miniport either because the device is removed
    or user unchecked our binding in the network connection applet.
    
Arguments:

    pOpenContext - pointer to open context representing our binding to the miniport

Return Value:

    NTSTATUS code
    
--*/
{
    NTSTATUS NtStatus;
    
    DEBUGP(DL_LOUD, ("-->ndisprotQueueStatusIndicationIrp\n"));

    NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
    
    if(pOpenContext->StatusIndicationIrp){
        
        DEBUGP(DL_WARN, ("Control IRP to indicate status is already pending: %p\n", pIrp));
        NtStatus = STATUS_DEVICE_BUSY;
        
    }else {

        //
        // Since we are queueing the IRP, we should set the cancel routine.
        //
        IoSetCancelRoutine(pIrp, ndisCancelIndicateStatusIrp);

        //
        // Let us check to see if the IRP is cancelled at this point.
        //
        if(pIrp->Cancel && IoSetCancelRoutine(pIrp, NULL)){
            //
            // The IRP has been already cancelled but the I/O manager
            // hasn't called the cancel routine yet. So complete the
            // IRP after releasing the lock.
            //
            NtStatus = STATUS_CANCELLED;
            
        }else {
            //
            // Queue the IRP and return status pending.
            // 
            IoMarkIrpPending(pIrp);
            pOpenContext->StatusIndicationIrp = pIrp;
            NtStatus = STATUS_PENDING;
            
            //
            // The IRP shouldn't be accessed after the lock is released
            // It could be grabbed by another thread or the cancel routine
            // is running.
            //
        }
    }
    
    *pBytesReturned = 0;
    
    NPROT_RELEASE_LOCK(&pOpenContext->Lock);

    DEBUGP(DL_LOUD, ("<--ndisprotQueueStatusIndicationIrp\n"));

    return NtStatus;
    
}
VOID 
ndisServiceIndicateStatusIrp(
    IN PNDISPROT_OPEN_CONTEXT   OpenContext,
    IN NDIS_STATUS              GeneralStatus,
    IN PVOID                    StatusBuffer,
    IN UINT                     StatusBufferSize,
    IN BOOLEAN                  Cancel
    )
/*++

Routine Description:

   We process the IRP based on the input arguments and complete
   the IRP. If the IRP was cancelled for some reason we will let
   the cancel routine do the IRP completion.
    
Arguments:

    ProtocolBindingContext - pointer to open context
    GeneralStatus - status code
    StatusBuffer - status-specific additional information
    StatusBufferSize - size of the above
    Cancel - Should the IRP be cancelled right away.

Return Value:

    None

--*/
{
    PIRP pIrp = NULL;
    PIO_STACK_LOCATION      pIrpSp = NULL;    
    PNDISPROT_INDICATE_STATUS     pIndicateStatus = NULL;
    NTSTATUS    ntStatus;
    ULONG   bytes = 0;
    ULONG inBufLength, outBufLength;

    DEBUGP(DL_LOUD, ("-->ndisServiceIndicateStatusIrp\n"));
    
    NPROT_ACQUIRE_LOCK(&OpenContext->Lock);

    pIrp = OpenContext->StatusIndicationIrp;

    do {
                
        if(pIrp){
            
            pIrpSp = IoGetCurrentIrpStackLocation(pIrp);            
            pIndicateStatus = pIrp->AssociatedIrp.SystemBuffer;
            inBufLength = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
            outBufLength = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;            
            //
            // Clear the cancel routine.
            //
            if(IoSetCancelRoutine(pIrp, NULL)){
                //
                // Cancel routine cannot run now and cannot have already 
                // started to run.
                //

                ntStatus = STATUS_CANCELLED;
                
                if(!Cancel){

                    //
                    // Check to see whether the buffer is large enough.
                    //
                    if(outBufLength >= sizeof(NDISPROT_INDICATE_STATUS) &&
                        (outBufLength - sizeof(NDISPROT_INDICATE_STATUS)) >= StatusBufferSize){
                        
                        pIndicateStatus->IndicatedStatus = GeneralStatus;
                        pIndicateStatus->StatusBufferLength = StatusBufferSize;
                        pIndicateStatus->StatusBufferOffset = sizeof(NDISPROT_INDICATE_STATUS);
                                 
                        NPROT_COPY_MEM((PUCHAR)pIndicateStatus + 
                                        pIndicateStatus->StatusBufferOffset,
                                        StatusBuffer,
                                        StatusBufferSize);
                        
                        
                        ntStatus = STATUS_SUCCESS;
                        
                    } else {
                        ntStatus = STATUS_BUFFER_OVERFLOW;
                    }
                }
                //
                // Since we are completing the IRP below, clear this field.
                //
                OpenContext->StatusIndicationIrp = NULL;                
                //
                // Number of bytes copied or number of bytes required.
                //
                bytes = sizeof(NDISPROT_INDICATE_STATUS) + StatusBufferSize;
                break;
            }else {
                //
                // Cancel rotuine is running. Leave the irp alone.
                //
                pIrp = NULL;
            }
        }
    }while(FALSE);
    
    NPROT_RELEASE_LOCK(&OpenContext->Lock);

    if(pIrp){
        pIrp->IoStatus.Information = bytes;
        pIrp->IoStatus.Status = ntStatus;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    }

    DEBUGP(DL_LOUD, ("<--ndisServiceIndicateStatusIrp\n"));
    
    return;
    
}

VOID
ndisCancelIndicateStatusIrp(
    IN PDEVICE_OBJECT               pDeviceObject,
    IN PIRP                         pIrp
    )
/*++

Routine Description:

    Cancel the pending status indication IRP registered by the app or 
    another driver. 
    
Arguments:

    pDeviceObject - pointer to our device object
    pIrp - IRP to be cancelled

Return Value:

    None

--*/
{
    PNDISPROT_OPEN_CONTEXT       pOpenContext;
    PIO_STACK_LOCATION          pIrpSp = NULL;    

    UNREFERENCED_PARAMETER(pDeviceObject);

    DEBUGP(DL_LOUD, ("-->ndisCancelIndicateStatusIrp\n"));
    
    IoReleaseCancelSpinLock(pIrp->CancelIrql);

    pIrpSp = IoGetCurrentIrpStackLocation(pIrp);

    pOpenContext = (PNDISPROT_OPEN_CONTEXT)pIrpSp->FileObject->FsContext;

    NPROT_STRUCT_ASSERT(pOpenContext, oc);
    NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);

    pOpenContext->StatusIndicationIrp = NULL;

    NPROT_RELEASE_LOCK(&pOpenContext->Lock);
    
    pIrp->IoStatus.Information = 0;
    pIrp->IoStatus.Status = STATUS_CANCELLED;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    DEBUGP(DL_LOUD, ("<--ndisCancelIndicateStatusIrp\n"));

    return;

}

⌨️ 快捷键说明

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