Sample Code
Windows Driver Samples/ GPIO Sample Drivers/ C++/ simdeviceumdf/ queue.cpp/
/*++ 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" // // IUnknown implementation // // // Queue destructor. // Free up the buffer, wait for thread to terminate and // delete critical section. // CSimdeviceQueue::~CSimdeviceQueue( VOID ) /*++ Routine Description: IUnknown implementation of Release Arguments: Return Value: ULONG (reference count after Release) --*/ { if (m_Buffer) { delete [] m_Buffer; } if (m_InitCritSec) { ::DeleteCriticalSection(&m_Crit); } } // // Initialize HRESULT CSimdeviceQueue::CreateInstance( _In_ IWDFDevice *FxDevice, _Out_ PCSimdeviceQueue *Queue ) /*++ Routine Description: CreateInstance creates an instance of the queue object. Arguments: ppUkwn - OUT parameter is an IUnknown interface to the queue object Return Value: HRESULT indicating success or failure --*/ { CSimdeviceQueue *pMyQueue = new CSimdeviceQueue; HRESULT hr; if (pMyQueue == NULL) { return E_OUTOFMEMORY; } hr = pMyQueue->Initialize(FxDevice); if (SUCCEEDED(hr)) { *Queue = pMyQueue; } else { pMyQueue->Release(); } return hr; } HRESULT CSimdeviceQueue::Initialize( _In_ IWDFDevice *FxDevice ) { IWDFIoQueue *fxQueue; HRESULT hr; // // Initialize the critical section before we continue // if (!InitializeCriticalSectionAndSpinCount(&m_Crit,0x80000400)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } m_InitCritSec = TRUE; // // Create the framework queue // { IUnknown *unknown = QueryIUnknown(); hr = FxDevice->CreateIoQueue(unknown, TRUE, WdfIoQueueDispatchSequential, TRUE, FALSE, &fxQueue); unknown->Release(); } if (FAILED(hr)) { goto Exit; } m_FxQueue = fxQueue; fxQueue->Release(); Exit: return hr; } HRESULT STDMETHODCALLTYPE CSimdeviceQueue::QueryInterface( _In_ REFIID InterfaceId, _Out_ PVOID *Object ) /*++ Routine Description: Query Interface Arguments: Follows COM specifications Return Value: HRESULT indicating success or failure --*/ { HRESULT hr; if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackWrite))) { *Object = QueryIQueueCallbackWrite(); hr = S_OK; } else if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackRead))) { *Object = QueryIQueueCallbackRead(); hr = S_OK; } else if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackDeviceIoControl))) { *Object = QueryIQueueCallbackDeviceIoControl(); hr = S_OK; } else { hr = CUnknown::QueryInterface(InterfaceId, Object); } return hr; } VOID STDMETHODCALLTYPE CSimdeviceQueue::OnDeviceIoControl( _In_ IWDFIoQueue *pWdfQueue, _In_ IWDFIoRequest *pWdfRequest, _In_ ULONG ControlCode, _In_ SIZE_T InputBufferSizeInBytes, _In_ SIZE_T OutputBufferSizeInBytes ) /*++ Routine Description: DeviceIoControl dispatch routine Arguments: pWdfQueue - Framework Queue instance pWdfRequest - Framework Request instance ControlCode - IO Control Code InputBufferSizeInBytes - Length of input buffer OutputBufferSizeInBytes - Length of output buffer Always succeeds DeviceIoIoctl Return Value: VOID --*/ { UNREFERENCED_PARAMETER(pWdfQueue); UNREFERENCED_PARAMETER(ControlCode); UNREFERENCED_PARAMETER(InputBufferSizeInBytes); UNREFERENCED_PARAMETER(OutputBufferSizeInBytes); pWdfRequest->Complete(S_OK); return; } VOID STDMETHODCALLTYPE CSimdeviceQueue::OnWrite( _In_ IWDFIoQueue *pWdfQueue, _In_ IWDFIoRequest *pWdfRequest, _In_ SIZE_T BytesToWrite ) /*++ Routine Description: Write dispatch routine IQueueCallbackWrite Arguments: pWdfQueue - Framework Queue instance pWdfRequest - Framework Request instance BytesToWrite - Length of bytes in the write buffer Allocate and copy data to local buffer Return Value: VOID --*/ { HRESULT hr; IWDFMemory* pRequestMemory = NULL; IWDFIoRequest2 * pWdfRequest2 = NULL; UNREFERENCED_PARAMETER(pWdfQueue); // // Handle Zero length writes. // if (!BytesToWrite) { pWdfRequest->CompleteWithInformation(S_OK, 0); return; } if( BytesToWrite > MAX_WRITE_LENGTH ) { pWdfRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_MORE_DATA), 0); return; } // Get memory object hr = pWdfRequest->QueryInterface(IID_PPV_ARGS(&pWdfRequest2)); if (FAILED(hr)) { pWdfRequest->Complete(hr); return; } // Release previous buffer if set if( m_Buffer != NULL ) { delete [] m_Buffer; m_Buffer = NULL; m_Length = 0L; } // Allocate Buffer m_Buffer = new UCHAR[BytesToWrite]; if (m_Buffer == NULL) { pWdfRequest->Complete(E_OUTOFMEMORY); m_Length = 0L; return; } hr = pWdfRequest2->RetrieveInputMemory(&pRequestMemory); if (FAILED(hr)) { goto Exit; } // Copy from memory object to our buffer hr = pRequestMemory->CopyToBuffer(0, m_Buffer, BytesToWrite); if (FAILED(hr)) { goto Exit; } // // Save the information so that we can use it // to complete the request later. // Lock(); m_Length = (ULONG) BytesToWrite; m_XferredBytes = m_Length; m_CurrentRequest = pWdfRequest2; pWdfRequest2 = NULL; Unlock(); Exit: if (FAILED(hr)) { pWdfRequest2->CompleteWithInformation(hr, 0); delete [] m_Buffer; m_Buffer = NULL; } SAFE_RELEASE(pRequestMemory); SAFE_RELEASE(pWdfRequest2); return; } VOID STDMETHODCALLTYPE CSimdeviceQueue::OnRead( _In_ IWDFIoQueue *pWdfQueue, _In_ IWDFIoRequest *pWdfRequest, _In_ SIZE_T SizeInBytes ) /*++ Routine Description: Read dispatch routine IQueueCallbackRead Arguments: pWdfQueue - Framework Queue instance pWdfRequest - Framework Request instance SizeInBytes - Length of bytes in the read buffer Copy available data into the read buffer Return Value: VOID --*/ { IWDFMemory* pRequestMemory = NULL; IWDFIoRequest2 * pWdfRequest2 = NULL; HRESULT hr; UNREFERENCED_PARAMETER(pWdfQueue); // // Handle Zero length reads. // if (!SizeInBytes) { pWdfRequest->CompleteWithInformation(S_OK, 0); return; } if (m_Buffer == NULL) { pWdfRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), SizeInBytes); return; } if (m_Length < SizeInBytes) { SizeInBytes = m_Length; } // // Get memory object // hr = pWdfRequest->QueryInterface(IID_PPV_ARGS(&pWdfRequest2)); if (FAILED(hr)) { pWdfRequest->Complete(hr); return; } hr = pWdfRequest2->RetrieveOutputMemory(&pRequestMemory ); if (FAILED(hr)) { goto Exit; } // Copy from buffer to memory object hr = pRequestMemory->CopyFromBuffer(0, m_Buffer, SizeInBytes); if (FAILED(hr)) { goto Exit; } // // Save the information so that we can use it // to complete the request later. // Lock(); m_CurrentRequest = pWdfRequest2; m_XferredBytes = SizeInBytes; pWdfRequest2 = NULL; Unlock(); Exit: if (FAILED(hr)) { pWdfRequest2->CompleteWithInformation(hr, 0); } SAFE_RELEASE(pRequestMemory); SAFE_RELEASE(pWdfRequest2); return; } DWORD CSimdeviceQueue::CompletionThread( PVOID ThreadParameter ) /*++ Routine Description: This routine is called from the thread started to complete I/O requests. It sleeps for TIMER_PERIOD and then completes the current request. Note that it has to release the lock before it calls the request complete method. Arguments: ThreadParameter - This is a pointer to the Queue object. Return Value: VOID --*/ { CSimdeviceQueue *pQueue = (CSimdeviceQueue *)ThreadParameter; IWDFIoRequest2 *request; SIZE_T bytesXferred = 0; for (;;) { // // Block for a fixed time and then complete the request. // Sleep(TIMER_PERIOD); pQueue->Lock(); // // Process the current request. // request = pQueue->m_CurrentRequest; if (request) { bytesXferred = pQueue->m_XferredBytes; } // // Reset values. // pQueue->m_CurrentRequest = NULL; pQueue->m_XferredBytes = 0; pQueue->Unlock(); if (request) { request->CompleteWithInformation(S_OK, bytesXferred); SAFE_RELEASE(request); } // // If thread needs to be terminated // if (pQueue->m_ExitThread) { ExitThread(0); } } }
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials