summaryrefslogtreecommitdiff
path: root/wpd/WpdBasicHardwareDriver/Queue.cpp
diff options
context:
space:
mode:
authorJ M Rossy <[email protected]>2015-07-29 15:40:09 -0700
committerJ M Rossy <[email protected]>2015-07-29 16:34:40 -0700
commit5d61a4a79a1e96dc5d9af1e5e712c84507307544 (patch)
tree49ed270893578cd18758b74ffcca16dc7ab948d6 /wpd/WpdBasicHardwareDriver/Queue.cpp
parent5d41613e26e147d2300c786bb2b34cb4b4067a25 (diff)
Samples update for public Windows 10 release
Fix #2 Enabling WPP Recorder in Sensors Samples causes errors Fix #4 Add back fixed KMDOD sample Add new BarcodeScanner sample in pos folder Add new MagneticStripeReader sample in pos folder Add new SynpaticsTouch sample in input folder Add new Power Engine Plugin sample in pofx folder Add new DeviceMft sample in avstream folder Add new AvsCamera sample in root Add new SimBatt sample in root Add other pre-existing samples not yet released for Win10
Diffstat (limited to 'wpd/WpdBasicHardwareDriver/Queue.cpp')
-rw-r--r--wpd/WpdBasicHardwareDriver/Queue.cpp340
1 files changed, 340 insertions, 0 deletions
diff --git a/wpd/WpdBasicHardwareDriver/Queue.cpp b/wpd/WpdBasicHardwareDriver/Queue.cpp
new file mode 100644
index 00000000..e4e81c09
--- /dev/null
+++ b/wpd/WpdBasicHardwareDriver/Queue.cpp
@@ -0,0 +1,340 @@
+// Queue.cpp : Implementation of CQueue
+
+
+#include "stdafx.h"
+#include <devioctl.h>
+
+#include "Queue.tmh"
+
+// Add table used to lookup the Access required for Wpd Commands
+BEGIN_WPD_COMMAND_ACCESS_MAP(g_WpdCommandAccessMap)
+ DECLARE_WPD_STANDARD_COMMAND_ACCESS_ENTRIES
+ // Add any custom commands here e.g.
+ // WPD_COMMAND_ACCESS_ENTRY(MyCustomCommand, WPD_COMMAND_ACCESS_READWRITE)
+END_WPD_COMMAND_ACCESS_MAP
+
+// This enables use to use VERIFY_WPD_COMMAND_ACCESS to check command access function for us.
+DECLARE_VERIFY_WPD_COMMAND_ACCESS;
+
+/******************************************************************************
+ * This function calls the WpdBaseDriver to handle the WPD message. In order
+ * to do this it does the following:
+ *
+ * - Deserializes pBuffer into an IPortableDeviceValues which holds the command
+ * input parameters from the WPD application.
+ * - Creates an IPortableDeviceValues for the results.
+ * - Calls the WpdBaseDriver to handle the message. (The results of this
+ * operation are put into the previously created results IPortableDeviceValues.)
+ * - The results IPortableDeviceValues is then serialized back into pBuffer, making
+ * sure that it does not overrun ulOutputBufferLength.
+ *
+ *****************************************************************************/
+HRESULT CQueue::ProcessWpdMessage(
+ ULONG ControlCode,
+ _In_ ContextMap* pClientContextMap,
+ _In_ IWDFDevice* pDevice,
+ _In_reads_bytes_(ulInputBufferLength) PVOID pInBuffer,
+ ULONG ulInputBufferLength,
+ _Out_writes_bytes_to_(ulOutputBufferLength, *pdwBytesWritten) PVOID pOutBuffer,
+ ULONG ulOutputBufferLength,
+ _Out_ DWORD* pdwBytesWritten)
+{
+ CComCritSecLock<CComAutoCriticalSection> Lock(m_CriticalSection);
+
+ HRESULT hr = S_OK;
+ CComPtr<IPortableDeviceValues> pParams;
+ CComPtr<IPortableDeviceValues> pResults;
+ CComPtr<WpdBaseDriver> pWpdBaseDriver;
+
+ *pdwBytesWritten = 0;
+
+ if (hr == S_OK)
+ {
+ hr = m_pWpdSerializer->GetIPortableDeviceValuesFromBuffer((BYTE*)pInBuffer,
+ ulInputBufferLength,
+ &pParams);
+ CHECK_HR(hr, "Failed to deserialize command parameters from input buffer");
+ }
+
+ // Verify that that command was sent with the appropriate access
+ if (hr == S_OK)
+ {
+ hr = VERIFY_WPD_COMMAND_ACCESS(ControlCode, pParams, g_WpdCommandAccessMap);
+ CHECK_HR(hr, "Wpd Command was sent with incorrect access flags");
+ }
+
+ // Create the WPD results collection
+ if (hr == S_OK)
+ {
+ hr = CoCreateInstance(CLSID_PortableDeviceValues,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IPortableDeviceValues,
+ (VOID**)&pResults);
+ CHECK_HR(hr, "Failed to CoCreate CLSID_PortableDeviceValues");
+ }
+
+ // Insert the client context map as one of this driver's private properties. This is
+ // just a convenient place holder which allows other methods down the chain to
+ // access the context map.
+ if (hr == S_OK)
+ {
+ hr = pParams->SetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, pClientContextMap);
+ CHECK_HR(hr, "Failed to set PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP");
+ }
+
+ // Insert the IWDFDevice interface as one of this driver's private properties. This is
+ // just a convenient place holder which allows other methods down the chain to
+ // access the WUDF Device object.
+ if (hr == S_OK)
+ {
+ hr = pParams->SetIUnknownValue(PRIVATE_SAMPLE_DRIVER_WUDF_DEVICE_OBJECT, pDevice);
+ CHECK_HR(hr, "Failed to set PRIVATE_SAMPLE_DRIVER_WUDF_DEVICE_OBJECT");
+ }
+
+ // Insert the IWpdSerializer interface as one of this driver's private properties. This is
+ // just a convenient place holder which allows other methods down the chain to
+ // access the WPD Serializer object.
+ if (hr == S_OK)
+ {
+ hr = pParams->SetIUnknownValue(PRIVATE_SAMPLE_DRIVER_WPD_SERIALIZER_OBJECT, m_pWpdSerializer);
+ CHECK_HR(hr, "Failed to set PRIVATE_SAMPLE_DRIVER_WPD_SERIALIZER_OBJECT");
+ }
+
+ // Get the WpdBaseDriver so we can dispatch the message
+ if (hr == S_OK)
+ {
+ hr = GetWpdBaseDriver(pDevice, &pWpdBaseDriver);
+ CHECK_HR(hr, "Failed to get WpdBaseDriver");
+ }
+
+ if (hr == S_OK)
+ {
+ hr = pWpdBaseDriver->DispatchWpdMessage(pParams, pResults);
+ CHECK_HR(hr, "Failed to handle WPD command");
+ }
+
+ if (hr == S_OK)
+ {
+ hr = m_pWpdSerializer->WriteIPortableDeviceValuesToBuffer(ulOutputBufferLength,
+ pResults,
+ (BYTE*)pOutBuffer,
+ pdwBytesWritten);
+ CHECK_HR(hr, "Failed to serialize results to output buffer");
+ }
+
+ return hr;
+}
+
+/******************************************************************************
+ * This method gets the WpdBaseDriver associated with the UMDF device object.
+ * The caller should Release *ppWpdBaseDriver when it is done.
+ *
+ * When this device was created, we assigned the WpdBaseDriver as the context.
+ * So, in order to retrieve the correct WpdBaseDriver for this device, we simply
+ * get the device context.
+ *****************************************************************************/
+HRESULT CQueue::GetWpdBaseDriver(
+ _In_ IWDFDevice* pDevice,
+ _Outptr_result_nullonfailure_ WpdBaseDriver** ppWpdBaseDriver)
+{
+ HRESULT hr = S_OK;
+ WpdBaseDriver* pContext = NULL;
+
+ if((pDevice == NULL) || (ppWpdBaseDriver == NULL))
+ {
+ hr = E_POINTER;
+ CHECK_HR(hr, "Cannot have NULL parameter for pDevice or ppWpdBaseDriver");
+ }
+
+ *ppWpdBaseDriver = NULL;
+
+ if(SUCCEEDED(hr))
+ {
+ hr = pDevice->RetrieveContext((void**)&pContext);
+ if(SUCCEEDED(hr))
+ {
+ if(pContext != NULL)
+ {
+ pContext->AddRef();
+ *ppWpdBaseDriver = pContext;
+ }
+ else
+ {
+ hr = E_UNEXPECTED;
+ CHECK_HR(hr, "Device context is NULL");
+ }
+ }
+ }
+
+ return hr;
+}
+
+// CQueue
+
+STDMETHODIMP_ (void)
+CQueue::OnCreateFile(
+ _In_ IWDFIoQueue* pQueue,
+ _In_ IWDFIoRequest* pRequest,
+ _In_ IWDFFile* pFileObject
+ )
+{
+ UNREFERENCED_PARAMETER(pQueue);
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FLAG_QUEUE, "%!FUNC! Entry");
+
+ // This critical section protects the section of code where we
+ // Create the serializer and results interfaces used in handling I/O messages.
+ // We only need to create them once, then we hang on to them for the lifetime of this
+ // queue object.
+ CComCritSecLock<CComAutoCriticalSection> Lock(m_CriticalSection);
+ HRESULT hr = S_OK;
+
+ // Create the WPD serializer
+ if ((hr == S_OK) &&
+ (m_pWpdSerializer == NULL))
+ {
+ hr = CoCreateInstance(CLSID_WpdSerializer,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IWpdSerializer,
+ (VOID**)&m_pWpdSerializer);
+
+ CHECK_HR(hr, "Failed to CoCreate CLSID_WpdSerializer");
+ }
+
+ // Create the client context map and associate it with the File Object
+ // so we can obtain it on a per-client basis.
+ if (hr == S_OK)
+ {
+ ContextMap* pClientContextMap = new ContextMap();
+
+ if(pClientContextMap != NULL)
+ {
+ hr = pFileObject->AssignContext(this, (void*)pClientContextMap);
+ CHECK_HR(hr, "Failed to set client context map");
+
+ // Release the client context map if we cannot set it
+ // properly
+ if(FAILED(hr))
+ {
+ pClientContextMap->Release();
+ pClientContextMap = NULL;
+ }
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ CHECK_HR(hr, "Failed to create client context map");
+ }
+ }
+
+ pRequest->Complete(hr);
+ return;
+}
+
+STDMETHODIMP_ (void)
+CQueue::OnDeviceIoControl(
+ _In_ IWDFIoQueue* pQueue,
+ _In_ IWDFIoRequest* pRequest,
+ ULONG ControlCode,
+ SIZE_T InputBufferSizeInBytes,
+ SIZE_T OutputBufferSizeInBytes
+ )
+{
+ UNREFERENCED_PARAMETER(InputBufferSizeInBytes);
+ UNREFERENCED_PARAMETER(OutputBufferSizeInBytes);
+
+ HRESULT hr = S_OK;
+ DWORD dwBytesWritten = 0;
+
+ if(IS_WPD_IOCTL(ControlCode))
+ {
+ BYTE* pInputBuffer = NULL;
+ SIZE_T cbInputBuffer = 0;
+ BYTE* pOutputBuffer = NULL;
+ SIZE_T cbOutputBuffer = 0;
+ ContextMap* pClientContextMap = NULL;
+ CComPtr<IWDFMemory> pMemoryIn;
+ CComPtr<IWDFMemory> pMemoryOut;
+ CComPtr<IWDFDevice> pDevice;
+ CComPtr<IWDFFile> pFileObject;
+
+ //
+ // Get input memory buffer, the memory object is always returned even if the
+ // underlying buffer is NULL
+ //
+ pRequest->GetInputMemory(&pMemoryIn);
+ pInputBuffer = (BYTE*) pMemoryIn->GetDataBuffer(&cbInputBuffer);
+
+ //
+ // Get output memory buffer, the memory object is always returned even if the
+ // underlying buffer is NULL
+ //
+ pRequest->GetOutputMemory(&pMemoryOut);
+ pOutputBuffer = (BYTE*) pMemoryOut->GetDataBuffer(&cbOutputBuffer);
+
+ // Get the Context map for this client
+ pRequest->GetFileObject(&pFileObject);
+ if (pFileObject != NULL)
+ {
+ hr = pFileObject->RetrieveContext((void**)&pClientContextMap);
+ CHECK_HR(hr, "Failed to get Contextmap from WDF File Object");
+
+ if (hr == S_OK)
+ {
+ // Get the device object
+ pQueue->GetDevice(&pDevice );
+ hr = ProcessWpdMessage(ControlCode,
+ pClientContextMap,
+ pDevice,
+ pInputBuffer,
+ (DWORD)cbInputBuffer,
+ pOutputBuffer,
+ (DWORD)cbOutputBuffer,
+ &dwBytesWritten);
+ }
+ }
+ else
+ {
+ hr = E_UNEXPECTED;
+ CHECK_HR(hr, "WDF File Object is NULL");
+ }
+ }
+ else
+ {
+ hr = E_UNEXPECTED;
+ CHECK_HR(hr, "Received invalid/unsupported IOCTL code '0x%lx'",ControlCode);
+ }
+
+ // Complete the request
+ if (hr == S_OK)
+ {
+ pRequest->CompleteWithInformation(hr, dwBytesWritten);
+ }
+ else
+ {
+ pRequest->Complete(hr);
+ }
+
+ return;
+}
+
+STDMETHODIMP_ (void)
+CQueue::OnCleanup(
+ _In_ IWDFObject* pWdfObject
+ )
+{
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FLAG_QUEUE, "%!FUNC! Entry");
+
+ // Destroy the client context map
+ HRESULT hr = S_OK;
+ ContextMap* pClientContextMap = NULL;
+
+ hr = pWdfObject->RetrieveContext((void**)&pClientContextMap);
+ if((hr == S_OK) && (pClientContextMap != NULL))
+ {
+ pClientContextMap->Release();
+ pClientContextMap = NULL;
+ }
+}
+