Example #1
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaEventsDequeue -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  DtaEventsDequeue(
    DtaDeviceData*  pDvcData,
    DtFileObject*  pFile,
    DtaEvents*  pEvents)            // If not NULL, we don't need the file object
{
    WDF_REQUEST_PARAMETERS  Params;
    WDFREQUEST  Request;
    WDFREQUEST  Request2;
    NTSTATUS  NtStatus = STATUS_SUCCESS;
    size_t  BufSize;
    DtaIoctlOutputData*  pOutBuf;
    
    
    // Get all pending requests from queue for this file object
    while (NtStatus == STATUS_SUCCESS)
    {
        WDF_REQUEST_PARAMETERS_INIT(&Params);
        
        NtStatus = WdfIoQueueFindRequest(pDvcData->m_IalData.m_EventQueue, NULL, 
                                               DtFileGetHandle(pFile), &Params, &Request);
        if (NtStatus != STATUS_SUCCESS) // Don't use the NT_SUCCESS macro here
            break;
        
        NtStatus = WdfIoQueueRetrieveFoundRequest(pDvcData->m_IalData.m_EventQueue, 
                                                                      Request, &Request2);
        
        WdfObjectDereference(Request);
        if (!NT_SUCCESS(NtStatus))
            continue;
        
        if (NT_SUCCESS(NtStatus))
        {
            NtStatus = WdfRequestRetrieveOutputBuffer(Request2, 
                                     Params.Parameters.DeviceIoControl.OutputBufferLength,
                                     &pOutBuf, &BufSize);
        }

        if (NT_SUCCESS(NtStatus))
        {   DtStatus  Status;
            BufSize = sizeof(DtaIoctlGetEventOutput);
            Status = DtaEventsGet(pDvcData, pFile, pEvents,
                                                    &pOutBuf->m_GetEvent.m_EventType,
                                                    &pOutBuf->m_GetEvent.m_Value1,
                                                    &pOutBuf->m_GetEvent.m_Value2);
        }

        if (!NT_SUCCESS(NtStatus))
            BufSize = 0;
        
        // Complete request, use DtStatus in the driver-defined information field
        WdfRequestCompleteWithInformation(Request2, NtStatus, (ULONG_PTR)BufSize);
    }
    return DT_STATUS_OK;
}
NTSTATUS
SimSensorScanPendingQueue (
    _In_ WDFDEVICE Device
    )

/*++

Routine Description:

    This routine scans the device's pending queue for retirable requests.

    N.B. This routine requires the QueueLock be held.

Arguments:

    Device - Supplies a handle to the device.

--*/

{
    WDFREQUEST CurrentRequest;
    PFDO_DATA DevExt;
    WDFREQUEST LastRequest;
    ULONG LowerBound;
    NTSTATUS Status;
    ULONG Temperature;
    ULONG UpperBound;

    DebugEnter();
    PAGED_CODE();

    DevExt = GetDeviceExtension(Device);

    Status = STATUS_SUCCESS;

    LastRequest = NULL;
    CurrentRequest = NULL;
    Temperature = SimSensorReadVirtualTemperature(Device);

    //
    // Prime the walk by finding the first request present. If there are no
    // requests, bail out immediately.
    //

    LowerBound = 0;
    UpperBound = (ULONG)-1;
    Status = WdfIoQueueFindRequest(DevExt->PendingRequestQueue,
                                   NULL,
                                   NULL,
                                   NULL,
                                   &CurrentRequest);

    //
    // Due to a technical limitation in SDV analysis engine, the following
    // analysis assume has to be inserted to supress a false defect for
    // the wdfioqueueretrievefoundrequest rule.
    //

    _Analysis_assume_(Status == STATUS_NOT_FOUND);

    while (NT_SUCCESS(Status)) {

        //
        // Walk past the current request. By walking past the current request
        // before checking it, the walk doesn't have to restart every time a
        // request is satisfied and removed form the queue.
        //

        LastRequest = CurrentRequest;
        Status = WdfIoQueueFindRequest(DevExt->PendingRequestQueue,
                                       LastRequest,
                                       NULL,
                                       NULL,
                                       &CurrentRequest);

        //
        // Process the last request.
        //

        SimSensorCheckQueuedRequest(Device,
                                    Temperature,
                                    &LowerBound,
                                    &UpperBound,
                                    LastRequest);

        WdfObjectDereference(LastRequest);

        if(Status == STATUS_NOT_FOUND) {

            //
            // LastRequest unexpectedly disappeared from the queue. Start over.
            //

            LowerBound = 0;
            UpperBound = (ULONG)-1;
            Status = WdfIoQueueFindRequest(DevExt->PendingRequestQueue,
                                           NULL,
                                           NULL,
                                           NULL,
                                           &CurrentRequest);

        }

    }

    //
    // Update the thresholds based on the latest contents of the queue.
    //

    SimSensorSetVirtualInterruptThresholds(Device, LowerBound, UpperBound);
    DebugExitStatus(Status);
    return Status;
}