diff options
Diffstat (limited to 'nfp/net/driver/Queue.cpp')
| -rw-r--r-- | nfp/net/driver/Queue.cpp | 824 |
1 files changed, 0 insertions, 824 deletions
diff --git a/nfp/net/driver/Queue.cpp b/nfp/net/driver/Queue.cpp deleted file mode 100644 index 129a5439..00000000 --- a/nfp/net/driver/Queue.cpp +++ /dev/null @@ -1,824 +0,0 @@ -/*++ - -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: - - user mode only - -Revision History: - ---*/ -#include "internal.h" - -#include "queue.tmh" - -CMyQueue::CMyQueue( - VOID - ) -{ - InitializeListHead(&m_SubsHead); - InitializeListHead(&m_ArrivalSubsHead); - InitializeListHead(&m_DepartureSubsHead); - InitializeListHead(&m_PubsHead); - InitializeListHead(&m_ConnectionHead); - - InitializeCriticalSection(&m_SubsLock); - InitializeCriticalSection(&m_PubsLock); - InitializeCriticalSection(&m_ConnectionLock); -} - -CMyQueue::~CMyQueue( - VOID - ) -{ - MethodEntry("void"); - - m_SocketListener.StopAccepting(); - - while (!IsListEmpty(&m_ConnectionHead)) - { - delete CConnection::FromListEntry(RemoveHeadList(&m_ConnectionHead)); - } - - DeleteCriticalSection(&m_SubsLock); - DeleteCriticalSection(&m_PubsLock); - DeleteCriticalSection(&m_ConnectionLock); -} - -// -// Initialize -// - -HRESULT -CMyQueue::Initialize( - _In_ CMyDevice * Device - ) -/*++ - -Routine Description: - - Queue Initialize helper routine. - This routine will Create a default parallel queue associated with the Fx device object - and pass the IUnknown for this queue - -Aruments: - Device object pointer - -Return Value: - - S_OK if Initialize succeeds - ---*/ -{ - MethodEntry("..."); - - CComPtr<IWDFIoQueue> fxQueue; - - HRESULT hr; - - // - // Create the I/O Queue object. - // - { - CComPtr<IUnknown> pUnk; - - HRESULT hrQI = this->QueryInterface(__uuidof(IUnknown),(void**)&pUnk); - - WUDF_SAMPLE_DRIVER_ASSERT(SUCCEEDED(hrQI)); - - hr = Device->GetFxDevice()->CreateIoQueue( - pUnk, - TRUE, - WdfIoQueueDispatchParallel, - TRUE, - FALSE, - &fxQueue - ); - } - - if (FAILED(hr)) - { - TraceErrorHR(hr, "Failed to initialize driver queue"); - } - - if (SUCCEEDED(hr)) - { - hr = m_SocketListener.Bind(); - if (FAILED(hr)) - { - TraceErrorHR(hr, "Failed to Bind"); - } - } - - if (SUCCEEDED(hr)) - { - hr = m_SocketListener.EnableAccepting(this); - if (FAILED(hr)) - { - TraceErrorHR(hr, "Failed to EnableAccepting"); - } - } - - if (SUCCEEDED(hr)) - { - m_FxQueue = fxQueue; - } - - MethodReturnHR(hr); -} - -HRESULT -CMyQueue::Configure( - VOID - ) -/*++ - -Routine Description: - - Queue configuration function . - It is called after queue object has been succesfully initialized. - -Aruments: - - NONE - - Return Value: - - S_OK if succeeds. - ---*/ -{ - MethodEntry("void"); - - HRESULT hr = S_OK; - - MethodReturnHR(hr); -} - - -STDMETHODIMP_(void) -CMyQueue::OnCreateFile( - _In_ IWDFIoQueue* /*pWdfQueue*/, - _In_ IWDFIoRequest* pWdfRequest, - _In_ IWDFFile* pWdfFile - ) - -/*++ - -Routine Description: - - Create callback from the framework for this default parallel queue - - The create request will create a socket connection , create a file i/o target associated - with the socket handle for this connection and store in the file object context. - -Aruments: - - pWdfQueue - Framework Queue instance - pWdfRequest - Framework Request instance - pWdfFile - WDF file object for this create - - Return Value: - - VOID - ---*/ -{ - MethodEntry("pWdfRequest = %p, pWdfFile = %p", - pWdfRequest, pWdfFile); - - HRESULT hr = S_OK; - - // - // Create file context for this file object - // - - CFileContext *pContext = new CFileContext(); - if (NULL == pContext) - { - hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); - TraceErrorHR(hr, "Could not create file context"); - } - - if (SUCCEEDED(hr)) - { - DWORD cchFileName = 0; - hr = pWdfFile->RetrieveFileName(NULL, &cchFileName); - if (SUCCEEDED(hr) && (cchFileName > 0) && (cchFileName <= MaxCchType)) - { - // Allocate a buffer big enough for the filename plus some extra to prevent - // overruns in the parsing below: The extra needs to be larger than the biggest - // *_CHARS value. The value 20 is overly big, but allows room to grow without - // hitting the OACR issue again. If the OACR issue is hit, just increase this - // to be larger than the biggest *_CHARS value used below in parsing. - DWORD cchFileNameBuffer = cchFileName + 20; - PWSTR pszFileNameBuffer = new WCHAR[cchFileNameBuffer]; - hr = (pszFileNameBuffer != NULL) ? S_OK : E_OUTOFMEMORY; - if (SUCCEEDED(hr)) - { - ZeroMemory(pszFileNameBuffer, cchFileNameBuffer * sizeof(WCHAR)); - - hr = pWdfFile->RetrieveFileName(pszFileNameBuffer, &cchFileName); - } - - if (SUCCEEDED(hr)) - { - PCWSTR pszFileName = pszFileNameBuffer; - if (pszFileNameBuffer[0] == L'\\') - { - // If it exists, remove the inital slash - pszFileName++; - cchFileName--; - } - - TraceInfo("cchFileName = %d, pszFileName = %S", cchFileName, pszFileName); - - PCWSTR pszProtocol = NULL; - if (CompareStringOrdinal(pszFileName, PUBS_NAMESPACE_CHARS, - PUBS_NAMESPACE, PUBS_NAMESPACE_CHARS, - TRUE) == CSTR_EQUAL) - { - pContext->SetRolePublication(); - pszProtocol = pszFileName + PUBS_NAMESPACE_CHARS; - } - else if (CompareStringOrdinal(pszFileName, SUBS_NAMESPACE_CHARS, - SUBS_NAMESPACE, SUBS_NAMESPACE_CHARS, - TRUE) == CSTR_EQUAL) - { - pContext->SetRoleSubcription(); - pszProtocol = pszFileName + SUBS_NAMESPACE_CHARS; - } - else - { - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - } - - if (SUCCEEDED(hr)) - { - if (CompareStringOrdinal(pszProtocol, WINDOWS_PROTOCOL_CHARS, - WINDOWS_PROTOCOL, WINDOWS_PROTOCOL_CHARS, - TRUE) == CSTR_EQUAL) - { - pContext->SetType(pszProtocol); - } - else if (CompareStringOrdinal(pszProtocol, -1, - WINDOWSURI_PROTOCOL, -1, - TRUE) == CSTR_EQUAL) - { - pContext->SetType(pszProtocol); - } - else if (CompareStringOrdinal(pszProtocol, WINDOWSMIME_PROTOCOL_CHARS, - WINDOWSMIME_PROTOCOL, WINDOWSMIME_PROTOCOL_CHARS, - TRUE) == CSTR_EQUAL) - { - pContext->SetType(pszProtocol); - } - else if (CompareStringOrdinal(pszProtocol, -1, DEVICE_ARRIVED, -1, - TRUE) == CSTR_EQUAL) - { - if (!pContext->SetRoleArrivedSubcription()) - { - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - } - } - else if (CompareStringOrdinal(pszProtocol, -1, DEVICE_DEPARTED, -1, - TRUE) == CSTR_EQUAL) - { - if (!pContext->SetRoleDepartedSubcription()) - { - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - } - } - else if (CompareStringOrdinal(pszProtocol, PAIRING_PROTOCOL_CHARS, - PAIRING_PROTOCOL, PAIRING_PROTOCOL_CHARS, - TRUE) == CSTR_EQUAL) - { - pContext->SetType(pszProtocol); - } - else if (CompareStringOrdinal(pszProtocol, NDEF_PROTOCOL_CHARS, - NDEF_PROTOCOL, NDEF_PROTOCOL_CHARS, - TRUE) == CSTR_EQUAL) - { - PCWSTR pszType = pszProtocol + NDEF_PROTOCOL_CHARS; - - if (CompareStringOrdinal(pszType, NDEF_EMPTY_TYPE_CHARS, - NDEF_EMPTY_TYPE, NDEF_EMPTY_TYPE_CHARS, - TRUE) != CSTR_EQUAL) - { - pContext->SetType(pszProtocol); - } - else - { - hr = HRESULT_FROM_NT(STATUS_INVALID_PARAMETER); - } - } - else - { - hr = HRESULT_FROM_NT(STATUS_OBJECT_PATH_NOT_FOUND); - } - } - } - - if (pszFileNameBuffer != NULL) - { - delete [] pszFileNameBuffer; - } - } - } - - if (SUCCEEDED(hr)) - { - hr = pWdfFile->AssignContext(NULL, (void*)pContext); - if (FAILED(hr)) - { - TraceErrorHR(hr, "Unable to Assign Context to this File Object"); - } - } - - if (SUCCEEDED(hr)) - { - EnterCriticalSection(&m_SubsLock); - - if (pContext->IsNormalSubscription()) - { - // Place this CFileContext into a list of Subscriptions - InsertHeadList(&m_SubsHead, pContext->GetListEntry()); - } - else if (pContext->IsArrivedSubscription()) - { - // Place this CFileContext into a list of arrival registrations - InsertHeadList(&m_ArrivalSubsHead, pContext->GetListEntry()); - } - else if (pContext->IsDepartedSubscription()) - { - // Place this CFileContext into a list of removal registrations - InsertHeadList(&m_DepartureSubsHead, pContext->GetListEntry()); - } - - LeaveCriticalSection(&m_SubsLock); - } - - if (FAILED(hr)) - { - if (pContext != NULL) - { - delete pContext; - pContext = NULL; - } - } - - pWdfRequest->Complete(hr); - - MethodReturnVoid(); -} - -STDMETHODIMP_(void) -CMyQueue::OnCloseFile( - _In_ IWDFFile* pWdfFileObject - ) -/*++ - - Routine Description: - - This method is called when an app closes the file handle to this device. - This will free the context memory associated with this file object, close - the connection object associated with this file object and delete the file - handle i/o target object associated with this file object. - - Arguments: - - pWdfFileObject - the framework file object for which close is handled. - - Return Value: - - None - ---*/ -{ - MethodEntry("..."); - - HRESULT hr = S_OK ; - CFileContext* pContext = NULL; - hr = pWdfFileObject->RetrieveContext((void**)&pContext); - if (SUCCEEDED(hr) && (pContext != NULL)) - { - CRITICAL_SECTION* pCritSec = NULL; - LIST_ENTRY* pHead = NULL; - - if (pContext->IsNormalSubscription()) - { - pCritSec = &m_SubsLock; - pHead = &m_SubsHead; - } - else if (pContext->IsArrivedSubscription()) - { - pCritSec = &m_SubsLock; - pHead = &m_ArrivalSubsHead; - } - else if (pContext->IsDepartedSubscription()) - { - pCritSec = &m_SubsLock; - pHead = &m_DepartureSubsHead; - } - else if (pContext->IsPublication()) - { - pCritSec = &m_PubsLock; - pHead = &m_PubsHead; - } - - if (pHead != NULL) - { - EnterCriticalSection(pCritSec); - - LIST_ENTRY* pFindEntry = pContext->GetListEntry(); - LIST_ENTRY* pEntry = pHead->Flink; - while (pEntry != pHead) - { - if (pEntry == pFindEntry) - { - RemoveEntryList(pEntry); - break; - } - - pEntry = pEntry->Flink; - } - - LeaveCriticalSection(pCritSec); - } - - delete pContext; - } - - MethodReturnVoid(); -} - -STDMETHODIMP_ (void) -CMyQueue::OnCancel( - _In_ IWDFIoRequest* pWdfRequest - ) -{ - MethodEntry("pWdfRequest = %p", - pWdfRequest); - - IWDFFile* pFxFile; - pWdfRequest->GetFileObject(&pFxFile); - if (pFxFile != NULL) - { - CFileContext* pFileContext; - HRESULT hr = pFxFile->RetrieveContext((void**)&pFileContext); - if (SUCCEEDED(hr)) - { - pFileContext->OnCancel(); - } - } - - MethodReturnVoid(); -} - -#define IOCTL_BEGIN_PROXIMITY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x1000, METHOD_BUFFERED, FILE_ANY_ACCESS) - -STDMETHODIMP_ (void) -CMyQueue::OnDeviceIoControl( - _In_ IWDFIoQueue* /*pWdfQueue*/, - _In_ IWDFIoRequest* pWdfRequest, - _In_ ULONG ControlCode, - _In_ SIZE_T /*InBufferSize*/, - _In_ SIZE_T /*OutBufferSize*/ - ) -{ - MethodEntry("pWdfRequest = %p, ControlCode = %d", - pWdfRequest, ControlCode); - - IWDFFile* pFxFile; - - pWdfRequest->GetFileObject(&pFxFile); - - bool fCompleteRequest = true; - - CFileContext *pFileContext; - HRESULT hr = pFxFile->RetrieveContext((void**)&pFileContext); - if (SUCCEEDED(hr)) - { - switch (ControlCode) - { - case IOCTL_NFP_GET_MAX_MESSAGE_BYTES: - { - IWDFMemory* pWdfOutputMemory; - pWdfRequest->GetOutputMemory(&pWdfOutputMemory); - if (pWdfOutputMemory != NULL) - { - SIZE_T cbOutputBuffer = 0; - // Set the first 4 bytes as the maximum message size of this device/driver - DWORD dwMaxCbPayload = MaxCbPayload; - hr = pWdfOutputMemory->CopyFromBuffer(0, &dwMaxCbPayload, 4); - if (SUCCEEDED(hr)) - { - cbOutputBuffer = 4; - } - pWdfOutputMemory->Release(); - - pWdfRequest->CompleteWithInformation(hr, cbOutputBuffer); - fCompleteRequest = false; - } - } - break; - - case IOCTL_NFP_GET_KILO_BYTES_PER_SECOND: - { - IWDFMemory* pWdfOutputMemory; - pWdfRequest->GetOutputMemory(&pWdfOutputMemory); - if (pWdfOutputMemory != NULL) - { - SIZE_T cbOutputBuffer = 0; - // Set the first 4 bytes as transfer speed of this device/driver - DWORD dwKilobytesPerSecond = KilobytesPerSecond; - hr = pWdfOutputMemory->CopyFromBuffer(0, &dwKilobytesPerSecond, 4); - if (SUCCEEDED(hr)) - { - cbOutputBuffer = 4; - } - pWdfOutputMemory->Release(); - - pWdfRequest->CompleteWithInformation(hr, cbOutputBuffer); - fCompleteRequest = false; - } - } - break; - - case IOCTL_NFP_DISABLE: - hr = pFileContext->Disable(); - break; - - case IOCTL_NFP_ENABLE: - hr = pFileContext->Enable(); - break; - - case IOCTL_NFP_SET_PAYLOAD: - hr = pFileContext->SetPayload(pWdfRequest); - if (SUCCEEDED(hr)) - { - MESSAGE* pMessage = new MESSAGE(); - hr = (pMessage != NULL) ? S_OK : E_OUTOFMEMORY; - if (SUCCEEDED(hr)) - { - pMessage->Initialize(pFileContext->GetType(), pFileContext->GetSize(), pFileContext->GetPayload()); - - EnterCriticalSection(&m_ConnectionLock); - - for (LIST_ENTRY* pEntry = m_ConnectionHead.Flink; - pEntry != &m_ConnectionHead; - pEntry = pEntry->Flink) - { - CConnection* pConnection = CConnection::FromListEntry(pEntry); - if (SUCCEEDED(pConnection->TransmitMessage(pMessage))) - { - pFileContext->HandleMessageTransmitted(); - } - } - - LeaveCriticalSection(&m_ConnectionLock); - - // Place this CFileContext into a list of published messages - EnterCriticalSection(&m_PubsLock); - InsertHeadList(&m_PubsHead, pFileContext->GetListEntry()); - LeaveCriticalSection(&m_PubsLock); - - delete pMessage; - } - } - break; - - case IOCTL_BEGIN_PROXIMITY: - hr = pFileContext->BeginProximity(pWdfRequest, this); - break; - - case IOCTL_NFP_GET_NEXT_SUBSCRIBED_MESSAGE: - hr = pFileContext->GetNextSubscribedMessage(this, pWdfRequest); - if (SUCCEEDED(hr)) - { - fCompleteRequest = false; - } - break; - - case IOCTL_NFP_GET_NEXT_TRANSMITTED_MESSAGE: - hr = pFileContext->GetNextTransmittedMessage(this, pWdfRequest); - if (SUCCEEDED(hr)) - { - fCompleteRequest = false; - } - break; - - default: - hr = HRESULT_FROM_NT(STATUS_INVALID_DEVICE_STATE); - break; - } - } - - if (fCompleteRequest) - { - TraceInfo("Completing Request: %!HRESULT!", hr); - pWdfRequest->Complete(hr); - } - - MethodReturnVoid(); -} - -void -CMyQueue::ValidateAccept(_In_ SOCKET Socket, _In_ GUID* pMagicPacket) -{ - MethodEntry("..."); - - CConnection* pConnection; - HRESULT hr = CConnection::Create(this, &pConnection); - if (SUCCEEDED(hr)) - { - // Mark it as an Inbound connection, so we know to delete it when - // it's removed from the list - pConnection->SetInboundConnection(); - - pConnection->ValidateAccept(Socket, pMagicPacket); - Socket = INVALID_SOCKET; - } - - if (Socket != INVALID_SOCKET) - { - closesocket(Socket); - } - - MethodReturnVoid(); -} - -void -CMyQueue::HandleReceivedMessage(_In_ MESSAGE* pMessage) -{ - MethodEntry("pMessage->m_szType = '%S'", - pMessage->m_szType); - - if ((pMessage->m_cbPayload > 0) && (pMessage->m_cbPayload <= MaxCbPayload)) - { - EnterCriticalSection(&m_SubsLock); - - LIST_ENTRY* pEntry = m_SubsHead.Flink; - while (pEntry != &m_SubsHead) - { - CFileContext* pSub = CFileContext::FromListEntry(pEntry); - - pSub->HandleReceivedPublication(pMessage->m_szType, - pMessage->m_cbPayload, - pMessage->m_Payload); - - pEntry = pEntry->Flink; - } - - LeaveCriticalSection(&m_SubsLock); - } - - MethodReturnVoid(); -} - -void -CMyQueue::ConnectionEstablished(_In_ CConnection* pConnection) -{ - MethodEntry("..."); - - EnterCriticalSection(&m_ConnectionLock); - BOOL fFirstConnection = IsListEmpty(&m_ConnectionHead); - InsertHeadList(&m_ConnectionHead, pConnection->GetListEntry()); - LeaveCriticalSection(&m_ConnectionLock); - - if (fFirstConnection) - { - AddArrivalEvent(); - } - - MESSAGE* pMessage = new MESSAGE(); - if (pMessage != NULL) - { - EnterCriticalSection(&m_PubsLock); - - LIST_ENTRY* pEntry = m_PubsHead.Flink; - while (pEntry != &m_PubsHead) - { - CFileContext* pPub = CFileContext::FromListEntry(pEntry); - if (pPub->IsEnabled()) - { - pMessage->Initialize(pPub->GetType(), pPub->GetSize(), pPub->GetPayload()); - if (SUCCEEDED(pConnection->TransmitMessage(pMessage))) - { - pPub->HandleMessageTransmitted(); - } - } - pEntry = pEntry->Flink; - } - - LeaveCriticalSection(&m_PubsLock); - delete pMessage; - } - - MethodReturnVoid(); -} - -BOOL -CMyQueue::ConnectionTerminated(_In_ CConnection* pConnection) -{ - MethodEntry("pConnection = 0x%p", - pConnection); - - LIST_ENTRY* pRemoveListEntry = pConnection->GetListEntry(); - - EnterCriticalSection(&m_ConnectionLock); - LIST_ENTRY* pEntry = m_ConnectionHead.Flink; - while (pEntry != &m_ConnectionHead) - { - if (pEntry == pRemoveListEntry) - { - RemoveEntryList(pEntry); - break; - } - pEntry = pEntry->Flink; - } - BOOL fNoMoreConnections = IsListEmpty(&m_ConnectionHead); - - LeaveCriticalSection(&m_ConnectionLock); - - BOOL fConnectionDeleted = FALSE; - if (pConnection->IsInboundConnection()) - { - delete pConnection; - fConnectionDeleted = TRUE; - } - - if (fNoMoreConnections) - { - AddRemovalEvent(); - } - - MethodReturnBool(fConnectionDeleted); -} - -void -CMyQueue::AddArrivalEvent() -{ - MethodEntry("void"); - - EnterCriticalSection(&m_SubsLock); - - for (LIST_ENTRY* pEntry = m_ArrivalSubsHead.Flink; - pEntry != &m_ArrivalSubsHead; - pEntry = pEntry->Flink) - { - CFileContext::FromListEntry(pEntry)->HandleArrivalEvent(); - } - - LeaveCriticalSection(&m_SubsLock); - - MethodReturnVoid(); -} - -void -CMyQueue::AddRemovalEvent() -{ - MethodEntry("void"); - - EnterCriticalSection(&m_SubsLock); - - for (LIST_ENTRY* pEntry = m_DepartureSubsHead.Flink; - pEntry != &m_DepartureSubsHead; - pEntry = pEntry->Flink) - { - CFileContext::FromListEntry(pEntry)->HandleRemovalEvent(); - } - - LeaveCriticalSection(&m_SubsLock); - - MethodReturnVoid(); -} - -STDMETHODIMP_(void) -CMyQueue::OnCleanup( - _In_ IWDFObject* /*pWdfObject*/ - ) -{ - MethodEntry("..."); - - // - // CMyQueue has a reference to framework device object via m_Queue. - // Framework queue object has a reference to CMyQueue object via the callbacks. - // This leads to circular reference and both the objects can't be destroyed until this circular reference is broken. - // To break the circular reference we release the reference to the framework queue object here in OnCleanup. - // - - m_FxQueue = NULL; - - MethodReturnVoid(); -} |
