diff options
| author | karlf <[email protected]> | 2016-08-11 13:28:13 -0700 |
|---|---|---|
| committer | karlf <[email protected]> | 2016-08-11 13:28:13 -0700 |
| commit | 96eb96dfb613e4c745db6bd1f53a92fe7e2290fc (patch) | |
| tree | ad5f3ede5cbcd6b598677ce41bcf8318471bdd92 /usb/wdf_osrfx2_lab/umdf/step4/ReadWriteQueue.cpp | |
| parent | 687b274aa38fd05c8c26e3068932121876d7f745 (diff) | |
Updated for "Windows 10 Anniversary Update" (Version 1607)
Diffstat (limited to 'usb/wdf_osrfx2_lab/umdf/step4/ReadWriteQueue.cpp')
| -rw-r--r-- | usb/wdf_osrfx2_lab/umdf/step4/ReadWriteQueue.cpp | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/usb/wdf_osrfx2_lab/umdf/step4/ReadWriteQueue.cpp b/usb/wdf_osrfx2_lab/umdf/step4/ReadWriteQueue.cpp new file mode 100644 index 00000000..21f42548 --- /dev/null +++ b/usb/wdf_osrfx2_lab/umdf/step4/ReadWriteQueue.cpp @@ -0,0 +1,423 @@ +/*++ + +Copyright (c) Microsoft Corporation, All Rights Reserved + +Module Name: + + queue.cpp + +Abstract: + + This file implements the I/O queue interface and performs + the read/write/ioctl operations. + +Environment: + + Windows User-Mode Driver Framework (WUDF) + +--*/ + +#include "internal.h" +#include "ReadWriteQueue.tmh" + +VOID +CMyReadWriteQueue::OnCompletion( + _In_ IWDFIoRequest* pWdfRequest, + _In_ IWDFIoTarget* pIoTarget, + _In_ IWDFRequestCompletionParams* pParams, + _In_ PVOID pContext + ) +{ + UNREFERENCED_PARAMETER(pIoTarget); + UNREFERENCED_PARAMETER(pContext); + + pWdfRequest->CompleteWithInformation( + pParams->GetCompletionStatus(), + pParams->GetInformation() + ); +} + +void +CMyReadWriteQueue::ForwardFormattedRequest( + _In_ IWDFIoRequest* pRequest, + _In_ IWDFIoTarget* pIoTarget + ) +{ + // + //First set the completion callback + // + + IRequestCallbackRequestCompletion * pCompletionCallback = NULL; + HRESULT hrQI = this->QueryInterface(IID_PPV_ARGS(&pCompletionCallback)); + WUDF_TEST_DRIVER_ASSERT(SUCCEEDED(hrQI) && (NULL != pCompletionCallback)); + + pRequest->SetCompletionCallback( + pCompletionCallback, + NULL + ); + + pCompletionCallback->Release(); + pCompletionCallback = NULL; + + // + //Send down the request + // + + HRESULT hrSend = S_OK; + hrSend = pRequest->Send(pIoTarget, + 0, //flags + 0); //timeout + + if (FAILED(hrSend)) + { + pRequest->CompleteWithInformation(hrSend, 0); + } + + return; +} + + +CMyReadWriteQueue::CMyReadWriteQueue( + _In_ PCMyDevice Device + ) : + CMyQueue(Device) +{ +} + +// +// Queue destructor. +// Free up the buffer, wait for thread to terminate and +// + +CMyReadWriteQueue::~CMyReadWriteQueue( + VOID + ) +/*++ + +Routine Description: + + + IUnknown implementation of Release + +Aruments: + + +Return Value: + + ULONG (reference count after Release) + +--*/ +{ + TraceEvents(TRACE_LEVEL_INFORMATION, + TEST_TRACE_QUEUE, + "%!FUNC! Entry" + ); + +} + + +HRESULT +STDMETHODCALLTYPE +CMyReadWriteQueue::QueryInterface( + _In_ REFIID InterfaceId, + _Outptr_ PVOID *Object + ) +/*++ + +Routine Description: + + + Query Interface + +Aruments: + + Follows COM specifications + +Return Value: + + HRESULT indicatin success or failure + +--*/ +{ + HRESULT hr; + + + if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackWrite))) + { + hr = S_OK; + *Object = QueryIQueueCallbackWrite(); + } + else if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackRead))) + { + hr = S_OK; + *Object = QueryIQueueCallbackRead(); + } + else if (IsEqualIID(InterfaceId, __uuidof(IRequestCallbackRequestCompletion))) + { + hr = S_OK; + *Object = QueryIRequestCallbackRequestCompletion(); + } + else if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackIoStop))) + { + hr = S_OK; + *Object = QueryIQueueCallbackIoStop(); + } + else + { + hr = CMyQueue::QueryInterface(InterfaceId, Object); + } + + return hr; +} + +// +// Initialize +// + +HRESULT +CMyReadWriteQueue::CreateInstance( + _In_ PCMyDevice Device, + _Out_ PCMyReadWriteQueue *Queue + ) +/*++ + +Routine Description: + + + CreateInstance creates an instance of the queue object. + +Aruments: + + ppUkwn - OUT parameter is an IUnknown interface to the queue object + +Return Value: + + HRESULT indicatin success or failure + +--*/ +{ + PCMyReadWriteQueue queue; + HRESULT hr = S_OK; + + queue = new CMyReadWriteQueue(Device); + + if (NULL == queue) + { + hr = E_OUTOFMEMORY; + } + + // + // Call the queue callback object to initialize itself. This will create + // its partner queue framework object. + // + + if (SUCCEEDED(hr)) + { + hr = queue->Initialize(); + } + + if (SUCCEEDED(hr)) + { + *Queue = queue; + } + else + { + SAFE_RELEASE(queue); + } + + return hr; +} + +HRESULT +CMyReadWriteQueue::Initialize( + ) +{ + HRESULT hr; + + // + // First initialize the base class. This will create the partner FxIoQueue + // object and setup automatic forwarding of I/O controls. + // + + hr = __super::Initialize(WdfIoQueueDispatchParallel, + true, + true); + + // + // return the status. + // + + return hr; +} + +STDMETHODIMP_ (void) +CMyReadWriteQueue::OnWrite( + _In_ IWDFIoQueue *pWdfQueue, + _In_ IWDFIoRequest *pWdfRequest, + _In_ SIZE_T BytesToWrite + ) +/*++ + +Routine Description: + + + Write dispatch routine + IQueueCallbackWrite + +Aruments: + + pWdfQueue - Framework Queue instance + pWdfRequest - Framework Request instance + BytesToWrite - Lenth of bytes in the write buffer + + Allocate and copy data to local buffer +Return Value: + + VOID + +--*/ +{ + UNREFERENCED_PARAMETER(pWdfQueue); + + TraceEvents(TRACE_LEVEL_INFORMATION, + TEST_TRACE_QUEUE, + "%!FUNC!: Queue %p Request %p BytesToTransfer %d\n", + this, + pWdfRequest, + (ULONG)(ULONG_PTR)BytesToWrite + ); + + HRESULT hr = S_OK; + IWDFMemory * pInputMemory = NULL; + IWDFUsbTargetPipe * pOutputPipe = m_Device->GetOutputPipe(); + + pWdfRequest->GetInputMemory(&pInputMemory); + + hr = pOutputPipe->FormatRequestForWrite( + pWdfRequest, + NULL, //pFile + pInputMemory, + NULL, //Memory offset + NULL //DeviceOffset + ); + + if (FAILED(hr)) + { + pWdfRequest->Complete(hr); + } + else + { + ForwardFormattedRequest(pWdfRequest, pOutputPipe); + } + + SAFE_RELEASE(pInputMemory); + + return; +} + +STDMETHODIMP_ (void) +CMyReadWriteQueue::OnRead( + _In_ IWDFIoQueue *pWdfQueue, + _In_ IWDFIoRequest *pWdfRequest, + _In_ SIZE_T BytesToRead + ) +/*++ + +Routine Description: + + + Read dispatch routine + IQueueCallbackRead + +Aruments: + + pWdfQueue - Framework Queue instance + pWdfRequest - Framework Request instance + BytesToRead - Lenth of bytes in the read buffer + + Copy available data into the read buffer +Return Value: + + VOID + +--*/ +{ + UNREFERENCED_PARAMETER(pWdfQueue); + + TraceEvents(TRACE_LEVEL_INFORMATION, + TEST_TRACE_QUEUE, + "%!FUNC!: Queue %p Request %p BytesToTransfer %d\n", + this, + pWdfRequest, + (ULONG)(ULONG_PTR)BytesToRead + ); + + HRESULT hr = S_OK; + IWDFMemory * pOutputMemory = NULL; + + pWdfRequest->GetOutputMemory(&pOutputMemory); + + hr = m_Device->GetInputPipe()->FormatRequestForRead( + pWdfRequest, + NULL, //pFile + pOutputMemory, + NULL, //Memory offset + NULL //DeviceOffset + ); + + if (FAILED(hr)) + { + pWdfRequest->Complete(hr); + } + else + { + ForwardFormattedRequest(pWdfRequest, m_Device->GetInputPipe()); + } + + SAFE_RELEASE(pOutputMemory); + + return; +} + +STDMETHODIMP_ (void) +CMyReadWriteQueue::OnIoStop( + _In_ IWDFIoQueue * pWdfQueue, + _In_ IWDFIoRequest * pWdfRequest, + _In_ ULONG ActionFlags + ) +{ + UNREFERENCED_PARAMETER(pWdfQueue); + + + // + // Because of device level locking we know that if our driver + // owns the request and we get here, our OnRead/OnWrite callback + // has returned and the request has been sent to I/O target + // + + if (ActionFlags == WdfRequestStopActionSuspend ) + { + // + // UMDF does not support an equivalent to WdfRequestStopAcknowledge. + // + // Cancel the request so that the power management operation can continue. + // + // NOTE: if cancelling the request would have an adverse affect and if the + // requests are expected to complete very quickly then leaving the + // request running may be a better option. + // + + pWdfRequest->CancelSentRequest(); + } + else if(ActionFlags == WdfRequestStopActionPurge) + { + // + // Cancel the sent request since we are asked to purge the request + // + + pWdfRequest->CancelSentRequest(); + } + + return; +} + |
