summaryrefslogtreecommitdiff
path: root/nfc/Simulator/Src/FileContext.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 /nfc/Simulator/Src/FileContext.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 'nfc/Simulator/Src/FileContext.cpp')
-rw-r--r--nfc/Simulator/Src/FileContext.cpp640
1 files changed, 640 insertions, 0 deletions
diff --git a/nfc/Simulator/Src/FileContext.cpp b/nfc/Simulator/Src/FileContext.cpp
new file mode 100644
index 00000000..6e609832
--- /dev/null
+++ b/nfc/Simulator/Src/FileContext.cpp
@@ -0,0 +1,640 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ filecontext.cpp
+
+Abstract:
+
+ This file implements the class for context associated with the file object
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "Internal.h"
+#include "FileContext.tmh"
+
+CFileObject::CFileObject(
+ WDFFILEOBJECT FileObject
+ )
+ : m_FileObject(FileObject),
+ m_Role(ROLE_UNDEFINED),
+ m_pszType(nullptr),
+ m_fEnabled(TRUE),
+ m_dwQueueSize(0),
+ m_cCompleteReady(0),
+ m_pConnection(nullptr),
+ m_Request(nullptr),
+ m_SecureElementEventType(ExternalReaderArrival)
+{
+ NT_ASSERT(m_FileObject != nullptr);
+
+ InitializeListHead(&m_Queue);
+ InitializeListHead(&m_ListEntry);
+ InitializeCriticalSection(&m_RoleLock);
+
+ RtlZeroMemory(&m_SecureElementId, sizeof(GUID));
+}
+
+CFileObject::~CFileObject()
+{
+ //
+ // The object is bound to the file handle and so this happens after close and the
+ // framework guarentees all requests on the file handle are cancelled prior to close
+ //
+ EnterCriticalSection(&m_RoleLock);
+ NT_ASSERT(m_Request == nullptr);
+ LeaveCriticalSection(&m_RoleLock);
+
+ PurgeQueue();
+
+ SAFE_DELETEARRAY(m_pszType);
+ SAFE_DELETE(m_pConnection);
+
+ DeleteCriticalSection(&m_RoleLock);
+
+ m_FileObject = nullptr;
+}
+
+VOID CFileObject::OnDestroy(_In_ WDFOBJECT FileObject)
+{
+ FunctionEntry("...");
+
+ CFileObject *pFileObject = GetFileObject(FileObject);
+
+ NT_ASSERT(pFileObject != nullptr);
+
+ if (pFileObject->m_FileObject == FileObject) {
+ // File object constructed using placement 'new' so explicitly invoke destructor
+ pFileObject->~CFileObject();
+ }
+
+ FunctionReturnVoid();
+}
+
+NTSTATUS CFileObject::Enable()
+{
+ MethodEntry("void");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsPublication() || IsSubscription());
+
+ if (m_fEnabled) {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ goto Exit;
+ }
+
+ m_fEnabled = TRUE;
+
+Exit:
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS CFileObject::Disable()
+{
+ MethodEntry("void");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsPublication() || IsSubscription());
+
+ if (!m_fEnabled) {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ goto Exit;
+ }
+
+ m_fEnabled = FALSE;
+ CompleteRequest(STATUS_CANCELLED, 0, true);
+ PurgeQueue();
+
+Exit:
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS CFileObject::SetType(_In_ PCWSTR pszType)
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ size_t cchType = wcslen(pszType) + 1;
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(m_pszType == nullptr);
+
+ NT_ASSERT(IsPublication() || IsSubscription());
+
+ if ((cchType > MinCchType) && (cchType < MaxCchType)) {
+ m_pszType = new WCHAR[cchType];
+
+ if (m_pszType != nullptr) {
+ StringCchCopy(m_pszType, cchType, pszType);
+ }
+ else {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ else {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS CFileObject::GetNextSubscribedMessage(_In_ WDFREQUEST Request)
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ CPayload* pPayload = nullptr;
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsSubscription());
+
+ if (m_Request != nullptr) {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ goto Exit;
+ }
+
+ if (!m_fEnabled) {
+ Status = STATUS_CANCELLED;
+ goto Exit;
+ }
+
+ Status = WdfRequestMarkCancelableEx(Request, CFileObject::OnRequestCancel);
+
+ if (NT_SUCCESS(Status)) {
+ m_Request = Request;
+
+ if (!IsListEmpty(&m_Queue)) {
+ pPayload = CPayload::FromListEntry(m_Queue.Flink);
+
+ if (CompleteRequest(pPayload->GetSize(), pPayload->GetPayload())) {
+ m_dwQueueSize--;
+ RemoveHeadList(&m_Queue);
+ delete pPayload;
+ }
+ }
+ }
+
+Exit:
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS CFileObject::SetPayload(_In_ DWORD cbPayload, _In_reads_bytes_(cbPayload) PBYTE pbPayload)
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsPublication());
+
+ if (m_Payload.GetPayload() != nullptr) {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ goto Exit;
+ }
+
+ Status = m_Payload.Initialize(cbPayload, pbPayload);
+
+Exit:
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS CFileObject::GetNextTransmittedMessage(_In_ WDFREQUEST Request)
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsPublication());
+
+ if (m_Request != nullptr) {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ goto Exit;
+ }
+
+ if (!m_fEnabled) {
+ Status = STATUS_CANCELLED;
+ goto Exit;
+ }
+
+ Status = WdfRequestMarkCancelableEx(Request, CFileObject::OnRequestCancel);
+
+ if (NT_SUCCESS(Status)) {
+ m_Request = Request;
+
+ if (m_cCompleteReady > 0) {
+ if (CompleteRequest(STATUS_SUCCESS, 0, true)) {
+ m_cCompleteReady--;
+ }
+ }
+ }
+
+Exit:
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS CFileObject::GetNextSecureElementPayload(_In_ WDFREQUEST Request)
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ CPayload* pPayload = nullptr;
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsSecureElementEvent() || IsSecureElementManager());
+
+ if (m_Request != nullptr) {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ goto Exit;
+ }
+
+ Status = WdfRequestMarkCancelableEx(Request, CFileObject::OnRequestCancel);
+
+ if (NT_SUCCESS(Status)) {
+ m_Request = Request;
+
+ if (!IsListEmpty(&m_Queue)) {
+ pPayload = CPayload::FromListEntry(m_Queue.Flink);
+
+ if (CompleteRequest(pPayload->GetSize(), pPayload->GetPayload())) {
+ m_dwQueueSize--;
+ RemoveHeadList(&m_Queue);
+ delete pPayload;
+ }
+ }
+ }
+
+Exit:
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS CFileObject::SubscribeForEvent(_In_ GUID& SecureElementId, _In_ SECURE_ELEMENT_EVENT_TYPE SecureElementEventType)
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsSecureElementEvent());
+
+ m_SecureElementId = SecureElementId;
+ m_SecureElementEventType = SecureElementEventType;
+
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CFileObject::BeginProximity(
+ _In_ BEGIN_PROXIMITY_ARGS *pArgs,
+ _In_ IConnectionCallback* pCallback
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ NT_ASSERT(IsRoleSimulation());
+
+ if (CConnection::Create(pCallback, &m_pConnection)) {
+ if (SUCCEEDED(m_pConnection->InitializeAsClient(pArgs))) {
+ Status = STATUS_SUCCESS;
+ }
+ else {
+ Status = STATUS_INTERNAL_ERROR;
+ }
+ }
+ else {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+void CFileObject::HandleArrivalEvent()
+{
+ MethodEntry("void");
+
+ DWORD dwFlags = 1; // payload for arrival event
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsArrivedSubscription());
+
+ if (m_fEnabled) {
+ HandleReceivedMessage(sizeof(DWORD), (PBYTE) &dwFlags);
+ }
+
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturnVoid();
+}
+
+void CFileObject::HandleRemovalEvent()
+{
+ MethodEntry("void");
+
+ DWORD dwFlags = 0; // payload for removal event
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsDepartedSubscription());
+
+ if (m_fEnabled) {
+ HandleReceivedMessage(sizeof(DWORD), (PBYTE) &dwFlags);
+ }
+
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturnVoid();
+}
+
+void CFileObject::HandleMessageTransmitted(void)
+{
+ MethodEntry("m_fEnabled=%!bool!", m_fEnabled);
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsPublication());
+
+ if (m_fEnabled) {
+ if (!CompleteRequest(STATUS_SUCCESS, 0, true)) {
+ m_cCompleteReady++;
+ }
+ }
+
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturnVoid();
+}
+
+void
+CFileObject::HandleReceivedMessage(
+ _In_ PCWSTR pszType,
+ _In_ DWORD cbPayload,
+ _In_reads_bytes_(cbPayload) PBYTE pbPayload
+ )
+{
+ MethodEntry("Enabled=%!bool!", m_fEnabled);
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsNormalSubscription());
+
+ if (m_fEnabled) {
+ if ((CompareStringOrdinal(m_pszType, -1, WINDOWSMIME_PROTOCOL, -1, FALSE) == CSTR_EQUAL) &&
+ (wcslen(pszType) > WINDOWSMIME_PROTOCOL_CHARS) &&
+ (CompareStringOrdinal(pszType, WINDOWSMIME_PROTOCOL_CHARS, WINDOWSMIME_PROTOCOL, -1, FALSE) == CSTR_EQUAL)) {
+
+ CHAR szMimeType[MaxCchMimeType + 1] = {};
+ BYTE* pbNewPayload = new BYTE[cbPayload + MaxCchMimeType];
+
+ if (pbNewPayload != nullptr) {
+ if (SUCCEEDED(StringCchPrintfA(szMimeType, _countof(szMimeType), "%S", pszType + WINDOWSMIME_PROTOCOL_CHARS + 1))) {
+ RtlCopyMemory(pbNewPayload, szMimeType, MaxCchMimeType);
+ RtlCopyMemory(pbNewPayload + MaxCchMimeType, pbPayload, cbPayload);
+
+ HandleReceivedMessage(cbPayload + MaxCchMimeType, pbNewPayload);
+ }
+
+ SAFE_DELETEARRAY(pbNewPayload);
+ }
+ }
+ else if (CompareStringOrdinal(pszType, -1, m_pszType, -1, FALSE) == CSTR_EQUAL) {
+ if (CompareStringOrdinal(m_pszType, -1, WINDOWSURI_PROTOCOL, -1, FALSE) == CSTR_EQUAL) {
+ // WindowsUri must be returned as NULL terminated UTF16
+ DWORD cbNewPayload = cbPayload + sizeof(WCHAR);
+ BYTE* pbNewPayload = new BYTE[cbNewPayload];
+
+ if (pbNewPayload != nullptr) {
+ RtlCopyMemory(pbNewPayload, pbPayload, cbPayload);
+ RtlZeroMemory(pbNewPayload + cbPayload, sizeof(WCHAR));
+
+ HandleReceivedMessage(cbNewPayload, pbNewPayload);
+
+ SAFE_DELETEARRAY(pbNewPayload);
+ }
+ }
+ else {
+ HandleReceivedMessage(cbPayload, pbPayload);
+ }
+ }
+ }
+
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturnVoid();
+}
+
+void CFileObject::HandleReceiveHcePacket(
+ _In_ USHORT uConnectionId,
+ _In_ DWORD cbPayload,
+ _In_reads_bytes_(cbPayload) PBYTE pbPayload
+ )
+{
+ MethodEntry("...");
+
+ size_t cbUsedBufferSize = 0;
+ DWORD cbNewPayload = cbPayload + 2 * sizeof(USHORT);
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsSecureElementManager());
+
+ BYTE* pbNewPayload = new BYTE[cbNewPayload];
+
+ if (pbNewPayload != nullptr) {
+ RtlCopyMemory(pbNewPayload + cbUsedBufferSize, &uConnectionId, sizeof(USHORT));
+ cbUsedBufferSize += sizeof(USHORT);
+ USHORT cbSize = (USHORT)cbPayload;
+
+ RtlCopyMemory(pbNewPayload + cbUsedBufferSize, &cbSize, sizeof(USHORT));
+ cbUsedBufferSize += sizeof(USHORT);
+ RtlCopyMemory(pbNewPayload + cbUsedBufferSize, pbPayload, cbPayload);
+
+ HandleReceivedMessage(cbNewPayload, pbNewPayload);
+
+ SAFE_DELETEARRAY(pbNewPayload);
+ }
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturnVoid();
+}
+
+void CFileObject::HandleSecureElementEvent(SECURE_ELEMENT_EVENT_INFO* pInfo)
+{
+ MethodEntry("...");
+
+ EnterCriticalSection(&m_RoleLock);
+
+ NT_ASSERT(IsSecureElementEvent());
+
+ if ((IsEqualGUID(m_SecureElementId, pInfo->guidSecureElementId) || IsEqualGUID(m_SecureElementId, GUID_NULL)) &&
+ (m_SecureElementEventType == pInfo->eEventType)) {
+ BYTE* pbPayload = (BYTE*)pInfo;
+ DWORD cbPayload = SECURE_ELEMENT_EVENT_INFO_HEADER + pInfo->cbEventData;
+
+ HandleReceivedMessage(cbPayload, pbPayload);
+ }
+
+ LeaveCriticalSection(&m_RoleLock);
+ MethodReturnVoid();
+}
+
+VOID CFileObject::HandleReceivedMessage(
+ _In_ DWORD cbPayload,
+ _In_reads_bytes_(cbPayload) PBYTE pbPayload
+ )
+{
+ bool fDelivered = false;
+
+ if (m_Request != nullptr) {
+ fDelivered = CompleteRequest(cbPayload, pbPayload);
+ }
+
+ if ((!fDelivered) && (m_dwQueueSize < MAX_MESSAGE_QUEUE_SIZE)) {
+ CPayload* pPayload = new CPayload();
+
+ if (pPayload != nullptr) {
+ if (NT_SUCCESS(pPayload->Initialize(cbPayload, pbPayload))) {
+ InsertTailList(&m_Queue, pPayload->GetListEntry());
+ m_dwQueueSize++;
+ }
+ else {
+ delete pPayload;
+ }
+ }
+ }
+}
+
+VOID CFileObject::OnRequestCancel(_In_ WDFREQUEST Request)
+{
+ FunctionEntry("...");
+
+ CFileObject *pFileObject = GetFileObject(WdfRequestGetFileObject(Request));
+
+ NT_ASSERT(pFileObject != nullptr);
+ pFileObject->Cancel();
+
+ FunctionReturnVoid();
+}
+
+void CFileObject::Cancel()
+{
+ MethodEntry("...");
+
+ EnterCriticalSection(&m_RoleLock);
+ CompleteRequest(STATUS_CANCELLED, 0, false);
+ LeaveCriticalSection(&m_RoleLock);
+
+ MethodReturnVoid();
+}
+
+bool
+CFileObject::CompleteRequest(
+ _In_ DWORD cbPayload,
+ _In_reads_bytes_opt_(cbPayload) PBYTE pbPayload
+ )
+{
+ MethodEntry("cbPayload = %d", cbPayload);
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ bool fDelivered = false;
+ WDFMEMORY OutputMemory;
+ size_t cbUsedBufferSize = 0;
+ size_t cbMaxBufferSize = 0;
+
+ NT_ASSERT(m_Request != nullptr);
+
+ Status = WdfRequestRetrieveOutputMemory(m_Request, &OutputMemory);
+
+ if (NT_SUCCESS(Status) && OutputMemory != nullptr) {
+ // Set the first 4 bytes as the size of the payload as a hint for future subscriptions.
+ Status = WdfMemoryCopyFromBuffer(OutputMemory, cbUsedBufferSize, &cbPayload, sizeof(DWORD));
+ cbUsedBufferSize += sizeof(DWORD);
+
+ if (NT_SUCCESS(Status)) {
+ if (pbPayload != nullptr) {
+ WdfMemoryGetBuffer(OutputMemory, &cbMaxBufferSize);
+
+ if (cbMaxBufferSize < (cbPayload + cbUsedBufferSize)) {
+ // We are unable to copy the payload into the output memory,
+ // Returning this signals to the client to send a bigger buffer
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else {
+ Status = WdfMemoryCopyFromBuffer(OutputMemory, cbUsedBufferSize, pbPayload, cbPayload);
+ }
+ }
+
+ if (NT_SUCCESS(Status)) {
+ fDelivered = true;
+ cbUsedBufferSize += cbPayload;
+ }
+ }
+
+ if (!CompleteRequest(Status, cbUsedBufferSize, true)) {
+ fDelivered = false;
+ }
+ }
+
+ MethodReturnBool(fDelivered);
+}
+
+
+bool
+CFileObject::CompleteRequest(
+ _In_ NTSTATUS CompletionStatus,
+ _In_ size_t cbSize,
+ _In_ bool fIsCancelable
+ )
+{
+ MethodEntry("CompletionStatus = %!STATUS!, cbSize = %d, fIsCancelable = %!bool!",
+ CompletionStatus, (DWORD)cbSize, fIsCancelable);
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ bool fCompleted = false;
+
+ if (m_Request != nullptr) {
+ if (fIsCancelable) {
+ Status = WdfRequestUnmarkCancelable(m_Request);
+ }
+
+ if (NT_SUCCESS(Status)) {
+ WdfRequestCompleteWithInformation(m_Request, CompletionStatus, cbSize);
+ m_Request = nullptr;
+ fCompleted = true;
+ }
+ }
+
+ MethodReturnBool(fCompleted);
+}
+
+void CFileObject::PurgeQueue()
+{
+ m_dwQueueSize = 0;
+
+ while (!IsListEmpty(&m_Queue)) {
+ delete CPayload::FromListEntry(RemoveHeadList(&m_Queue));
+ }
+} \ No newline at end of file