summaryrefslogtreecommitdiff
path: root/nfc/Simulator/Src/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 /nfc/Simulator/Src/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 'nfc/Simulator/Src/Queue.cpp')
-rw-r--r--nfc/Simulator/Src/Queue.cpp2420
1 files changed, 2420 insertions, 0 deletions
diff --git a/nfc/Simulator/Src/Queue.cpp b/nfc/Simulator/Src/Queue.cpp
new file mode 100644
index 00000000..c72dfba9
--- /dev/null
+++ b/nfc/Simulator/Src/Queue.cpp
@@ -0,0 +1,2420 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ queue.cpp
+
+Abstract:
+
+ This file implements the I/O queue interface and performs the ioctl operations.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "Internal.h"
+#include "Queue.tmh"
+
+CQueue::CQueue(WDFQUEUE Queue) :
+ m_Queue(Queue),
+ m_SmartCardReader(WdfIoQueueGetDevice(Queue)),
+ m_SocketListener(this),
+ m_pSEManager(nullptr),
+ m_pHCEConnection(nullptr),
+ m_NfpRadioState(TRUE),
+ m_NfpRadioOffPolicyOverride(FALSE),
+ m_NfpRadioOffSystemOverride(FALSE),
+ m_SERadioState(TRUE),
+ m_NfpInterfaceCreated(FALSE),
+ m_ScInterfaceCreated(FALSE),
+ m_SEInterfaceCreated(FALSE),
+ m_RoutingTable(this),
+ m_HCEConnectionId(0)
+{
+ NT_ASSERT(m_Queue != nullptr);
+
+ InitializeListHead(&m_SubsList);
+ InitializeListHead(&m_ArrivalSubsList);
+ InitializeListHead(&m_DepartureSubsList);
+ InitializeListHead(&m_PubsList);
+ InitializeListHead(&m_ConnectionList);
+ InitializeListHead(&m_SecureElementList);
+ InitializeListHead(&m_SEEventsList);
+
+ InitializeCriticalSection(&m_SubsLock);
+ InitializeCriticalSection(&m_PubsLock);
+ InitializeCriticalSection(&m_ConnectionLock);
+ InitializeCriticalSection(&m_SEManagerLock);
+ InitializeCriticalSection(&m_SEEventsLock);
+ InitializeCriticalSection(&m_RadioLock);
+ InitializeCriticalSection(&m_pHCEConnectionLock);
+}
+
+CQueue::~CQueue()
+{
+ DeleteCriticalSection(&m_SubsLock);
+ DeleteCriticalSection(&m_PubsLock);
+ DeleteCriticalSection(&m_ConnectionLock);
+ DeleteCriticalSection(&m_SEEventsLock);
+ DeleteCriticalSection(&m_RadioLock);
+ DeleteCriticalSection(&m_pHCEConnectionLock);
+
+ m_Queue = nullptr;
+}
+
+NTSTATUS CQueue::Initialize()
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ WSADATA WsaData = {};
+
+ DECLARE_CONST_UNICODE_STRING(RMNamespace, RM_NAMESPACE);
+ DECLARE_CONST_UNICODE_STRING(SCNamespace, SMARTCARD_READER_NAMESPACE);
+ DECLARE_CONST_UNICODE_STRING(SimulatorNamespace, SIM_NAMESPACE);
+
+ ReadSettingsFromRegistry();
+
+ if (WSAStartup(MAKEWORD(2,2), &WsaData) != 0) {
+ Status = STATUS_INTERNAL_ERROR;
+ goto Exit;
+ }
+
+
+ if (!NT_SUCCESS(m_SmartCardReader.Initialize())) {
+ Status = STATUS_INTERNAL_ERROR;
+ goto Exit;
+ }
+
+ if (FAILED(m_SocketListener.Bind())) {
+ Status = STATUS_INTERNAL_ERROR;
+ goto Exit;
+ }
+
+ if (FAILED(m_SocketListener.EnableAccepting())) {
+ Status = STATUS_INTERNAL_ERROR;
+ goto Exit;
+ }
+
+ EnumerateSecureElements();
+ m_RoutingTable.Initialize(WdfIoQueueGetDevice(m_Queue));
+
+ // Register for NFP Radio Manager interface
+ Status = WdfDeviceCreateDeviceInterface(
+ WdfIoQueueGetDevice(m_Queue),
+ (LPGUID) &GUID_NFC_RADIO_MEDIA_DEVICE_INTERFACE,
+ &RMNamespace);
+
+ if (!NT_SUCCESS(Status)) {
+ TraceInfo("WdfDeviceCreateDeviceInterface failed with %!STATUS!", Status);
+ goto Exit;
+ }
+
+ if (IsNfpRadioEnabled()) {
+ // Register for Proximity interface
+ Status = WdfDeviceCreateDeviceInterface(
+ WdfIoQueueGetDevice(m_Queue),
+ (LPGUID) &GUID_DEVINTERFACE_NFP,
+ nullptr);
+
+ if (!NT_SUCCESS(Status)) {
+ TraceInfo("WdfDeviceCreateDeviceInterface failed with Status %!STATUS!", Status);
+ goto Exit;
+ }
+
+ m_NfpInterfaceCreated = TRUE;
+
+ // Register for Smart Card interface
+ Status = WdfDeviceCreateDeviceInterface(
+ WdfIoQueueGetDevice(m_Queue),
+ (LPGUID) &GUID_DEVINTERFACE_SMARTCARD_READER,
+ &SCNamespace);
+
+ if (!NT_SUCCESS(Status)) {
+ TraceInfo("WdfDeviceCreateDeviceInterface failed with Status %!STATUS!", Status);
+ goto Exit;
+ }
+
+ m_ScInterfaceCreated = TRUE;
+ }
+
+ if (IsSERadioEnabled()) {
+ // Register for Secure Element interface
+ Status = WdfDeviceCreateDeviceInterface(
+ WdfIoQueueGetDevice(m_Queue),
+ (LPGUID) &GUID_DEVINTERFACE_NFCSE,
+ nullptr);
+
+ if (!NT_SUCCESS(Status)) {
+ TraceInfo("WdfDeviceCreateDeviceInterface failed with Status %!STATUS!", Status);
+ goto Exit;
+ }
+
+ m_SEInterfaceCreated = TRUE;
+ }
+
+ // Register for Simulator interface
+ Status = WdfDeviceCreateDeviceInterface(
+ WdfIoQueueGetDevice(m_Queue),
+ (LPGUID) &GUID_DEVINTERFACE_NFCSIM,
+ &SimulatorNamespace);
+
+ if (!NT_SUCCESS(Status)) {
+ TraceInfo("WdfDeviceCreateDeviceInterface failed with %!STATUS!", Status);
+ goto Exit;
+ }
+
+Exit:
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS CQueue::Deinitialize()
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ while (!IsListEmpty(&m_SecureElementList)) {
+ delete CSecureElement::FromListEntry(RemoveHeadList(&m_SecureElementList));
+ }
+
+
+ m_SocketListener.StopAccepting();
+ m_SmartCardReader.Deinitialize();
+
+ while (!IsListEmpty(&m_ConnectionList)) {
+ delete CConnection::FromListEntry(RemoveHeadList(&m_ConnectionList));
+ }
+
+ WSACleanup();
+
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+BOOLEAN CQueue::IsNfpRadioEnabled()
+{
+ BOOLEAN NfpRadioState;
+
+ EnterCriticalSection(&m_RadioLock);
+ NfpRadioState = m_NfpRadioState;
+ LeaveCriticalSection(&m_RadioLock);
+
+ return NfpRadioState;
+}
+
+BOOLEAN CQueue::IsSERadioEnabled()
+{
+ BOOLEAN SERadioState;
+
+ EnterCriticalSection(&m_RadioLock);
+ SERadioState = m_SERadioState;
+ LeaveCriticalSection(&m_RadioLock);
+
+ return SERadioState;
+}
+
+NTSTATUS CQueue::DetectRole(CFileObject *pFileObject, PCWSTR pszFileName)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PCWSTR pszProtocol = nullptr;
+ PCWSTR pszType = nullptr;
+
+ MethodEntry("pszFileName = %S", pszFileName);
+
+ if (IsStringPrefixed(pszFileName, PUBS_NAMESPACE)) {
+ if (IsNfpRadioEnabled()) {
+ pFileObject->SetRolePublication();
+ pszProtocol = pszFileName + PUBS_NAMESPACE_CHARS;
+ }
+ else {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ }
+ }
+ else if (IsStringPrefixed(pszFileName, SUBS_NAMESPACE)) {
+ if (IsNfpRadioEnabled()) {
+ pFileObject->SetRoleSubcription();
+ pszProtocol = pszFileName + SUBS_NAMESPACE_CHARS;
+ }
+ else {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ }
+ }
+ else if (IsStringEqual(pszFileName, SEEVENTS_NAMESPACE)) {
+ if (IsSERadioEnabled()) {
+ pFileObject->SetRoleSecureElementEvent();
+ }
+ else {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ }
+ }
+ else if (IsStringEqual(pszFileName, SEMANAGE_NAMESPACE)) {
+ if (IsSERadioEnabled()) {
+ pFileObject->SetRoleSecureElementManager();
+ }
+ else {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ }
+ }
+ else if (IsStringEqual(pszFileName, SMARTCARD_READER_NAMESPACE)) {
+ if (IsNfpRadioEnabled()) {
+ pFileObject->SetRoleSmartCardReader();
+ }
+ else {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ }
+ }
+ else if (IsStringEqual(pszFileName, SIM_NAMESPACE)) {
+ pFileObject->SetRoleSimulation();
+ }
+ else if (IsStringEqual(pszFileName, RM_NAMESPACE)) {
+ pFileObject->SetRoleRadioManager();
+ }
+ else {
+ Status = STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+
+ if (NT_SUCCESS(Status) && pszProtocol != nullptr) {
+ Status = STATUS_OBJECT_PATH_NOT_FOUND;
+
+ if (IsStringPrefixed(pszProtocol, WINDOWS_PROTOCOL)) {
+ pszType = pszProtocol + WINDOWS_PROTOCOL_CHARS;
+
+ if (*pszType == L'.') {
+ Status = pFileObject->SetType(pszProtocol);
+ }
+ else if (*pszType == L':') {
+ pszType = pszType + 1;
+
+ if (pFileObject->IsPublication() && IsStringEqual(pszType, WRITETAG_TYPE)) {
+ Status = pFileObject->SetType(pszProtocol);
+ }
+ }
+ else if (IsStringPrefixed(pszType, WINDOWSURI_TYPE)) {
+ pszType = pszType + WINDOWSURI_TYPE_CHARS;
+
+ if (*pszType == L'\0') {
+ Status = pFileObject->SetType(pszProtocol);
+ }
+ else if (*pszType == L':') {
+ pszType = pszType + 1;
+
+ if (pFileObject->IsPublication() && IsStringEqual(pszType, WRITETAG_TYPE)) {
+ Status = pFileObject->SetType(pszProtocol);
+ }
+ }
+ }
+ else if (IsStringPrefixed(pszType, WINDOWSMIME_TYPE)) {
+ pszType = pszType + WINDOWSMIME_TYPE_CHARS;
+
+ if (*pszType == L'\0') {
+ if (pFileObject->IsNormalSubscription()) {
+ Status = pFileObject->SetType(pszProtocol);
+ }
+ }
+ else if (*pszType == L':') {
+ pszType = pszType + 1;
+
+ if (pFileObject->IsPublication() && IsStringEqual(pszType, WRITETAG_TYPE)) {
+ Status = pFileObject->SetType(pszProtocol);
+ }
+ }
+ else if (*pszType == L'.') {
+ Status = pFileObject->SetType(pszProtocol);
+ }
+ }
+ }
+ else if (IsStringPrefixed(pszProtocol, NDEF_PROTOCOL)) {
+ pszType = pszProtocol + NDEF_PROTOCOL_CHARS;
+
+ if (*pszType == L'\0') {
+ Status = pFileObject->SetType(pszProtocol);
+ }
+ else if (*pszType == L':') {
+ pszType = pszType + 1;
+
+ if (pFileObject->IsPublication()) {
+ if (IsStringEqual(pszType, WRITETAG_TYPE)) {
+ Status = pFileObject->SetType(pszProtocol);
+ }
+ }
+ else {
+ if (IsStringPrefixed(pszType, NDEF_EXT_TYPE) ||
+ IsStringPrefixed(pszType, NDEF_MIME_TYPE) ||
+ IsStringPrefixed(pszType, NDEF_URI_TYPE) ||
+ IsStringPrefixed(pszType, NDEF_WKT_TYPE) ||
+ IsStringPrefixed(pszType, NDEF_UNKNOWN_TYPE)) {
+ Status = pFileObject->SetType(pszProtocol);
+ }
+ }
+ }
+ }
+ else if (pFileObject->IsPublication()) {
+ if (IsStringEqual(pszProtocol, LAUNCHAPP_WRITETAG_PROTOCOL)) {
+ Status = pFileObject->SetType(pszProtocol);
+ }
+ }
+ else if (pFileObject->IsNormalSubscription()) {
+ if (IsStringEqual(pszProtocol, DEVICE_ARRIVED)) {
+ if (pFileObject->SetRoleArrivedSubcription()) {
+ Status = STATUS_SUCCESS;
+ }
+ }
+ else if (IsStringEqual(pszProtocol, DEVICE_DEPARTED)) {
+ if (pFileObject->SetRoleDepartedSubcription()) {
+ Status = STATUS_SUCCESS;
+ }
+ }
+ else if (IsStringEqual(pszProtocol, PAIRING_BLUETOOTH_PROTOCOL) ||
+ IsStringEqual(pszProtocol, PAIRING_UPNP_PROTOCOL) ||
+ IsStringEqual(pszProtocol, WRITEABLETAG_PROTOCOL)) {
+ Status = pFileObject->SetType(pszProtocol);
+ }
+ }
+ }
+
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+void
+CQueue::OnFileCreate(
+ _In_ WDFDEVICE Device,
+ _In_ WDFREQUEST Request,
+ _In_ WDFFILEOBJECT FileObject
+ )
+{
+ MethodEntry("Request = %p, FileObject = %p", Request, FileObject);
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ PUNICODE_STRING FileName = nullptr;
+ PCWSTR pszFileName = nullptr;
+ CFileObject *pFileObject = nullptr;
+
+ UNREFERENCED_PARAMETER(Device);
+
+ // Construct file object on the preallocated buffer using placement 'new'
+ pFileObject = new (GetFileObject(FileObject)) CFileObject(FileObject);
+
+ if (pFileObject == nullptr) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ FileName = WdfFileObjectGetFileName(FileObject);
+
+ if ((FileName != nullptr) && (FileName->Length > 0)) {
+ NT_ASSERT(FileName->Buffer != nullptr);
+
+ if ((FileName->Length / sizeof(WCHAR)) > MaxCchType) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ pszFileName = FileName->Buffer;
+ pszFileName = (pszFileName[0] == L'\\') ? pszFileName+1 : pszFileName;
+
+ Status = DetectRole(pFileObject, pszFileName);
+
+ if (!NT_SUCCESS(Status)) {
+ goto Exit;
+ }
+
+ TraceInfo("pszFileName = %S pFileObject = %p", pszFileName, pFileObject);
+ }
+
+ if (pFileObject->IsNormalSubscription()) {
+ EnterCriticalSection(&m_SubsLock);
+ InsertHeadList(&m_SubsList, pFileObject->GetListEntry());
+ LeaveCriticalSection(&m_SubsLock);
+ }
+ else if (pFileObject->IsArrivedSubscription()) {
+ EnterCriticalSection(&m_SubsLock);
+ InsertHeadList(&m_ArrivalSubsList, pFileObject->GetListEntry());
+ LeaveCriticalSection(&m_SubsLock);
+ }
+ else if (pFileObject->IsDepartedSubscription()) {
+ EnterCriticalSection(&m_SubsLock);
+ InsertHeadList(&m_DepartureSubsList, pFileObject->GetListEntry());
+ LeaveCriticalSection(&m_SubsLock);
+ }
+ else if (pFileObject->IsSmartCardReader()) {
+ Status = m_SmartCardReader.AddClient(pFileObject);
+ }
+ else if (pFileObject->IsSecureElementManager()) {
+ EnterCriticalSection(&m_SEManagerLock);
+ Status = InterlockedCompareExchangePointer((void**)&m_pSEManager, pFileObject, nullptr) == nullptr ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
+ LeaveCriticalSection(&m_SEManagerLock);
+ }
+
+Exit:
+ TraceInfo("%!FUNC! Completing Request with Status %!STATUS!", Status);
+ WdfRequestComplete(Request, Status);
+
+ MethodReturnVoid();
+}
+
+void CQueue::OnFileClose(_In_ WDFFILEOBJECT FileObject)
+{
+ MethodEntry("...");
+
+ CFileObject* pFileObject = GetFileObject(FileObject);
+ CRITICAL_SECTION *pLock = nullptr;
+ LIST_ENTRY* pHead = nullptr;
+
+ NT_ASSERT(pFileObject != nullptr);
+
+ if (pFileObject->IsNormalSubscription()) {
+ pLock = &m_SubsLock;
+ pHead = &m_SubsList;
+ }
+ else if (pFileObject->IsArrivedSubscription()) {
+ pLock = &m_SubsLock;
+ pHead = &m_ArrivalSubsList;
+ }
+ else if (pFileObject->IsDepartedSubscription()) {
+ pLock = &m_SubsLock;
+ pHead = &m_DepartureSubsList;
+ }
+ else if (pFileObject->IsPublication()) {
+ pLock = &m_PubsLock;
+ pHead = &m_PubsList;
+ }
+ else if (pFileObject->IsSmartCardReader()) {
+ m_SmartCardReader.RemoveClient(pFileObject);
+ }
+ else if (pFileObject->IsSecureElementEvent()) {
+ pLock = &m_SEEventsLock;
+ pHead = &m_SEEventsList;
+ }
+ else if (pFileObject->IsSecureElementManager()) {
+ EnterCriticalSection(&m_SEManagerLock);
+ InterlockedCompareExchangePointer((void**)&m_pSEManager, nullptr, pFileObject);
+ LeaveCriticalSection(&m_SEManagerLock);
+
+ for (LIST_ENTRY* pEntry = m_SecureElementList.Flink;
+ pEntry != &m_SecureElementList;
+ pEntry = pEntry->Flink) {
+ CSecureElement::FromListEntry(pEntry)->SetEmulationMode(EmulationOff);
+ }
+ }
+
+ if (pHead != nullptr) {
+ EnterCriticalSection(pLock);
+
+ for (LIST_ENTRY* pEntry = pHead->Flink;
+ pEntry != pHead;
+ pEntry = pEntry->Flink) {
+ if (pEntry == pFileObject->GetListEntry()) {
+ RemoveEntryList(pEntry);
+ break;
+ }
+ }
+ LeaveCriticalSection(pLock);
+ }
+
+ MethodReturnVoid();
+}
+
+VOID
+CQueue::OnIoDeviceControl(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request,
+ _In_ size_t OutputBufferLength,
+ _In_ size_t InputBufferLength,
+ _In_ ULONG IoControlCode
+ )
+{
+ FunctionEntry("...");
+
+ CQueue *pQueue = GetQueueObject(Queue);
+
+ NT_ASSERT(pQueue != nullptr);
+ pQueue->OnIoDeviceControl(Request, IoControlCode, InputBufferLength, OutputBufferLength);
+
+ FunctionReturnVoid();
+}
+
+void
+CQueue::OnIoDeviceControl(
+ _In_ WDFREQUEST Request,
+ _In_ ULONG IoControlCode,
+ _In_ size_t InputBufferLength,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("Request = %p, IoControlCode = 0x%x InputBufferLength=%d OutputBufferLength=%d",
+ Request, IoControlCode, (DWORD)InputBufferLength, (DWORD)OutputBufferLength);
+
+ NTSTATUS Status = STATUS_INVALID_DEVICE_STATE;
+
+ switch (IoControlCode)
+ {
+ case IOCTL_NFP_GET_MAX_MESSAGE_BYTES:
+ case IOCTL_NFP_GET_KILO_BYTES_PER_SECOND:
+ case IOCTL_NFP_DISABLE:
+ case IOCTL_NFP_ENABLE:
+ case IOCTL_NFP_SET_PAYLOAD:
+ case IOCTL_NFP_GET_NEXT_SUBSCRIBED_MESSAGE:
+ case IOCTL_NFP_GET_NEXT_TRANSMITTED_MESSAGE:
+ case IOCTL_NFCSIM_BEGIN_PROXIMITY:
+ {
+ const DISPATCH_ENTRY DispatchTable[] =
+ {
+ { IOCTL_NFP_ENABLE, 0, 0, &CQueue::OnNfpEnable },
+ { IOCTL_NFP_DISABLE, 0, 0, &CQueue::OnNfpDisable },
+ { IOCTL_NFP_GET_NEXT_SUBSCRIBED_MESSAGE, 0, sizeof(DWORD), &CQueue::OnNfpGetNextSubscribedMessage },
+ { IOCTL_NFP_SET_PAYLOAD, MinCbPayload, 0, &CQueue::OnNfpSetPayload },
+ { IOCTL_NFP_GET_NEXT_TRANSMITTED_MESSAGE, 0, 0, &CQueue::OnNfpGetNextTransmittedMessage },
+ { IOCTL_NFP_GET_MAX_MESSAGE_BYTES, 0, sizeof(DWORD), &CQueue::OnNfpGetMaxMessageBytes },
+ { IOCTL_NFP_GET_KILO_BYTES_PER_SECOND, 0, sizeof(DWORD), &CQueue::OnNfpGetTransmissionRateKbps },
+ { IOCTL_NFCSIM_BEGIN_PROXIMITY, sizeof(BEGIN_PROXIMITY_ARGS), 0, &CQueue::OnNfpBeginProximity },
+ };
+
+ if (IsNfpRadioEnabled()) {
+ Status = DispatchMessage(DispatchTable, _countof(DispatchTable), Request, IoControlCode, InputBufferLength, OutputBufferLength);
+ }
+ }
+ break;
+
+ case IOCTL_NFCSE_ENUM_ENDPOINTS:
+ case IOCTL_NFCSE_SUBSCRIBE_FOR_EVENT:
+ case IOCTL_NFCSE_GET_NEXT_EVENT:
+ case IOCTL_NFCSE_SET_CARD_EMULATION_MODE:
+ case IOCTL_NFCSIM_TRIGGER_SEEVENT:
+ case IOCTL_NFCSE_GET_NFCC_CAPABILITIES:
+ case IOCTL_NFCSE_GET_ROUTING_TABLE:
+ case IOCTL_NFCSE_SET_ROUTING_TABLE:
+ case IOCTL_NFCSE_HCE_REMOTE_RECV:
+ case IOCTL_NFCSE_HCE_REMOTE_SEND:
+ {
+ const DISPATCH_ENTRY DispatchTable[] =
+ {
+ { IOCTL_NFCSE_SET_CARD_EMULATION_MODE, sizeof(SECURE_ELEMENT_SET_CARD_EMULATION_MODE_INFO), 0, &CQueue::OnSESetCardEmulationMode },
+ { IOCTL_NFCSE_GET_NEXT_EVENT, 0, sizeof(DWORD), &CQueue::OnSEGetNextEvent },
+ { IOCTL_NFCSE_SUBSCRIBE_FOR_EVENT, sizeof(SECURE_ELEMENT_EVENT_SUBSCRIPTION_INFO), 0, &CQueue::OnSESubscribeForEvent },
+ { IOCTL_NFCSE_ENUM_ENDPOINTS, 0, sizeof(DWORD), &CQueue::OnSEEnumEndpoints },
+ { IOCTL_NFCSE_GET_NFCC_CAPABILITIES, 0, sizeof(SECURE_ELEMENT_NFCC_CAPABILITIES), &CQueue::OnSEGetNfccCapabilities },
+ { IOCTL_NFCSE_GET_ROUTING_TABLE, 0, sizeof(DWORD), &CQueue::OnSEGetRoutingTable },
+ { IOCTL_NFCSE_SET_ROUTING_TABLE, sizeof(SECURE_ELEMENT_ROUTING_TABLE), 0, &CQueue::OnSESetRoutingTable },
+ { IOCTL_NFCSE_HCE_REMOTE_RECV, 0, sizeof(DWORD), &CQueue::OnSEHCERemoteRecv },
+ { IOCTL_NFCSE_HCE_REMOTE_SEND, 2 * sizeof(USHORT) + 2, 0, &CQueue::OnSEHCERemoteSend },
+ { IOCTL_NFCSIM_TRIGGER_SEEVENT, SECURE_ELEMENT_EVENT_INFO_HEADER, 0, &CQueue::OnSETriggerEvent },
+ };
+
+ if (IsSERadioEnabled()) {
+ Status = DispatchMessage(DispatchTable, _countof(DispatchTable), Request, IoControlCode, InputBufferLength, OutputBufferLength);
+ }
+ }
+ break;
+
+ case IOCTL_SMARTCARD_EJECT:
+ case IOCTL_SMARTCARD_GET_LAST_ERROR:
+ case IOCTL_SMARTCARD_SET_ATTRIBUTE:
+ case IOCTL_SMARTCARD_SWALLOW:
+ case IOCTL_SMARTCARD_GET_ATTRIBUTE:
+ case IOCTL_SMARTCARD_GET_STATE:
+ case IOCTL_SMARTCARD_IS_ABSENT:
+ case IOCTL_SMARTCARD_IS_PRESENT:
+ case IOCTL_SMARTCARD_POWER:
+ case IOCTL_SMARTCARD_SET_PROTOCOL:
+ case IOCTL_SMARTCARD_TRANSMIT:
+ {
+ const DISPATCH_ENTRY DispatchTable[] =
+ {
+ { IOCTL_SMARTCARD_GET_ATTRIBUTE, sizeof(DWORD), 0, &CQueue::OnSCGetAttribute },
+ { IOCTL_SMARTCARD_SET_ATTRIBUTE, sizeof(DWORD), 0, &CQueue::OnSCSetAttribute },
+ { IOCTL_SMARTCARD_GET_STATE, 0, sizeof(DWORD), &CQueue::OnSCGetState },
+ { IOCTL_SMARTCARD_POWER, sizeof(DWORD), 0, &CQueue::OnSCPower },
+ { IOCTL_SMARTCARD_SET_PROTOCOL, sizeof(DWORD), sizeof(DWORD), &CQueue::OnSCSetProtocol },
+ { IOCTL_SMARTCARD_IS_ABSENT, 0, 0, &CQueue::OnSCIsAbsent },
+ { IOCTL_SMARTCARD_IS_PRESENT, 0, 0, &CQueue::OnSCIsPresent },
+ { IOCTL_SMARTCARD_TRANSMIT, sizeof(SCARD_IO_REQUEST)+1, sizeof(SCARD_IO_REQUEST)+2, &CQueue::OnSCTransmit },
+ { IOCTL_SMARTCARD_GET_LAST_ERROR, 0, 0, &CQueue::OnSCGetLastError },
+ };
+
+ if (IsNfpRadioEnabled()) {
+ Status = DispatchMessage(DispatchTable, _countof(DispatchTable), Request, IoControlCode, InputBufferLength, OutputBufferLength);
+ }
+ }
+ break;
+
+ case IOCTL_NFCRM_SET_RADIO_STATE:
+ case IOCTL_NFCRM_QUERY_RADIO_STATE:
+ case IOCTL_NFCSERM_SET_RADIO_STATE:
+ case IOCTL_NFCSERM_QUERY_RADIO_STATE:
+ {
+ const DISPATCH_ENTRY DispatchTable[] =
+ {
+ { IOCTL_NFCRM_SET_RADIO_STATE, sizeof(NFCRM_SET_RADIO_STATE), 0, &CQueue::OnNfpSetRadioState },
+ { IOCTL_NFCRM_QUERY_RADIO_STATE, 0, sizeof(NFCRM_RADIO_STATE), &CQueue::OnNfpQueryRadioState },
+ };
+
+ Status = DispatchMessage(DispatchTable, _countof(DispatchTable), Request, IoControlCode, InputBufferLength, OutputBufferLength);
+ }
+ break;
+
+ default:
+ {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ break;
+ }
+ }
+
+ if (Status != STATUS_PENDING) {
+ TraceInfo("%!FUNC! Completing Request with Status %!STATUS!", Status);
+ WdfRequestComplete(Request, Status);
+ }
+
+ MethodReturnVoid();
+}
+
+BOOL CQueue::ValidateMessage(_In_ CFileObject *pFileObject, _In_ ULONG IoControlCode)
+{
+ switch (IoControlCode)
+ {
+ case IOCTL_NFP_GET_MAX_MESSAGE_BYTES:
+ case IOCTL_NFP_GET_KILO_BYTES_PER_SECOND:
+ {
+ return TRUE;
+ }
+
+ case IOCTL_NFP_DISABLE:
+ case IOCTL_NFP_ENABLE:
+ {
+ return (pFileObject->IsPublication() || pFileObject->IsSubscription());
+ }
+
+ case IOCTL_NFP_SET_PAYLOAD:
+ case IOCTL_NFP_GET_NEXT_TRANSMITTED_MESSAGE:
+ {
+ return pFileObject->IsPublication();
+ }
+
+ case IOCTL_NFP_GET_NEXT_SUBSCRIBED_MESSAGE:
+ {
+ return pFileObject->IsSubscription();
+ }
+
+ case IOCTL_NFCSE_GET_NFCC_CAPABILITIES:
+ case IOCTL_NFCSE_ENUM_ENDPOINTS:
+ {
+ return TRUE;
+ }
+
+ case IOCTL_NFCSE_GET_NEXT_EVENT:
+ case IOCTL_NFCSE_SUBSCRIBE_FOR_EVENT:
+ {
+ return pFileObject->IsSecureElementEvent();
+ }
+
+ case IOCTL_NFCSE_GET_ROUTING_TABLE:
+ case IOCTL_NFCSE_SET_ROUTING_TABLE:
+ case IOCTL_NFCSE_HCE_REMOTE_SEND:
+ case IOCTL_NFCSE_HCE_REMOTE_RECV:
+ case IOCTL_NFCSE_SET_CARD_EMULATION_MODE:
+ {
+ return pFileObject->IsSecureElementManager();
+ }
+
+ case IOCTL_SMARTCARD_EJECT:
+ case IOCTL_SMARTCARD_GET_LAST_ERROR:
+ case IOCTL_SMARTCARD_SET_ATTRIBUTE:
+ case IOCTL_SMARTCARD_SWALLOW:
+ case IOCTL_SMARTCARD_GET_ATTRIBUTE:
+ case IOCTL_SMARTCARD_GET_STATE:
+ case IOCTL_SMARTCARD_IS_ABSENT:
+ case IOCTL_SMARTCARD_IS_PRESENT:
+ case IOCTL_SMARTCARD_POWER:
+ case IOCTL_SMARTCARD_SET_PROTOCOL:
+ case IOCTL_SMARTCARD_TRANSMIT:
+ {
+ return pFileObject->IsSmartCardReader();
+ }
+
+ case IOCTL_NFCRM_SET_RADIO_STATE:
+ case IOCTL_NFCRM_QUERY_RADIO_STATE:
+ {
+ return pFileObject->IsRoleRadioManager();
+ }
+
+ case IOCTL_NFCSIM_BEGIN_PROXIMITY:
+ case IOCTL_NFCSIM_TRIGGER_SEEVENT:
+ {
+ return pFileObject->IsRoleSimulation();
+ }
+ }
+
+ return FALSE;
+}
+
+NTSTATUS
+CQueue::DispatchMessage(
+ _In_reads_(TableEntries) const DISPATCH_ENTRY rgDispatchTable[],
+ _In_ DWORD TableEntries,
+ _In_ WDFREQUEST Request,
+ _In_ ULONG IoControlCode,
+ _In_ size_t InputBufferLength,
+ _In_ size_t OutputBufferLength
+ )
+{
+ NTSTATUS Status = STATUS_NOT_SUPPORTED;
+ PVOID InputBuffer = nullptr;
+ PVOID OutputBuffer = nullptr;
+ CFileObject *pFileObject = GetFileObject(WdfRequestGetFileObject(Request));
+
+ for (DWORD TableEntry = 0; TableEntry < TableEntries; TableEntry++) {
+ if (rgDispatchTable[TableEntry].IoControlCode != IoControlCode)
+ continue;
+
+ if (InputBufferLength >= rgDispatchTable[TableEntry].MinInputBufferLength &&
+ OutputBufferLength >= rgDispatchTable[TableEntry].MinOutputBufferLength) {
+ if (InputBufferLength != 0) {
+ Status = WdfRequestRetrieveInputBuffer(Request, 0, &InputBuffer, nullptr);
+ NT_ASSERT(NT_SUCCESS(Status));
+ }
+
+ if (OutputBufferLength != 0) {
+ Status = WdfRequestRetrieveOutputBuffer(Request, 0, &OutputBuffer, nullptr);
+ NT_ASSERT(NT_SUCCESS(Status));
+ }
+
+ if (ValidateMessage(pFileObject, IoControlCode)) {
+ Status = (this->*rgDispatchTable[TableEntry].DispatchHandler)(
+ pFileObject,
+ Request,
+ InputBuffer,
+ InputBufferLength,
+ OutputBuffer,
+ OutputBufferLength);
+ }
+ else {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ }
+ }
+ else {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ break;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+CQueue::OnNfpEnable(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = pFileObject->Enable();
+
+Exit:
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnNfpDisable(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = pFileObject->Disable();
+
+Exit:
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnNfpSetPayload(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+
+ if (OutputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (InputBufferLength > MaxCbPayload) {
+ Status = STATUS_INVALID_BUFFER_SIZE;
+ goto Exit;
+ }
+
+ Status = pFileObject->SetPayload((DWORD)InputBufferLength, (PBYTE)InputBuffer);
+
+ if (NT_SUCCESS(Status)) {
+ MESSAGE* pMessage = new MESSAGE();
+
+ if (pMessage != nullptr) {
+ pMessage->Initialize(pFileObject->GetType(), pFileObject->GetSize(), pFileObject->GetPayload());
+
+ EnterCriticalSection(&m_ConnectionLock);
+
+ for (LIST_ENTRY* pEntry = m_ConnectionList.Flink;
+ pEntry != &m_ConnectionList;
+ pEntry = pEntry->Flink) {
+ CConnection* pConnection = CConnection::FromListEntry(pEntry);
+
+ if (SUCCEEDED(pConnection->TransmitMessage(pMessage))) {
+ pFileObject->HandleMessageTransmitted();
+ }
+ }
+ LeaveCriticalSection(&m_ConnectionLock);
+
+ EnterCriticalSection(&m_PubsLock);
+ InsertHeadList(&m_PubsList, pFileObject->GetListEntry());
+ LeaveCriticalSection(&m_PubsLock);
+
+ delete pMessage;
+ }
+ else {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+Exit:
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnNfpGetNextSubscribedMessage(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fCompleteRequest = TRUE;
+
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = pFileObject->GetNextSubscribedMessage(Request);
+ fCompleteRequest = !NT_SUCCESS(Status);
+
+Exit:
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnNfpGetNextTransmittedMessage(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fCompleteRequest = TRUE;
+
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (OutputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = pFileObject->GetNextTransmittedMessage(Request);
+ fCompleteRequest = !NT_SUCCESS(Status);
+
+Exit:
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnNfpGetMaxMessageBytes(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fCompleteRequest = TRUE;
+ DWORD *pcbMaxPayload = (DWORD*)OutputBuffer;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ //
+ // Since the output buffer has already been validated
+ // to contain 4 bytes, we know we can safely make this assumption
+ //
+ _Analysis_assume_(sizeof(DWORD) <= OutputBufferLength);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ *pcbMaxPayload = MaxCbPayload;
+ WdfRequestCompleteWithInformation(Request, Status, sizeof(DWORD));
+ fCompleteRequest = FALSE;
+
+Exit:
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnNfpGetTransmissionRateKbps(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fCompleteRequest = TRUE;
+ DWORD *pdwKilobytesPerSecond = (DWORD*)OutputBuffer;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ //
+ // Since the output buffer has already been validated
+ // to contain 4 bytes, we know we can safely make this assumption
+ //
+ _Analysis_assume_(sizeof(DWORD) <= OutputBufferLength);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ *pdwKilobytesPerSecond = KilobytesPerSecond;
+ WdfRequestCompleteWithInformation(Request, Status, sizeof(DWORD));
+ fCompleteRequest = FALSE;
+
+Exit:
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnNfpBeginProximity(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ BEGIN_PROXIMITY_ARGS *pArgs = (BEGIN_PROXIMITY_ARGS*)InputBuffer;
+
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+
+ //
+ // Since the input buffer has already been validated
+ // for input buffer length so we know we can safely make this assumption
+ //
+ _Analysis_assume_(sizeof(BEGIN_PROXIMITY_ARGS) <= InputBufferLength);
+
+ if (OutputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = pFileObject->BeginProximity(pArgs, this);
+
+Exit:
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnNfpSetRadioState(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ PNFCRM_SET_RADIO_STATE pRadioState = (PNFCRM_SET_RADIO_STATE)InputBuffer;
+ BOOLEAN NfpRadioState;
+ DECLARE_CONST_UNICODE_STRING(SCNamespace, SMARTCARD_READER_NAMESPACE);
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+
+ _Analysis_assume_(sizeof(NFCRM_SET_RADIO_STATE) <= InputBufferLength);
+
+ EnterCriticalSection(&m_RadioLock);
+
+ if (OutputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (pRadioState->SystemStateUpdate) {
+ m_NfpRadioOffSystemOverride = !pRadioState->MediaRadioOn;
+ }
+ else {
+ //
+ // Since the request is modifying the radio state independent of the
+ // system state, set the system state override to FALSE
+ //
+ m_NfpRadioOffSystemOverride = FALSE;
+ m_NfpRadioOffPolicyOverride = !pRadioState->MediaRadioOn;
+ }
+
+ NfpRadioState = !m_NfpRadioOffSystemOverride && !m_NfpRadioOffPolicyOverride;
+
+ if (NfpRadioState == m_NfpRadioState) {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ goto Exit;
+ }
+
+ if (NfpRadioState) {
+ if (!m_NfpInterfaceCreated) {
+ // Register for Proximity interface
+ Status = WdfDeviceCreateDeviceInterface(
+ WdfIoQueueGetDevice(m_Queue),
+ (LPGUID) &GUID_DEVINTERFACE_NFP,
+ nullptr);
+
+ if (!NT_SUCCESS(Status)) {
+ TraceInfo("WdfDeviceCreateDeviceInterface failed with Status %!STATUS!", Status);
+ goto Exit;
+ }
+
+ m_NfpInterfaceCreated = TRUE;
+ }
+
+ WdfDeviceSetDeviceInterfaceState(
+ WdfIoQueueGetDevice(m_Queue),
+ (LPGUID) &GUID_DEVINTERFACE_NFP,
+ nullptr,
+ TRUE);
+
+ if (!m_ScInterfaceCreated) {
+ // Register for Smart Card interface
+ Status = WdfDeviceCreateDeviceInterface(
+ WdfIoQueueGetDevice(m_Queue),
+ (LPGUID) &GUID_DEVINTERFACE_SMARTCARD_READER,
+ &SCNamespace);
+
+ if (!NT_SUCCESS(Status)) {
+ TraceInfo("WdfDeviceCreateDeviceInterface failed with Status %!STATUS!", Status);
+ goto Exit;
+ }
+
+ m_ScInterfaceCreated = TRUE;
+ }
+
+ WdfDeviceSetDeviceInterfaceState(
+ WdfIoQueueGetDevice(m_Queue),
+ (LPGUID) &GUID_DEVINTERFACE_SMARTCARD_READER,
+ &SCNamespace,
+ TRUE);
+ }
+ else {
+ if (m_NfpInterfaceCreated) {
+ WdfDeviceSetDeviceInterfaceState(
+ WdfIoQueueGetDevice(m_Queue),
+ (LPGUID) &GUID_DEVINTERFACE_NFP,
+ nullptr,
+ FALSE);
+ }
+
+ if (m_ScInterfaceCreated) {
+ WdfDeviceSetDeviceInterfaceState(
+ WdfIoQueueGetDevice(m_Queue),
+ (LPGUID) &GUID_DEVINTERFACE_SMARTCARD_READER,
+ &SCNamespace,
+ FALSE);
+ }
+ }
+
+ m_NfpRadioState = NfpRadioState;
+
+Exit:
+ WriteSettingsToRegistry();
+ LeaveCriticalSection(&m_RadioLock);
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnNfpQueryRadioState(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fCompleteRequest = TRUE;
+ PNFCRM_RADIO_STATE pRadioState = (PNFCRM_RADIO_STATE)OutputBuffer;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ _Analysis_assume_(sizeof(NFCRM_RADIO_STATE) <= OutputBufferLength);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ pRadioState->MediaRadioOn = IsNfpRadioEnabled();
+ WdfRequestCompleteWithInformation(Request, Status, sizeof(NFCRM_RADIO_STATE));
+ fCompleteRequest = FALSE;
+
+Exit:
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSEEnumEndpoints(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fCompleteRequest = TRUE;
+ SECURE_ELEMENT_ENDPOINT_INFO rgEndpointInfo[MaxSecureElements] = {};
+ SECURE_ELEMENT_ENDPOINT_LIST *pEndpointList = (SECURE_ELEMENT_ENDPOINT_LIST*)OutputBuffer;
+ DWORD cbOutputBuffer = 0;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(InputBuffer);
+
+ //
+ // Since the output buffer has already been validated
+ // for output buffer length so we know we can safely make this assumption
+ //
+ _Analysis_assume_(sizeof(DWORD) <= OutputBufferLength);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ pEndpointList->NumberOfEndpoints = 0;
+
+ for (LIST_ENTRY* pEntry = m_SecureElementList.Flink;
+ pEntry != &m_SecureElementList && pEndpointList->NumberOfEndpoints < _countof(rgEndpointInfo);
+ pEntry = pEntry->Flink) {
+ SECURE_ELEMENT_ENDPOINT_INFO Info;
+
+ Info.guidSecureElementId = CSecureElement::FromListEntry(pEntry)->GetIdentifier();
+ Info.eSecureElementType = CSecureElement::FromListEntry(pEntry)->GetType();
+
+ rgEndpointInfo[pEndpointList->NumberOfEndpoints++] = Info;
+ }
+
+ cbOutputBuffer = sizeof(DWORD);
+
+ if ((cbOutputBuffer + (pEndpointList->NumberOfEndpoints * sizeof(SECURE_ELEMENT_ENDPOINT_INFO))) <= OutputBufferLength) {
+ RtlCopyMemory(pEndpointList->EndpointList, rgEndpointInfo, pEndpointList->NumberOfEndpoints * sizeof(SECURE_ELEMENT_ENDPOINT_INFO));
+ cbOutputBuffer += (pEndpointList->NumberOfEndpoints * sizeof(SECURE_ELEMENT_ENDPOINT_INFO));
+ }
+ else {
+ // Returning this signals to the client to send a bigger buffer
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+
+ WdfRequestCompleteWithInformation(Request, Status, cbOutputBuffer);
+ fCompleteRequest = FALSE;
+
+Exit:
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSESubscribeForEvent(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ SECURE_ELEMENT_EVENT_SUBSCRIPTION_INFO *pInfo = (SECURE_ELEMENT_EVENT_SUBSCRIPTION_INFO*)InputBuffer;
+ CSecureElement *pSecureElement = nullptr;
+
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+
+ //
+ // Since the input buffer has already been validated
+ // for input buffer length so we know we can safely make this assumption
+ //
+ _Analysis_assume_(sizeof(SECURE_ELEMENT_EVENT_SUBSCRIPTION_INFO) <= InputBufferLength);
+
+ if (OutputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (IsEqualGUID(pInfo->guidSecureElementId, GUID_NULL) ||
+ NT_SUCCESS(Status = GetSecureElementObject(pInfo->guidSecureElementId, &pSecureElement))) {
+ Status = pFileObject->SubscribeForEvent(pInfo->guidSecureElementId, pInfo->eEventType);
+
+ if (NT_SUCCESS(Status)) {
+ EnterCriticalSection(&m_SEEventsLock);
+ InsertHeadList(&m_SEEventsList, pFileObject->GetListEntry());
+ LeaveCriticalSection(&m_SEEventsLock);
+ }
+ }
+
+Exit:
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSEGetNextEvent(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fCompleteRequest = TRUE;
+
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = pFileObject->GetNextSecureElementPayload(Request);
+ fCompleteRequest = !NT_SUCCESS(Status);
+
+Exit:
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSESetCardEmulationMode(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ SECURE_ELEMENT_SET_CARD_EMULATION_MODE_INFO *pMode = (SECURE_ELEMENT_SET_CARD_EMULATION_MODE_INFO*)InputBuffer;
+ CSecureElement *pSecureElement = nullptr;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+
+ //
+ // Since the input buffer has already been validated
+ // for input buffer length so we know we can safely make this assumption
+ //
+ _Analysis_assume_(sizeof(SECURE_ELEMENT_SET_CARD_EMULATION_MODE_INFO) <= InputBufferLength);
+
+ if (OutputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = GetSecureElementObject(pMode->guidSecureElementId, &pSecureElement);
+
+ if (NT_SUCCESS(Status)) {
+ Status = pSecureElement->SetEmulationMode(pMode->eMode);
+ }
+
+Exit:
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSETriggerEvent(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ SECURE_ELEMENT_EVENT_INFO *pInfo = (SECURE_ELEMENT_EVENT_INFO*)InputBuffer;
+ CSecureElement *pSecureElement = nullptr;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+
+ //
+ // Since the input buffer has already been validated
+ // for input buffer length so we know we can safely make this assumption
+ //
+ _Analysis_assume_(SECURE_ELEMENT_EVENT_INFO_HEADER <= InputBufferLength);
+
+ if (OutputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (pInfo->guidSecureElementId == GUID_NULL) {
+ for (LIST_ENTRY* pEntry = m_SecureElementList.Flink;
+ pEntry != &m_SecureElementList;
+ pEntry = pEntry->Flink) {
+ pInfo->guidSecureElementId = CSecureElement::FromListEntry(pEntry)->GetIdentifier();
+ HandleSecureElementEvent(pInfo);
+ }
+ }
+ else {
+ Status = GetSecureElementObject(pInfo->guidSecureElementId, &pSecureElement);
+
+ if (NT_SUCCESS(Status)) {
+ HandleSecureElementEvent(pInfo);
+ }
+ }
+
+Exit:
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSEGetNfccCapabilities(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ PSECURE_ELEMENT_NFCC_CAPABILITIES pCapabilities = (PSECURE_ELEMENT_NFCC_CAPABILITIES)OutputBuffer;
+ BOOL fCompleteRequest = TRUE;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ //
+ // Since the input buffer has already been validated
+ // for input buffer length so we know we can safely make this assumption
+ //
+ _Analysis_assume_(sizeof(SECURE_ELEMENT_NFCC_CAPABILITIES) <= OutputBufferLength);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ pCapabilities->cbMaxRoutingTableSize = m_RoutingTable.MaxRoutingTableSize();
+ pCapabilities->IsAidRoutingSupported = m_RoutingTable.IsAidRoutingSupported();
+ pCapabilities->IsProtocolRoutingSupported = m_RoutingTable.IsProtocolRoutingSupported();
+ pCapabilities->IsTechRoutingSupported = m_RoutingTable.IsTechRoutingSupported();
+
+ WdfRequestCompleteWithInformation(Request, Status, sizeof(SECURE_ELEMENT_NFCC_CAPABILITIES));
+ fCompleteRequest = FALSE;
+
+Exit:
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSESetRoutingTable(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ PSECURE_ELEMENT_ROUTING_TABLE pRoutingTable = (PSECURE_ELEMENT_ROUTING_TABLE)InputBuffer;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ //
+ // Since the input buffer has already been validated
+ // for input buffer length so we know we can safely make this assumption
+ //
+ _Analysis_assume_(sizeof(SECURE_ELEMENT_ROUTING_TABLE) <= InputBufferLength);
+
+ if (pRoutingTable->NumberOfEntries == 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if ((sizeof(SECURE_ELEMENT_ROUTING_TABLE) + (pRoutingTable->NumberOfEntries - 1) * sizeof(SECURE_ELEMENT_ROUTING_TABLE_ENTRY)) < InputBufferLength) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = m_RoutingTable.SetRoutingTable(pRoutingTable);
+
+Exit:
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSEGetRoutingTable(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fCompleteRequest = TRUE;
+ DWORD cbOutputBuffer = 0;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(InputBuffer);
+
+ //
+ // Since the output buffer has already been validated
+ // for output buffer length so we know we can safely make this assumption
+ //
+ _Analysis_assume_(sizeof(DWORD) <= OutputBufferLength);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = m_RoutingTable.GetRoutingTable(OutputBuffer, OutputBufferLength, &cbOutputBuffer);
+ WdfRequestCompleteWithInformation(Request, Status, cbOutputBuffer);
+ fCompleteRequest = FALSE;
+
+Exit:
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSEHCERemoteRecv(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ GUID guidSecureElementId;
+ BOOL fCompleteRequest = TRUE;
+
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (!NT_SUCCESS(GetSecureElementId(DeviceHost, &guidSecureElementId))) {
+ Status = STATUS_NOT_SUPPORTED;
+ goto Exit;
+ }
+
+ Status = pFileObject->GetNextSecureElementPayload(Request);
+ fCompleteRequest = !NT_SUCCESS(Status);
+
+Exit:
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSEHCERemoteSend(
+ _In_ CFileObject *pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ GUID guidSecureElementId;
+ MESSAGE* pMessage = nullptr;
+ PSECURE_ELEMENT_HCE_DATA_PACKET pDataPacket = (PSECURE_ELEMENT_HCE_DATA_PACKET)InputBuffer;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+
+ //
+ // Since the input buffer has already been validated
+ // for input buffer length so we know we can safely make this assumption
+ //
+ _Analysis_assume_(2 * sizeof(USHORT) + 2 <= InputBufferLength);
+
+ EnterCriticalSection(&m_pHCEConnectionLock);
+
+ if (OutputBufferLength != 0 ||
+ pDataPacket->bConnectionId != m_HCEConnectionId) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (pDataPacket->cbPayload > MaxCbPayload) {
+ Status = STATUS_INVALID_BUFFER_SIZE;
+ goto Exit;
+ }
+
+ if (!NT_SUCCESS(GetSecureElementId(DeviceHost, &guidSecureElementId))) {
+ Status = STATUS_NOT_SUPPORTED;
+ goto Exit;
+ }
+
+ if (m_pHCEConnection == nullptr) {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ goto Exit;
+ }
+
+ pMessage = new MESSAGE();
+
+ if (pMessage == nullptr) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ pMessage->Initialize(HCE_MESSAGE_TYPE_TRANSMIT, pDataPacket->cbPayload, pDataPacket->pbPayload);
+
+ if (FAILED(m_pHCEConnection->TransmitMessage(pMessage))) {
+ Status = STATUS_DATA_ERROR;
+ goto Exit;
+ }
+
+Exit:
+ SAFE_DELETE(pMessage);
+ LeaveCriticalSection(&m_pHCEConnectionLock);
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSCGetLastError(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ DWORD *pdwError = (DWORD*)OutputBuffer;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ _Analysis_assume_(sizeof(DWORD) <= OutputBufferLength);
+
+ *pdwError = STATUS_SUCCESS;
+ WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, sizeof(DWORD));
+
+ MethodReturn(STATUS_PENDING, "Status = %!STATUS!", STATUS_SUCCESS);
+}
+
+NTSTATUS
+CQueue::OnSCGetAttribute(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fCompleteRequest = TRUE;
+ DWORD *pdwAttributeId = (DWORD*)InputBuffer;
+ DWORD cbOutputBuffer = (DWORD)OutputBufferLength;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+
+ _Analysis_assume_(sizeof(DWORD) <= InputBufferLength);
+ _Analysis_assume_(sizeof(DWORD) <= OutputBufferLength);
+
+ Status = m_SmartCardReader.GetAttribute(*pdwAttributeId, (PBYTE)OutputBuffer, &cbOutputBuffer);
+
+ if (NT_SUCCESS(Status)) {
+ WdfRequestCompleteWithInformation(Request, Status, cbOutputBuffer);
+ fCompleteRequest = FALSE;
+ }
+
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSCSetAttribute(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ DWORD *pdwAttributeId = (DWORD*)InputBuffer;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ _Analysis_assume_(sizeof(DWORD) <= InputBufferLength);
+
+ Status = m_SmartCardReader.SetAttribute(*pdwAttributeId);
+
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSCGetState(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ DWORD *pdwState = (DWORD*)OutputBuffer;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ _Analysis_assume_(sizeof(DWORD) <= OutputBufferLength);
+
+ *pdwState = m_SmartCardReader.GetState();
+ WdfRequestCompleteWithInformation(Request, Status, sizeof(DWORD));
+
+ MethodReturn(STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSCIsAbsent(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (OutputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = m_SmartCardReader.IsAbsent(Request);
+
+Exit:
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSCIsPresent(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(InputBuffer);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+
+ if (InputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (OutputBufferLength != 0) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = m_SmartCardReader.IsPresent(Request);
+
+Exit:
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSCPower(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ DWORD *pdwPower = (DWORD*)InputBuffer;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(Request);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(OutputBuffer);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ _Analysis_assume_(sizeof(DWORD) <= InputBufferLength);
+
+ Status = m_SmartCardReader.SetPower(*pdwPower);
+
+ MethodReturn(Status, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSCSetProtocol(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fCompleteRequest = TRUE;
+ DWORD *pdwProtocol = (DWORD*)InputBuffer;
+ DWORD *pdwSelectedProtocol = (DWORD*)OutputBuffer;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ _Analysis_assume_(sizeof(DWORD) <= InputBufferLength);
+ _Analysis_assume_(sizeof(DWORD) <= OutputBufferLength);
+
+ Status = m_SmartCardReader.SetProtocol(*pdwProtocol, pdwSelectedProtocol);
+
+ if (NT_SUCCESS(Status)) {
+ WdfRequestCompleteWithInformation(Request, Status, sizeof(DWORD));
+ fCompleteRequest = FALSE;
+ }
+
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+NTSTATUS
+CQueue::OnSCTransmit(
+ _In_ CFileObject* pFileObject,
+ _In_ WDFREQUEST Request,
+ _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
+ _In_ size_t InputBufferLength,
+ _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
+ _In_ size_t OutputBufferLength
+ )
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fCompleteRequest = TRUE;
+ size_t BytesTransferred = 0;
+
+ UNREFERENCED_PARAMETER(pFileObject);
+
+ //
+ // Since the input and buffer buffer length has already been validated
+ // for input buffer length we need to have atleast one byte to transfer (discarding the header)
+ // for output buffer length we should atleast be able to store status codes SW1+SW2
+ //
+ _Analysis_assume_(sizeof(SCARD_IO_REQUEST)+1 <= InputBufferLength);
+ _Analysis_assume_(sizeof(SCARD_IO_REQUEST)+2 <= OutputBufferLength);
+
+ Status = m_SmartCardReader.Transmit((PBYTE)InputBuffer, InputBufferLength, (PBYTE)OutputBuffer, OutputBufferLength, &BytesTransferred);
+
+ if (NT_SUCCESS(Status)) {
+ WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, BytesTransferred);
+ fCompleteRequest = FALSE;
+ }
+
+ MethodReturn(fCompleteRequest ? Status : STATUS_PENDING, "Status = %!STATUS!", Status);
+}
+
+void CQueue::ValidateAccept(_In_ SOCKET Socket, _In_ GUID* pMagicPacket)
+{
+ MethodEntry("...");
+
+ CConnection* pConnection;
+
+ if (CConnection::Create(this, &pConnection)) {
+ // 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 CQueue::ConnectionEstablished(_In_ CConnection* pConnection)
+{
+ MethodEntry("...");
+
+ if (pConnection->GetConnectionType() == CONNECTION_TYPE_P2P) {
+ EnterCriticalSection(&m_ConnectionLock);
+
+ if (IsListEmpty(&m_ConnectionList)) {
+ HandleArrivalEvent();
+ }
+
+ InsertHeadList(&m_ConnectionList, pConnection->GetListEntry());
+ LeaveCriticalSection(&m_ConnectionLock);
+
+ MESSAGE* pMessage = new MESSAGE();
+
+ if (pMessage != nullptr) {
+ EnterCriticalSection(&m_PubsLock);
+
+ for (LIST_ENTRY* pEntry = m_PubsList.Flink;
+ pEntry != &m_PubsList;
+ pEntry = pEntry->Flink) {
+ CFileObject* pPub = CFileObject::FromListEntry(pEntry);
+
+ if (pPub->IsEnabled()) {
+ pMessage->Initialize(pPub->GetType(), pPub->GetSize(), pPub->GetPayload());
+
+ if (SUCCEEDED(pConnection->TransmitMessage(pMessage))) {
+ pPub->HandleMessageTransmitted();
+ }
+ }
+ }
+ LeaveCriticalSection(&m_PubsLock);
+
+ delete pMessage;
+ }
+ }
+ else if (pConnection->GetConnectionType() == CONNECTION_TYPE_TAG) {
+ m_SmartCardReader.CardArrived(pConnection);
+ }
+ else if (pConnection->GetConnectionType() == CONNECTION_TYPE_HCE) {
+ SECURE_ELEMENT_EVENT_INFO_AND_PAYLOAD(sizeof(SECURE_ELEMENT_HCE_ACTIVATION_PAYLOAD)) EventInfo;
+
+ if (NT_SUCCESS(GetSecureElementId(DeviceHost, &EventInfo.Info.guidSecureElementId))) {
+ EnterCriticalSection(&m_pHCEConnectionLock);
+
+ if (m_pHCEConnection == nullptr) {
+ PSECURE_ELEMENT_HCE_ACTIVATION_PAYLOAD pbEventPayload = NULL;
+
+ m_pHCEConnection = pConnection;
+ m_HCEConnectionId++;
+
+ EventInfo.Info.eEventType = HceActivated;
+ EventInfo.Info.cbEventData = sizeof(SECURE_ELEMENT_HCE_ACTIVATION_PAYLOAD);
+
+ pbEventPayload = (PSECURE_ELEMENT_HCE_ACTIVATION_PAYLOAD)EventInfo.Info.pbEventData;
+
+ pbEventPayload->bConnectionId = m_HCEConnectionId;
+ pbEventPayload->eRfTechType = NFC_RF_TECHNOLOGY_A;
+ pbEventPayload->eRfProtocolType = PROTOCOL_ISO_DEP;
+
+ HandleSecureElementEvent(&EventInfo.Info);
+ }
+
+ LeaveCriticalSection(&m_pHCEConnectionLock);
+ }
+ }
+
+ MethodReturnVoid();
+}
+
+BOOL CQueue::ConnectionTerminated(_In_ CConnection* pConnection)
+{
+ MethodEntry("pConnection = 0x%p", pConnection);
+
+ BOOL fConnectionDeleted = FALSE;
+
+ if (pConnection->GetConnectionType() == CONNECTION_TYPE_P2P) {
+ LIST_ENTRY* pRemoveListEntry = pConnection->GetListEntry();
+
+ EnterCriticalSection(&m_ConnectionLock);
+
+ for (LIST_ENTRY* pEntry = m_ConnectionList.Flink;
+ pEntry != &m_ConnectionList;
+ pEntry = pEntry->Flink) {
+ if (pEntry == pRemoveListEntry) {
+ RemoveEntryList(pEntry);
+ break;
+ }
+ }
+
+ if (IsListEmpty(&m_ConnectionList)) {
+ HandleRemovalEvent();
+ }
+ LeaveCriticalSection(&m_ConnectionLock);
+
+ if (pConnection->IsInboundConnection()) {
+ delete pConnection;
+ fConnectionDeleted = TRUE;
+ }
+ }
+ else if (pConnection->GetConnectionType() == CONNECTION_TYPE_TAG) {
+ fConnectionDeleted = m_SmartCardReader.CardRemoved(pConnection);
+ }
+ else if (pConnection->GetConnectionType() == CONNECTION_TYPE_HCE) {
+ SECURE_ELEMENT_EVENT_INFO_AND_PAYLOAD(sizeof(USHORT)) EventInfo;
+
+ if (NT_SUCCESS(GetSecureElementId(DeviceHost, &EventInfo.Info.guidSecureElementId))) {
+ EnterCriticalSection(&m_pHCEConnectionLock);
+
+ if (m_pHCEConnection != nullptr) {
+ m_pHCEConnection = nullptr;
+
+ EventInfo.Info.eEventType = HceDeactivated;
+ EventInfo.Info.cbEventData = sizeof(USHORT);
+
+ *((USHORT*)EventInfo.Info.pbEventData) = m_HCEConnectionId;
+
+ HandleSecureElementEvent(&EventInfo.Info);
+ }
+ LeaveCriticalSection(&m_pHCEConnectionLock);
+ }
+ }
+
+ MethodReturnBool(fConnectionDeleted);
+}
+
+void CQueue::HandleArrivalEvent()
+{
+ MethodEntry("void");
+
+ EnterCriticalSection(&m_SubsLock);
+
+ for (LIST_ENTRY* pEntry = m_ArrivalSubsList.Flink;
+ pEntry != &m_ArrivalSubsList;
+ pEntry = pEntry->Flink) {
+ CFileObject::FromListEntry(pEntry)->HandleArrivalEvent();
+ }
+ LeaveCriticalSection(&m_SubsLock);
+
+ MethodReturnVoid();
+}
+
+void CQueue::HandleRemovalEvent()
+{
+ MethodEntry("void");
+
+ EnterCriticalSection(&m_SubsLock);
+
+ for (LIST_ENTRY* pEntry = m_DepartureSubsList.Flink;
+ pEntry != &m_DepartureSubsList;
+ pEntry = pEntry->Flink) {
+ CFileObject::FromListEntry(pEntry)->HandleRemovalEvent();
+ }
+ LeaveCriticalSection(&m_SubsLock);
+
+ MethodReturnVoid();
+}
+
+void CQueue::HandleReceivedMessage(_In_ CONNECTION_TYPE ConnType, _In_ MESSAGE* pMessage)
+{
+ MethodEntry("pMessage->m_szType = '%S'", pMessage->m_szType);
+
+ if (ConnType == CONNECTION_TYPE_P2P) {
+ if ((pMessage->m_cbPayload > 0) && (pMessage->m_cbPayload <= MaxCbPayload)) {
+ EnterCriticalSection(&m_SubsLock);
+
+ for (LIST_ENTRY* pEntry = m_SubsList.Flink; pEntry != &m_SubsList; pEntry = pEntry->Flink) {
+ CFileObject* pSub = CFileObject::FromListEntry(pEntry);
+ pSub->HandleReceivedMessage(pMessage->m_szType, pMessage->m_cbPayload, pMessage->m_Payload);
+ }
+ LeaveCriticalSection(&m_SubsLock);
+ }
+ }
+ else if (ConnType == CONNECTION_TYPE_TAG) {
+ m_SmartCardReader.MessageReceived(pMessage);
+ }
+ else if (ConnType == CONNECTION_TYPE_HCE) {
+ EnterCriticalSection(&m_SEManagerLock);
+
+ if (m_pSEManager != nullptr) {
+ m_pSEManager->HandleReceiveHcePacket((USHORT)m_HCEConnectionId, pMessage->m_cbPayload, pMessage->m_Payload);
+ }
+ LeaveCriticalSection(&m_SEManagerLock);
+ }
+
+ MethodReturnVoid();
+}
+
+void CQueue::HandleSecureElementEvent(SECURE_ELEMENT_EVENT_INFO *pInfo)
+{
+ MethodEntry("...");
+
+ CSecureElement *pSecureElement = nullptr;
+
+ if (NT_SUCCESS(GetSecureElementObject(pInfo->guidSecureElementId, &pSecureElement))) {
+ if (pSecureElement->GetEmulationMode() != EmulationOff) {
+ EnterCriticalSection(&m_SEEventsLock);
+
+ for (LIST_ENTRY* pEntry = m_SEEventsList.Flink;
+ pEntry != &m_SEEventsList;
+ pEntry = pEntry->Flink) {
+ CFileObject::FromListEntry(pEntry)->HandleSecureElementEvent(pInfo);
+ }
+ LeaveCriticalSection(&m_SEEventsLock);
+ }
+ }
+
+ MethodReturnVoid();
+}
+
+void CQueue::EnumerateSecureElements()
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ WDFKEY KeyHandle = nullptr;
+ WDFCOLLECTION Collection = nullptr;
+ GUID SecureElementId;
+ UNICODE_STRING GuidString;
+ CSecureElement *pSecureElement = nullptr;
+
+ DECLARE_CONST_UNICODE_STRING(SEEndpointsKey, SE_ENDPOINTS_KEY);
+
+ Status = WdfDeviceOpenRegistryKey(
+ WdfIoQueueGetDevice(m_Queue),
+ PLUGPLAY_REGKEY_DEVICE,
+ KEY_READ,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &KeyHandle);
+
+ if (NT_SUCCESS(Status) && (KeyHandle != nullptr)) {
+ Status = WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &Collection);
+
+ if (NT_SUCCESS(Status) && (Collection != nullptr)) {
+ Status = WdfRegistryQueryMultiString(
+ KeyHandle,
+ &SEEndpointsKey,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ Collection);
+
+ if (NT_SUCCESS(Status)) {
+ ULONG Count = WdfCollectionGetCount(Collection);
+
+ for (ULONG Index = 0; Index < Count; Index++) {
+ WdfStringGetUnicodeString((WDFSTRING) WdfCollectionGetItem(Collection, Index), &GuidString);
+
+ if (SUCCEEDED(CLSIDFromString(GuidString.Buffer, &SecureElementId)) &&
+ (pSecureElement = new CSecureElement(SecureElementId, IsEqualGUID(SecureElementId, GUID_DH_SECURE_ELEMENT) ? DeviceHost : External)) != nullptr) {
+ TraceInfo("Secure Element Id=%S Type=%d", GuidString.Buffer, pSecureElement->GetType());
+ InsertHeadList(&m_SecureElementList, pSecureElement->GetListEntry());
+ }
+ }
+ }
+
+ WdfObjectDelete(Collection);
+ }
+
+ WdfRegistryClose(KeyHandle);
+ }
+
+ MethodReturnVoid();
+}
+
+void CQueue::ReadSettingsFromRegistry()
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ WDFKEY KeyHandle = nullptr;
+ ULONG NfpRadioOffPolicyOverride = 0, NfpRadioOffSystemOverride = 0;
+
+ DECLARE_CONST_UNICODE_STRING(NfpRadioTurnedOffKey, NFP_RADIO_TURNED_OFF_KEY);
+ DECLARE_CONST_UNICODE_STRING(NfpRadioFlightModeKey, NFP_RADIO_FLIGHT_MODE_KEY);
+
+ Status = WdfDeviceOpenRegistryKey(
+ WdfIoQueueGetDevice(m_Queue),
+ PLUGPLAY_REGKEY_DEVICE | WDF_REGKEY_DEVICE_SUBKEY,
+ KEY_READ,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &KeyHandle);
+
+ if (NT_SUCCESS(Status) && (KeyHandle != nullptr)) {
+ Status = WdfRegistryQueryULong(
+ KeyHandle,
+ &NfpRadioTurnedOffKey,
+ &NfpRadioOffPolicyOverride);
+
+ if (NT_SUCCESS(Status)) {
+ TraceInfo("%S = %d", NFP_RADIO_TURNED_OFF_KEY, NfpRadioOffPolicyOverride);
+ m_NfpRadioOffPolicyOverride = (NfpRadioOffPolicyOverride != 0);
+ }
+
+ Status = WdfRegistryQueryULong(
+ KeyHandle,
+ &NfpRadioFlightModeKey,
+ &NfpRadioOffSystemOverride);
+
+ if (NT_SUCCESS(Status)) {
+ TraceInfo("%S = %d", NFP_RADIO_FLIGHT_MODE_KEY, NfpRadioOffSystemOverride);
+ m_NfpRadioOffSystemOverride = (NfpRadioOffSystemOverride != 0);
+ }
+
+ m_NfpRadioState = !m_NfpRadioOffPolicyOverride && !m_NfpRadioOffSystemOverride;
+
+ WdfRegistryClose(KeyHandle);
+ }
+
+ MethodReturnVoid();
+}
+
+void CQueue::WriteSettingsToRegistry()
+{
+ MethodEntry("...");
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ WDFKEY KeyHandle = nullptr;
+
+ DECLARE_CONST_UNICODE_STRING(NfpRadioTurnedOffKey, NFP_RADIO_TURNED_OFF_KEY);
+ DECLARE_CONST_UNICODE_STRING(NfpRadioFlightModeKey, NFP_RADIO_FLIGHT_MODE_KEY);
+
+ Status = WdfDeviceOpenRegistryKey(
+ WdfIoQueueGetDevice(m_Queue),
+ PLUGPLAY_REGKEY_DEVICE | WDF_REGKEY_DEVICE_SUBKEY,
+ GENERIC_ALL & ~(GENERIC_WRITE | KEY_CREATE_SUB_KEY | WRITE_DAC),
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &KeyHandle);
+
+ if (NT_SUCCESS(Status) && (KeyHandle != nullptr)) {
+ Status = WdfRegistryAssignULong(
+ KeyHandle,
+ &NfpRadioTurnedOffKey,
+ m_NfpRadioOffPolicyOverride);
+
+ if (NT_SUCCESS(Status)) {
+ TraceInfo("%S = %d successfully persisted", NFP_RADIO_TURNED_OFF_KEY, m_NfpRadioOffPolicyOverride);
+ }
+
+ Status = WdfRegistryAssignULong(
+ KeyHandle,
+ &NfpRadioFlightModeKey,
+ m_NfpRadioOffSystemOverride);
+
+ if (NT_SUCCESS(Status)) {
+ TraceInfo("%S = %d successfully persisted", NFP_RADIO_FLIGHT_MODE_KEY, m_NfpRadioOffSystemOverride);
+ }
+
+ WdfRegistryClose(KeyHandle);
+ }
+
+ MethodReturnVoid();
+}
+
+NTSTATUS CQueue::GetSecureElementObject(GUID &SecureElementId, CSecureElement **ppSecureElement)
+{
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ for (LIST_ENTRY* pEntry = m_SecureElementList.Flink;
+ pEntry != &m_SecureElementList;
+ pEntry = pEntry->Flink) {
+ if (SecureElementId == CSecureElement::FromListEntry(pEntry)->GetIdentifier()) {
+ *ppSecureElement = CSecureElement::FromListEntry(pEntry);
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ }
+
+ return Status;
+}
+
+NTSTATUS CQueue::GetSecureElementId(SECURE_ELEMENT_TYPE eType, GUID *pSecureElementId)
+{
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ *pSecureElementId = GUID_NULL;
+
+ for (LIST_ENTRY* pEntry = m_SecureElementList.Flink;
+ (pEntry != &m_SecureElementList);
+ pEntry = pEntry->Flink) {
+ if (CSecureElement::FromListEntry(pEntry)->GetType() == eType) {
+ *pSecureElementId = CSecureElement::FromListEntry(pEntry)->GetIdentifier();
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ }
+
+ return Status;
+}
+