From 085c2a4806ad07a26b63f9457142c0a5ce1c2bd4 Mon Sep 17 00:00:00 2001 From: Daniel Ayala Date: Tue, 24 Aug 2021 16:09:25 -0700 Subject: [PATCH 01/13] Cleaned original code --- .../PushNotificationChannel.cpp | 89 +++++++++++++++++-- .../PushNotificationChannel.h | 18 +++- .../PushNotificationReceivedEventArgs.cpp | 28 ++++-- .../PushNotificationReceivedEventArgs.h | 10 ++- .../NotificationsLongRunningProcess.idl | 12 +++ .../ForegroundSinkManager.cpp | 44 +++++++++ .../ForegroundSinkManager.h | 22 +++++ .../PushNotificationsLongRunningTask.vcxproj | 26 +++--- ...tificationsLongRunningTask.vcxproj.filters | 6 ++ .../platform.cpp | 19 +++- .../platform.h | 9 +- .../WindowsAppSDK_DLL.vcxproj | 16 ++-- .../PushNotificationsDemoApp/main.cpp | 11 ++- 13 files changed, 271 insertions(+), 39 deletions(-) create mode 100644 dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp create mode 100644 dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index e3d8ed743f..f2087f0f5d 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. #include "pch.h" +#include #include "PushNotificationChannel.h" #include "Microsoft.Windows.PushNotifications.PushNotificationChannel.g.cpp" #include @@ -22,14 +23,34 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { PushNotificationChannel::PushNotificationChannel(winrt::Windows::PushNotificationChannel const& channel): m_channel(channel) {} + PushNotificationChannel::~PushNotificationChannel() noexcept + { + try + { + if (!IsPackagedApp()) + { + char processName[1024]; + GetModuleFileNameExA(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])); + + wil::com_ptr notificationsLongRunningPlatform{ + wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; + + notificationsLongRunningPlatform->UnregisterForegroundActivator(this, processName); + } + } + CATCH_LOG() + } + winrt::Windows::Uri PushNotificationChannel::Uri() { return winrt::Windows::Uri{ m_channel.Uri() }; } + winrt::Windows::DateTime PushNotificationChannel::ExpirationTime() { return m_channel.ExpirationTime(); } + void PushNotificationChannel::Close() { try @@ -48,18 +69,72 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::event_token PushNotificationChannel::PushReceived(winrt::Windows::TypedEventHandler handler) { - return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) + if (IsPackagedApp()) // Should be !m_isBIAvailable <- just for testing { - auto strong = weak_self.get(); - if (strong) + return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) { - handler(*strong, winrt::make(args)); - }; - }); + auto strong = weak_self.get(); + if (strong) + { + handler(*strong, winrt::make(args)); + }; + }); + } + else + { + char processName[1024]; + GetModuleFileNameExA(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])); + + wil::com_ptr notificationsLongRunningPlatform{ + wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; + + THROW_IF_FAILED(notificationsLongRunningPlatform->RegisterForegroundActivator(this, processName)); + + return m_foregroundHandlers.add(handler); + } } void PushNotificationChannel::PushReceived(winrt::event_token const& token) noexcept { - m_channel.PushNotificationReceived(token); + if (IsPackagedApp()) + { + m_channel.PushNotificationReceived(token); + } + else + { + m_foregroundHandlers.remove(token); + } + } + + HRESULT __stdcall PushNotificationChannel::InvokeAll(byte* start, ULONG length) noexcept try + { + std::vector vec; + + for (int i = 0; (ULONG)i < length; i++) + { + vec.push_back(start[i]); + } + + com_array arr{ start, start + (length * sizeof(uint8_t)) }; + m_foregroundHandlers(*this, winrt::make(start, length)); + + return S_OK; + } + CATCH_RETURN() + + bool PushNotificationChannel::IsBackgroundTaskBuilderAvailable() + { + return winrt::Windows::Metadata::ApiInformation::IsMethodPresent(L"Windows.ApplicationModel.Background.BackgroundTaskBuilder", L"SetTaskEntryPointClsid"); + } + + // Determines if the caller should be treated as packaged app or not. + bool PushNotificationChannel::IsPackagedApp() + { + if (AppModel::Identity::IsPackagedProcess() && IsBackgroundTaskBuilderAvailable()) + { + return true; + } + + return false; } } diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h index 8349d8f6b8..fe01348ce7 100644 --- a/dev/PushNotifications/PushNotificationChannel.h +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -3,12 +3,19 @@ #pragma once #include "Microsoft.Windows.PushNotifications.PushNotificationChannel.g.h" +#include namespace winrt::Microsoft::Windows::PushNotifications::implementation { - struct PushNotificationChannel : PushNotificationChannelT + typedef winrt::Windows::Foundation::TypedEventHandler< + winrt::Microsoft::Windows::PushNotifications::PushNotificationChannel, + winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs> PushNotificationEventHandler; + + struct PushNotificationChannel : PushNotificationChannelT { PushNotificationChannel(winrt::Windows::Networking::PushNotifications::PushNotificationChannel const& channel); + ~PushNotificationChannel() noexcept; + winrt::Windows::Foundation::Uri Uri(); winrt::Windows::Foundation::DateTime ExpirationTime(); void Close(); @@ -16,11 +23,20 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::event_token PushReceived(winrt::Windows::Foundation::TypedEventHandler handler); void PushReceived(winrt::event_token const& token) noexcept; + // IWpnForegroundSink + HRESULT __stdcall InvokeAll(byte* start, ULONG length) noexcept; + private: + bool IsPackagedApp(); + bool IsBackgroundTaskBuilderAvailable(); + const winrt::Windows::Networking::PushNotifications::PushNotificationChannel m_channel{ nullptr }; + bool m_isBIAvailable = false; + winrt::event m_foregroundHandlers; }; } + namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation { struct PushNotificationChannel : PushNotificationChannelT diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp index 9db256b051..13754b09df 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp @@ -23,14 +23,31 @@ namespace winrt namespace winrt::Microsoft::Windows::PushNotifications::implementation { - PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::IBackgroundTaskInstance const& backgroundTask): m_backgroundTaskInstance(backgroundTask), m_rawNotification(backgroundTask.TriggerDetails().as().ContentBytes()) {} - - PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args): m_args(args), m_rawNotification(args.RawNotification().ContentBytes()) {} + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::IBackgroundTaskInstance const& backgroundTask): + m_backgroundTaskInstance(backgroundTask), + m_rawNotification(GetByteArrayFromBuffer(backgroundTask.TriggerDetails().as().ContentBytes())), + m_isBIAvailable(true) {} + + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args): + m_args(args), + m_rawNotification(GetByteArrayFromBuffer(args.RawNotification().ContentBytes())), + m_isBIAvailable(true) {} + + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(byte* payload, ULONG length): + m_rawNotification(payload), + m_length(length), + m_isBIAvailable(false) {} + + byte* PushNotificationReceivedEventArgs::GetByteArrayFromBuffer(winrt::Windows::Storage::Streams::IBuffer buffer) + { + auto rawNotificationData = buffer.data(); + m_length = buffer.Length(); + return rawNotificationData; + } winrt::com_array PushNotificationReceivedEventArgs::Payload() { - auto rawNotificationData = m_rawNotification.data(); - return { rawNotificationData, rawNotificationData + (m_rawNotification.Length() * sizeof(uint8_t)) }; + return { m_rawNotification, m_rawNotification + (m_length * sizeof(uint8_t)) }; } winrt::BackgroundTaskDeferral PushNotificationReceivedEventArgs::GetDeferral() @@ -58,6 +75,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); + // Also, we need to handle scenario for notifications coming from the LRP return m_args.Cancel(); } diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.h b/dev/PushNotifications/PushNotificationReceivedEventArgs.h index 017b1f2f08..fe1c49475f 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.h +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.h @@ -9,6 +9,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationReceivedEventArgs(winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance const& backgroundTask); PushNotificationReceivedEventArgs(winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs const& args); + PushNotificationReceivedEventArgs(byte* payload, ULONG length); com_array Payload(); winrt::Windows::ApplicationModel::Background::BackgroundTaskDeferral GetDeferral(); @@ -17,9 +18,16 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation bool Handled(); void Handled(bool value); + byte* GetByteArrayFromBuffer(winrt::Windows::Storage::Streams::IBuffer buffer); + private: - const winrt::Windows::Storage::Streams::IBuffer m_rawNotification{}; + + byte* m_rawNotification = nullptr; + const winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance m_backgroundTaskInstance{}; const winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs m_args = nullptr; + + ULONG m_length = 0; + bool m_isBIAvailable = false; }; } diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl b/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl index 64bc2f82ea..b96f42759a 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl +++ b/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl @@ -6,12 +6,24 @@ import "ocidl.idl"; #include "../PushNotifications-Constants.h" +[object] +[uuid(25604D55-9B17-426F-9D67-2B11B3A65598)] +[pointer_default(unique)] +interface IWpnForegroundSink : IUnknown +{ + HRESULT InvokeAll([in] byte* payload, [in] ULONG length); +}; + [object] [uuid(60FC21B2-B396-4D49-94F0-7555869FB93C)] [pointer_default(unique)] interface INotificationsLongRunningPlatform : IUnknown { HRESULT RegisterFullTrustApplication([in] LPCWSTR processName, [in] GUID remoteId, [out] GUID* appId); + + HRESULT RegisterForegroundActivator([in] IWpnForegroundSink* sink, [in] LPCSTR processName); + + HRESULT UnregisterForegroundActivator([in] IWpnForegroundSink* sink, [in] LPCSTR processName); }; [uuid(PUSHNOTIFICATIONS_LIBID_UUID)] diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp new file mode 100644 index 0000000000..e282d6e0b6 --- /dev/null +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp @@ -0,0 +1,44 @@ +#pragma once + +#include "pch.h" + +#include + + + +#include + +void ForegroundSinkManager::AddSink(LPCSTR processName, IWpnForegroundSink* sink) +{ + if (!m_foregroundMap.contains(processName)) + { + m_foregroundMap[processName] = std::unordered_set(); + } + + m_foregroundMap[processName].insert(sink); +} + +void ForegroundSinkManager::Remove(LPCSTR processName, IWpnForegroundSink* sink) +{ + THROW_HR_IF(E_INVALIDARG, !m_foregroundMap.contains(processName)); + + std::unordered_set sinks = m_foregroundMap[processName]; + sinks.erase(sink); + if (sinks.empty()) + { + m_foregroundMap.erase(processName); + } +} + +bool ForegroundSinkManager::InvokeForegroundHandlers(LPCSTR processName, byte* payload, ULONG payloadSize) +{ + std::unordered_set sinks = m_foregroundMap[processName]; + if (!m_foregroundMap.contains(processName)) + { + return false; + } + + std::unordered_set sinks2 = m_foregroundMap[processName]; + std::for_each(sinks.begin(), sinks.end(), [&](IWpnForegroundSink* sink) { sink->InvokeAll(payload, payloadSize); }); + return true; +} diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h new file mode 100644 index 0000000000..53625d141b --- /dev/null +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#include +#include +#include + +class ForegroundSinkManager +{ +public: + ForegroundSinkManager() = default; + + void AddSink(LPCSTR processName, IWpnForegroundSink* sink); + + void Remove(LPCSTR processName, IWpnForegroundSink* sink); + + bool InvokeForegroundHandlers(LPCSTR processName, byte* payload, ULONG payloadSize); + +private: + std::unordered_map> m_foregroundMap = {}; + +}; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj b/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj index d4fa8ab079..e9751fc85a 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj @@ -122,13 +122,13 @@ true WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp17 + stdcpp20 %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL Windows DebugFull - Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) @@ -139,7 +139,7 @@ true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp17 + stdcpp20 Guard %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL @@ -148,7 +148,7 @@ true true DebugFull - Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) @@ -157,13 +157,13 @@ true _DEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp17 + stdcpp20 %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL Windows DebugFull - Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) @@ -174,7 +174,7 @@ true NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp17 + stdcpp20 Guard %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL @@ -183,7 +183,7 @@ true true DebugFull - Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) @@ -192,13 +192,13 @@ true _DEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp17 + stdcpp20 %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL Windows DebugFull - Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) @@ -210,7 +210,7 @@ NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true Guard - stdcpp17 + stdcpp20 %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL @@ -218,10 +218,11 @@ true true DebugFull - Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + @@ -229,6 +230,7 @@ + diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj.filters b/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj.filters index 7b32be73d3..103525bc94 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj.filters +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj.filters @@ -27,6 +27,9 @@ Header Files + + Header Files + @@ -44,6 +47,9 @@ Source Files + + Source Files + diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp index a16f0f7c42..49927a3c23 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp @@ -18,7 +18,7 @@ void NotificationsLongRunningPlatformImpl::Initialize() // Schedule event signaling after 5 seconds. This is in case we don't have any apps to track in the LRP. // If we realize that we need to persist the LRP, timer should be canceled. m_shutdownTimerManager = std::make_unique(); - m_shutdownTimerManager->Setup(); + //m_shutdownTimerManager->Setup(); /* TODO: Verify registry and UDK list and make sure we have apps to be tracked */ @@ -55,3 +55,20 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterF return E_NOTIMPL; } +STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterForegroundActivator(/*[in]*/ IWpnForegroundSink* sink, /*[in]*/ LPCSTR processName) +{ + RETURN_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); + auto lock = m_lock.lock_exclusive(); + + m_foregroundSinkManager.AddSink(processName, sink); + return S_OK; +} + +STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::UnregisterForegroundActivator(/*[out]*/ IWpnForegroundSink* sink, /*[in]*/ LPCSTR processName) +{ + RETURN_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); + auto lock = m_lock.lock_exclusive(); + + m_foregroundSinkManager.Remove(processName, sink); + return S_OK; +} diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h index 99b353de1b..80887d9775 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h @@ -3,6 +3,7 @@ #include "../PushNotifications-Constants.h" #include "PlatformLifetimeTimerManager.h" +#include "ForegroundSinkManager.h" struct __declspec(uuid(PUSHNOTIFICATIONS_IMPL_CLSID_STRING)) NotificationsLongRunningPlatformImpl WrlFinal : Microsoft::WRL::RuntimeClass< @@ -20,6 +21,10 @@ Microsoft::WRL::RuntimeClass< STDMETHOD(RegisterFullTrustApplication)(_In_ PCWSTR processName, _In_ GUID remoteId, _Out_ GUID* appId) noexcept; + STDMETHOD(RegisterForegroundActivator)(/*[in]*/ IWpnForegroundSink* sink, /*[in]*/ LPCSTR processName); + + STDMETHOD(UnregisterForegroundActivator)(/*[out]*/ IWpnForegroundSink* sink, /*[in]*/ LPCSTR processName); + /* Add your functions to retrieve the platform components */ private: @@ -29,7 +34,7 @@ Microsoft::WRL::RuntimeClass< bool m_initialized = false; bool m_shutdown = false; - std::unique_ptr m_shutdownTimerManager; - // Here we will define the Platform components i.e. the map wrappings + std::unique_ptr m_shutdownTimerManager; + ForegroundSinkManager m_foregroundSinkManager; }; diff --git a/dev/WindowsAppSDK_DLL/WindowsAppSDK_DLL.vcxproj b/dev/WindowsAppSDK_DLL/WindowsAppSDK_DLL.vcxproj index c88854d15f..0beae9dd40 100644 --- a/dev/WindowsAppSDK_DLL/WindowsAppSDK_DLL.vcxproj +++ b/dev/WindowsAppSDK_DLL/WindowsAppSDK_DLL.vcxproj @@ -174,7 +174,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)appmodel\identity;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)appmodel\identity;$(SolutionDir)common Use Level4 true @@ -193,7 +193,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true @@ -212,7 +212,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true @@ -231,7 +231,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true @@ -250,7 +250,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true @@ -273,7 +273,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true @@ -296,7 +296,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true @@ -319,7 +319,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index 45a0cdcfaf..dea2adfd00 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -89,7 +89,14 @@ winrt::Microsoft::Windows::PushNotifications::PushNotificationChannel RequestCha int main() { - PushNotificationActivationInfo info( + Sleep(20000); // Attach to debugger + + PushNotificationChannel channel = RequestChannel(); + + printf("Press 'Enter' at any time to exit App."); + std::cin.ignore(); + + /*PushNotificationActivationInfo info( PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator, winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); // same clsid as app manifest @@ -130,7 +137,7 @@ int main() } // Don't unregister PushTrigger because we still want to receive push notifications from background infrastructure. - PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOptions::ComActivator); + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOptions::ComActivator);*/ return 0; } From 4e3b33ba41ed6a87889509a0a69a6f06879f976f Mon Sep 17 00:00:00 2001 From: Daniel Ayala Date: Wed, 25 Aug 2021 21:50:37 -0700 Subject: [PATCH 02/13] Added IWpnNotificationSink COM interface to LRP MSIX --- .../PushNotificationsLongRunningTask.Msix/appxmanifest.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/PushNotifications/PushNotificationsLongRunningTask.Msix/appxmanifest.xml b/test/PushNotifications/PushNotificationsLongRunningTask.Msix/appxmanifest.xml index ead9cdd55a..9cc91b8a4b 100644 --- a/test/PushNotifications/PushNotificationsLongRunningTask.Msix/appxmanifest.xml +++ b/test/PushNotifications/PushNotificationsLongRunningTask.Msix/appxmanifest.xml @@ -56,6 +56,12 @@ + + + + + + Date: Wed, 25 Aug 2021 21:50:59 -0700 Subject: [PATCH 03/13] Just stuff for testing. Needs to be undone --- .../PushNotificationChannel.cpp | 6 ++-- .../winmain.cpp | 2 ++ .../platform.cpp | 36 +++++++++++++++++++ .../platform.h | 5 +++ .../winmain.cpp | 2 ++ 5 files changed, 48 insertions(+), 3 deletions(-) diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index f2087f0f5d..95c44fb16e 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -27,7 +27,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { try { - if (!IsPackagedApp()) + if (IsPackagedApp()) { char processName[1024]; GetModuleFileNameExA(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])); @@ -69,7 +69,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::event_token PushNotificationChannel::PushReceived(winrt::Windows::TypedEventHandler handler) { - if (IsPackagedApp()) // Should be !m_isBIAvailable <- just for testing + if (!IsPackagedApp()) // Should be !m_isBIAvailable <- just for testing { return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) { @@ -96,7 +96,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void PushNotificationChannel::PushReceived(winrt::event_token const& token) noexcept { - if (IsPackagedApp()) + if (!IsPackagedApp()) { m_channel.PushNotificationReceived(token); } diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask.StartupTask/winmain.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask.StartupTask/winmain.cpp index 3e1c6ba159..72ff5f6287 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask.StartupTask/winmain.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask.StartupTask/winmain.cpp @@ -17,6 +17,8 @@ inline bool isRetriableRpcError(HRESULT hr) int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, PSTR /*lpCmdLine*/, int /*nCmdShow*/) { + Sleep(20000); + RETURN_IF_FAILED(::CoInitializeEx(nullptr, COINITBASE_MULTITHREADED)); auto scopeExit = wil::scope_exit( diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp index 49927a3c23..ab1c18a8de 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp @@ -61,6 +61,7 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterF auto lock = m_lock.lock_exclusive(); m_foregroundSinkManager.AddSink(processName, sink); + SetForegroundTimer(); return S_OK; } @@ -72,3 +73,38 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::Unregiste m_foregroundSinkManager.Remove(processName, sink); return S_OK; } + +void NotificationsLongRunningPlatformImpl::SetForegroundTimer() +{ + m_foregroundTimer.reset(CreateThreadpoolTimer( + [](PTP_CALLBACK_INSTANCE, _Inout_ PVOID platformPtr, _Inout_ PTP_TIMER) + { + NotificationsLongRunningPlatformImpl* platform = reinterpret_cast(platformPtr); + + if (platform != nullptr) + { + platform->SendForegroundNotification(); + } + }, + this, + nullptr)); + + THROW_LAST_ERROR_IF_NULL(m_foregroundTimer); + + // Negative times in SetThreadpoolTimer are relative. Allow 5 seconds to fire. + FILETIME dueTime{}; + *reinterpret_cast(&dueTime) = -static_cast(5000 * 10000); + + SetThreadpoolTimer(m_foregroundTimer.get(), &dueTime, 0, 0); +} + +void NotificationsLongRunningPlatformImpl::SendForegroundNotification() +{ + auto lock = m_lock.lock_shared(); + + byte samplePayload[] = { 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, + 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x4c, 0x52, 0x50, 0x21 }; // Payload from the LRP! + + m_foregroundSinkManager.InvokeForegroundHandlers("PushNotificationsDemoApp.exe", samplePayload, sizeof(samplePayload)); +} diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h index 80887d9775..91054f2d92 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h @@ -29,6 +29,11 @@ Microsoft::WRL::RuntimeClass< private: + // Extra stuff for testing + void SendForegroundNotification(); + void SetForegroundTimer(); + wil::unique_threadpool_timer m_foregroundTimer; + wil::srwlock m_lock; bool m_initialized = false; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/winmain.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/winmain.cpp index bf1d4fcd20..203517acfb 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/winmain.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/winmain.cpp @@ -21,6 +21,8 @@ using namespace Microsoft::WRL; int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, PSTR /*lpCmdLine*/, int /*nCmdShow*/) { + Sleep(20000); + RETURN_IF_FAILED(::CoInitializeEx(nullptr, COINITBASE_MULTITHREADED)); ComPtr platformFactory; From aa8f82130181b2599e037beb5fb69cd6e4506de4 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Thu, 26 Aug 2021 12:30:33 -0700 Subject: [PATCH 04/13] Still working on it --- .../ForegroundSinkManager.cpp | 29 ++++++++++++------- .../ForegroundSinkManager.h | 10 ++++--- .../platform.cpp | 5 +++- .../PushNotificationsDemoApp/main.cpp | 2 +- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp index e282d6e0b6..170e1e533c 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp @@ -3,22 +3,19 @@ #include "pch.h" #include - - - #include -void ForegroundSinkManager::AddSink(LPCSTR processName, IWpnForegroundSink* sink) +void ForegroundSinkManager::AddSink(std::string processName, IWpnForegroundSink* sink) { - if (!m_foregroundMap.contains(processName)) + /*if (!m_foregroundMap.contains(processName)) { m_foregroundMap[processName] = std::unordered_set(); - } - + }*/ + m_foregroundMap[processName] = std::unordered_set(); // for testing m_foregroundMap[processName].insert(sink); } -void ForegroundSinkManager::Remove(LPCSTR processName, IWpnForegroundSink* sink) +void ForegroundSinkManager::Remove(std::string processName, IWpnForegroundSink* sink) { THROW_HR_IF(E_INVALIDARG, !m_foregroundMap.contains(processName)); @@ -30,15 +27,25 @@ void ForegroundSinkManager::Remove(LPCSTR processName, IWpnForegroundSink* sink) } } -bool ForegroundSinkManager::InvokeForegroundHandlers(LPCSTR processName, byte* payload, ULONG payloadSize) +void ForegroundSinkManager::InvokeAllHandlers(byte* payload, ULONG payloadSize) +{ + for (std::pair> pair : m_foregroundMap) + { + for (IWpnForegroundSink* sink : pair.second) + { + sink->InvokeAll(payload, payloadSize); + } + } +} + +bool ForegroundSinkManager::InvokeForegroundHandlers(std::string processName, byte* payload, ULONG payloadSize) { - std::unordered_set sinks = m_foregroundMap[processName]; if (!m_foregroundMap.contains(processName)) { return false; } - std::unordered_set sinks2 = m_foregroundMap[processName]; + std::unordered_set sinks = m_foregroundMap[processName]; std::for_each(sinks.begin(), sinks.end(), [&](IWpnForegroundSink* sink) { sink->InvokeAll(payload, payloadSize); }); return true; } diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h index 53625d141b..efead89756 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h @@ -10,13 +10,15 @@ class ForegroundSinkManager public: ForegroundSinkManager() = default; - void AddSink(LPCSTR processName, IWpnForegroundSink* sink); + void AddSink(std::string processName, IWpnForegroundSink* sink); - void Remove(LPCSTR processName, IWpnForegroundSink* sink); + void Remove(std::string processName, IWpnForegroundSink* sink); - bool InvokeForegroundHandlers(LPCSTR processName, byte* payload, ULONG payloadSize); + void InvokeAllHandlers(byte* payload, ULONG payloadSize); // for testing + + bool InvokeForegroundHandlers(std::string processName, byte* payload, ULONG payloadSize); private: - std::unordered_map> m_foregroundMap = {}; + std::unordered_map> m_foregroundMap = {}; }; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp index ab1c18a8de..5768e222a8 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp @@ -61,6 +61,7 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterF auto lock = m_lock.lock_exclusive(); m_foregroundSinkManager.AddSink(processName, sink); + SendForegroundNotification(); SetForegroundTimer(); return S_OK; } @@ -106,5 +107,7 @@ void NotificationsLongRunningPlatformImpl::SendForegroundNotification() 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x52, 0x50, 0x21 }; // Payload from the LRP! - m_foregroundSinkManager.InvokeForegroundHandlers("PushNotificationsDemoApp.exe", samplePayload, sizeof(samplePayload)); + m_foregroundSinkManager.InvokeAllHandlers(samplePayload, sizeof(samplePayload)); + + //m_foregroundSinkManager.InvokeForegroundHandlers("PushNotificationsDemoApp.exe", samplePayload, sizeof(samplePayload)); } diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index dea2adfd00..1588a13836 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -89,7 +89,7 @@ winrt::Microsoft::Windows::PushNotifications::PushNotificationChannel RequestCha int main() { - Sleep(20000); // Attach to debugger + Sleep(10000); // Attach to debugger PushNotificationChannel channel = RequestChannel(); From 0869fa5c6b97dca92f5a946b9864e607a445ed98 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Thu, 26 Aug 2021 17:26:50 -0700 Subject: [PATCH 05/13] Com proxy objects not being stored correctly --- dev/PushNotifications/PushNotificationChannel.cpp | 2 +- .../ForegroundSinkManager.cpp | 9 ++++----- .../ForegroundSinkManager.h | 2 +- .../PushNotificationsLongRunningTask/platform.cpp | 5 +---- test/TestApps/PushNotificationsDemoApp/main.cpp | 3 ++- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index 95c44fb16e..c76781fb70 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -80,7 +80,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation }; }); } - else + else // forcing the packaged application to use LRP for testing { char processName[1024]; GetModuleFileNameExA(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])); diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp index 170e1e533c..0c1514c902 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp @@ -7,17 +7,16 @@ void ForegroundSinkManager::AddSink(std::string processName, IWpnForegroundSink* sink) { - /*if (!m_foregroundMap.contains(processName)) + if (!m_foregroundMap.contains(processName)) { m_foregroundMap[processName] = std::unordered_set(); - }*/ - m_foregroundMap[processName] = std::unordered_set(); // for testing + } m_foregroundMap[processName].insert(sink); } void ForegroundSinkManager::Remove(std::string processName, IWpnForegroundSink* sink) { - THROW_HR_IF(E_INVALIDARG, !m_foregroundMap.contains(processName)); + //THROW_HR_IF(E_INVALIDARG, !m_foregroundMap.contains(processName)); std::unordered_set sinks = m_foregroundMap[processName]; sinks.erase(sink); @@ -38,7 +37,7 @@ void ForegroundSinkManager::InvokeAllHandlers(byte* payload, ULONG payloadSize) } } -bool ForegroundSinkManager::InvokeForegroundHandlers(std::string processName, byte* payload, ULONG payloadSize) +bool ForegroundSinkManager::InvokeForegroundHandlersOfProc(std::string processName, byte* payload, ULONG payloadSize) { if (!m_foregroundMap.contains(processName)) { diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h index efead89756..f2e06a7532 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h @@ -16,7 +16,7 @@ class ForegroundSinkManager void InvokeAllHandlers(byte* payload, ULONG payloadSize); // for testing - bool InvokeForegroundHandlers(std::string processName, byte* payload, ULONG payloadSize); + bool InvokeForegroundHandlersOfProc(std::string processName, byte* payload, ULONG payloadSize); private: std::unordered_map> m_foregroundMap = {}; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp index 5768e222a8..5e437a1d01 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp @@ -61,7 +61,6 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterF auto lock = m_lock.lock_exclusive(); m_foregroundSinkManager.AddSink(processName, sink); - SendForegroundNotification(); SetForegroundTimer(); return S_OK; } @@ -101,13 +100,11 @@ void NotificationsLongRunningPlatformImpl::SetForegroundTimer() void NotificationsLongRunningPlatformImpl::SendForegroundNotification() { - auto lock = m_lock.lock_shared(); - byte samplePayload[] = { 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x52, 0x50, 0x21 }; // Payload from the LRP! m_foregroundSinkManager.InvokeAllHandlers(samplePayload, sizeof(samplePayload)); - //m_foregroundSinkManager.InvokeForegroundHandlers("PushNotificationsDemoApp.exe", samplePayload, sizeof(samplePayload)); + //m_foregroundSinkManager.InvokeForegroundHandlersOfProc("PushNotificationsDemoApp.exe", samplePayload, sizeof(samplePayload)); } diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index 1588a13836..4eaf54b07e 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -56,8 +56,9 @@ winrt::Windows::Foundation::IAsyncOperation RequestChan // Do stuff to process the raw payload std::string payloadString(payload.begin(), payload.end()); std::cout << "Push notification content received from FOREGROUND: " << payloadString << std::endl << std::endl; - args.Handled(true); + // args.Handled(true); }); + // Caller's responsibility to keep the channel alive co_return result.Channel(); } From 9628910d0691029627bae18dd95a9de0724eeb21 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Fri, 27 Aug 2021 17:30:19 -0700 Subject: [PATCH 06/13] Receiving Data from LRP and changed sink container --- .../PushNotificationChannel.cpp | 16 +++--- .../PushNotificationChannel.h | 2 +- .../NotificationsLongRunningProcess.idl | 6 +-- .../ForegroundSinkManager.cpp | 54 ++++++++----------- .../ForegroundSinkManager.h | 11 ++-- .../PushNotificationsLongRunningTask.vcxproj | 8 +-- .../platform.cpp | 10 ++-- .../platform.h | 4 +- .../PushNotificationsDemoApp/main.cpp | 6 ++- 9 files changed, 55 insertions(+), 62 deletions(-) diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index c76781fb70..49ae8e33ea 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -29,13 +29,13 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { if (IsPackagedApp()) { - char processName[1024]; - GetModuleFileNameExA(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])); - wil::com_ptr notificationsLongRunningPlatform{ wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; - notificationsLongRunningPlatform->UnregisterForegroundActivator(this, processName); + wchar_t processName[1024]; + THROW_HR_IF(ERROR_FILE_NOT_FOUND, GetModuleFileNameExW(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])) == 0); + + notificationsLongRunningPlatform->UnregisterForegroundActivator(processName); } } CATCH_LOG() @@ -82,12 +82,12 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } else // forcing the packaged application to use LRP for testing { - char processName[1024]; - GetModuleFileNameExA(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])); - wil::com_ptr notificationsLongRunningPlatform{ wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; + wchar_t processName[1024]; + THROW_HR_IF(ERROR_FILE_NOT_FOUND, GetModuleFileNameExW(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])) == 0); + THROW_IF_FAILED(notificationsLongRunningPlatform->RegisterForegroundActivator(this, processName)); return m_foregroundHandlers.add(handler); @@ -106,7 +106,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } } - HRESULT __stdcall PushNotificationChannel::InvokeAll(byte* start, ULONG length) noexcept try + HRESULT __stdcall PushNotificationChannel::InvokeAll(ULONG length, byte* start) noexcept try { std::vector vec; diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h index fe01348ce7..d98787470b 100644 --- a/dev/PushNotifications/PushNotificationChannel.h +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -24,7 +24,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void PushReceived(winrt::event_token const& token) noexcept; // IWpnForegroundSink - HRESULT __stdcall InvokeAll(byte* start, ULONG length) noexcept; + HRESULT __stdcall InvokeAll(ULONG length, byte* start) noexcept; private: bool IsPackagedApp(); diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl b/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl index b96f42759a..1aec1954ee 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl +++ b/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl @@ -11,7 +11,7 @@ import "ocidl.idl"; [pointer_default(unique)] interface IWpnForegroundSink : IUnknown { - HRESULT InvokeAll([in] byte* payload, [in] ULONG length); + HRESULT InvokeAll([in] ULONG length, [in, string] byte data[]); }; [object] @@ -21,9 +21,9 @@ interface INotificationsLongRunningPlatform : IUnknown { HRESULT RegisterFullTrustApplication([in] LPCWSTR processName, [in] GUID remoteId, [out] GUID* appId); - HRESULT RegisterForegroundActivator([in] IWpnForegroundSink* sink, [in] LPCSTR processName); + HRESULT RegisterForegroundActivator([in] IWpnForegroundSink* sink, [in] LPCWSTR processName); - HRESULT UnregisterForegroundActivator([in] IWpnForegroundSink* sink, [in] LPCSTR processName); + HRESULT UnregisterForegroundActivator([in] LPCWSTR processName); }; [uuid(PUSHNOTIFICATIONS_LIBID_UUID)] diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp index 0c1514c902..ff23710c3e 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp @@ -5,46 +5,36 @@ #include #include -void ForegroundSinkManager::AddSink(std::string processName, IWpnForegroundSink* sink) +void ForegroundSinkManager::AddSink(std::wstring processName, IWpnForegroundSink* sink) { - if (!m_foregroundMap.contains(processName)) - { - m_foregroundMap[processName] = std::unordered_set(); - } - m_foregroundMap[processName].insert(sink); + // Maybe check if exists? + m_foregroundMap[processName] = sink; } -void ForegroundSinkManager::Remove(std::string processName, IWpnForegroundSink* sink) +void ForegroundSinkManager::Remove(std::wstring processName) { - //THROW_HR_IF(E_INVALIDARG, !m_foregroundMap.contains(processName)); - - std::unordered_set sinks = m_foregroundMap[processName]; - sinks.erase(sink); - if (sinks.empty()) - { - m_foregroundMap.erase(processName); - } + // Check if it exists + m_foregroundMap.erase(processName); } -void ForegroundSinkManager::InvokeAllHandlers(byte* payload, ULONG payloadSize) +void ForegroundSinkManager::InvokeForegroundHandlers(ULONG payloadSize, byte* payload) { - for (std::pair> pair : m_foregroundMap) + for (std::pair> sink : m_foregroundMap) { - for (IWpnForegroundSink* sink : pair.second) - { - sink->InvokeAll(payload, payloadSize); - } + sink.second->InvokeAll(payloadSize, payload); } } -bool ForegroundSinkManager::InvokeForegroundHandlersOfProc(std::string processName, byte* payload, ULONG payloadSize) -{ - if (!m_foregroundMap.contains(processName)) - { - return false; - } - - std::unordered_set sinks = m_foregroundMap[processName]; - std::for_each(sinks.begin(), sinks.end(), [&](IWpnForegroundSink* sink) { sink->InvokeAll(payload, payloadSize); }); - return true; -} +//*** +// Waiting for NotificationListener to be finished +// *** +//void ForegroundSinkManager::InvokeForegroundHandlers(std::string processName, byte* payload, ULONG payloadSize) +//{ +// THROW_HR_IF(E_INVALIDARG, !m_foregroundMap.contains(processName)); +// +// std::vector>> sinkContainer = m_foregroundMap[processName]; +// for (std::pair> sink : sinkContainer) +// { +// sink.second->InvokeAll(payload, payloadSize); +// } +//} diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h index f2e06a7532..3a2cab9d24 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h @@ -4,21 +4,22 @@ #include #include #include +#include class ForegroundSinkManager { public: ForegroundSinkManager() = default; - void AddSink(std::string processName, IWpnForegroundSink* sink); + void AddSink(std::wstring processName, IWpnForegroundSink* sink); - void Remove(std::string processName, IWpnForegroundSink* sink); + void Remove(std::wstring processName); - void InvokeAllHandlers(byte* payload, ULONG payloadSize); // for testing + void InvokeForegroundHandlers(ULONG payloadSize, byte* payload); - bool InvokeForegroundHandlersOfProc(std::string processName, byte* payload, ULONG payloadSize); + // void InvokeForegroundHandlers(std::wstring processName, byte* payload, ULONG payloadSize); private: - std::unordered_map> m_foregroundMap = {}; + std::unordered_map> m_foregroundMap = {}; }; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj b/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj index e9751fc85a..9f207246b2 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj @@ -122,7 +122,7 @@ true WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp20 + stdcpp17 %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL @@ -139,7 +139,7 @@ true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp20 + stdcpp17 Guard %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL @@ -157,7 +157,7 @@ true _DEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp20 + stdcpp17 %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL @@ -174,7 +174,7 @@ true NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp20 + stdcpp17 Guard %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp index 5e437a1d01..8360feacdc 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp @@ -55,7 +55,7 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterF return E_NOTIMPL; } -STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterForegroundActivator(/*[in]*/ IWpnForegroundSink* sink, /*[in]*/ LPCSTR processName) +STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterForegroundActivator(/*[in]*/ IWpnForegroundSink* sink, /*[in]*/ PCWSTR processName) { RETURN_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); auto lock = m_lock.lock_exclusive(); @@ -65,12 +65,12 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterF return S_OK; } -STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::UnregisterForegroundActivator(/*[out]*/ IWpnForegroundSink* sink, /*[in]*/ LPCSTR processName) +STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::UnregisterForegroundActivator(/*[in]*/ PCWSTR processName) { RETURN_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); auto lock = m_lock.lock_exclusive(); - m_foregroundSinkManager.Remove(processName, sink); + m_foregroundSinkManager.Remove(processName); return S_OK; } @@ -103,8 +103,8 @@ void NotificationsLongRunningPlatformImpl::SendForegroundNotification() byte samplePayload[] = { 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x52, 0x50, 0x21 }; // Payload from the LRP! - - m_foregroundSinkManager.InvokeAllHandlers(samplePayload, sizeof(samplePayload)); + + m_foregroundSinkManager.InvokeForegroundHandlers(sizeof(samplePayload), samplePayload); //m_foregroundSinkManager.InvokeForegroundHandlersOfProc("PushNotificationsDemoApp.exe", samplePayload, sizeof(samplePayload)); } diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h index 91054f2d92..d5aa6291dd 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h @@ -21,9 +21,9 @@ Microsoft::WRL::RuntimeClass< STDMETHOD(RegisterFullTrustApplication)(_In_ PCWSTR processName, _In_ GUID remoteId, _Out_ GUID* appId) noexcept; - STDMETHOD(RegisterForegroundActivator)(/*[in]*/ IWpnForegroundSink* sink, /*[in]*/ LPCSTR processName); + STDMETHOD(RegisterForegroundActivator)(/*[in]*/ IWpnForegroundSink* sink, _In_ PCWSTR processName); - STDMETHOD(UnregisterForegroundActivator)(/*[out]*/ IWpnForegroundSink* sink, /*[in]*/ LPCSTR processName); + STDMETHOD(UnregisterForegroundActivator)(_In_ PCWSTR processName); /* Add your functions to retrieve the platform components */ diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index 4eaf54b07e..71db75a673 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -49,7 +49,7 @@ winrt::Windows::Foundation::IAsyncOperation RequestChan auto channelExpiry = result.Channel().ExpirationTime(); // Register Push Event for Foreground - result.Channel().PushReceived([](const auto&, PushNotificationReceivedEventArgs const& args) + winrt::event_token token = result.Channel().PushReceived([](const auto&, PushNotificationReceivedEventArgs const& args) { auto payload = args.Payload(); @@ -92,7 +92,9 @@ int main() { Sleep(10000); // Attach to debugger - PushNotificationChannel channel = RequestChannel(); + { + PushNotificationChannel channel = RequestChannel(); + } printf("Press 'Enter' at any time to exit App."); std::cin.ignore(); From 383801cdad5e3b938ae2f4be615a53d668053a96 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Sat, 28 Aug 2021 14:42:47 -0700 Subject: [PATCH 07/13] Foreground activation working --- .../PushNotificationChannel.cpp | 39 ++++------ .../PushNotificationChannel.h | 3 +- .../PushNotificationReceivedEventArgs.cpp | 71 +++++++++++++++---- .../PushNotificationReceivedEventArgs.h | 6 +- .../NotificationsLongRunningProcess.idl | 3 +- .../ForegroundSinkManager.cpp | 24 ++----- .../ForegroundSinkManager.h | 4 +- .../platform.cpp | 47 +++--------- .../platform.h | 10 ++- .../PushNotificationsDemoApp/main.cpp | 16 +---- 10 files changed, 99 insertions(+), 124 deletions(-) diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index 49ae8e33ea..3aa2b9548b 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -23,24 +23,6 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { PushNotificationChannel::PushNotificationChannel(winrt::Windows::PushNotificationChannel const& channel): m_channel(channel) {} - PushNotificationChannel::~PushNotificationChannel() noexcept - { - try - { - if (IsPackagedApp()) - { - wil::com_ptr notificationsLongRunningPlatform{ - wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; - - wchar_t processName[1024]; - THROW_HR_IF(ERROR_FILE_NOT_FOUND, GetModuleFileNameExW(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])) == 0); - - notificationsLongRunningPlatform->UnregisterForegroundActivator(processName); - } - } - CATCH_LOG() - } - winrt::Windows::Uri PushNotificationChannel::Uri() { return winrt::Windows::Uri{ m_channel.Uri() }; @@ -69,7 +51,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::event_token PushNotificationChannel::PushReceived(winrt::Windows::TypedEventHandler handler) { - if (!IsPackagedApp()) // Should be !m_isBIAvailable <- just for testing + if (IsPackagedApp()) { return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) { @@ -80,23 +62,27 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation }; }); } - else // forcing the packaged application to use LRP for testing + else { - wil::com_ptr notificationsLongRunningPlatform{ - wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; + if (!m_isRegisteredWithLRP) + { + wil::com_ptr notificationsLongRunningPlatform{ + wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; - wchar_t processName[1024]; - THROW_HR_IF(ERROR_FILE_NOT_FOUND, GetModuleFileNameExW(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])) == 0); + wchar_t processName[1024]; + THROW_HR_IF(ERROR_FILE_NOT_FOUND, GetModuleFileNameExW(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])) == 0); - THROW_IF_FAILED(notificationsLongRunningPlatform->RegisterForegroundActivator(this, processName)); + THROW_IF_FAILED(notificationsLongRunningPlatform->RegisterForegroundActivator(this, processName)); + m_isRegisteredWithLRP = true; + } return m_foregroundHandlers.add(handler); } } void PushNotificationChannel::PushReceived(winrt::event_token const& token) noexcept { - if (!IsPackagedApp()) + if (IsPackagedApp()) { m_channel.PushNotificationReceived(token); } @@ -117,7 +103,6 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation com_array arr{ start, start + (length * sizeof(uint8_t)) }; m_foregroundHandlers(*this, winrt::make(start, length)); - return S_OK; } CATCH_RETURN() diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h index d98787470b..1924969ea3 100644 --- a/dev/PushNotifications/PushNotificationChannel.h +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -14,7 +14,6 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation struct PushNotificationChannel : PushNotificationChannelT { PushNotificationChannel(winrt::Windows::Networking::PushNotifications::PushNotificationChannel const& channel); - ~PushNotificationChannel() noexcept; winrt::Windows::Foundation::Uri Uri(); winrt::Windows::Foundation::DateTime ExpirationTime(); @@ -32,7 +31,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation const winrt::Windows::Networking::PushNotifications::PushNotificationChannel m_channel{ nullptr }; - bool m_isBIAvailable = false; + bool m_isRegisteredWithLRP = false; winrt::event m_foregroundHandlers; }; } diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp index 13754b09df..5a0e371f8f 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp @@ -52,38 +52,79 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::BackgroundTaskDeferral PushNotificationReceivedEventArgs::GetDeferral() { - THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); - - return m_backgroundTaskInstance.GetDeferral(); + if (m_isBIAvailable) + { + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); + + return m_backgroundTaskInstance.GetDeferral(); + } + else + { + return nullptr; + } } winrt::event_token PushNotificationReceivedEventArgs::Canceled(winrt::BackgroundTaskCanceledEventHandler const& handler) { - THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); - - return m_backgroundTaskInstance.Canceled(handler); + if (m_isBIAvailable) + { + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); + + return m_backgroundTaskInstance.Canceled(handler); + } + else + { + return { 0 }; + } } void PushNotificationReceivedEventArgs::Canceled(winrt::event_token const& token) noexcept { - THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); + if (m_isBIAvailable) + { + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); - m_backgroundTaskInstance.Canceled(token); + m_backgroundTaskInstance.Canceled(token); + } } bool PushNotificationReceivedEventArgs::Handled() { - THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); - - // Also, we need to handle scenario for notifications coming from the LRP - return m_args.Cancel(); + if (m_isBIAvailable) + { + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); + + return m_args.Cancel(); + } + else + { + return m_handledUnpackaged; + } } void PushNotificationReceivedEventArgs::Handled(bool value) { - THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); - - m_args.Cancel(value); + if (m_isBIAvailable) + { + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); + + m_args.Cancel(value); + } + else + { + if (value) + { + wchar_t processName[1024]; + THROW_HR_IF(ERROR_FILE_NOT_FOUND, GetModuleFileNameExW(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])) == 0); + + wil::com_ptr notificationsLongRunningPlatform{ + wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; + + notificationsLongRunningPlatform->SendBackgroundNotification(processName, m_rawNotification, m_length); + } + + m_handledUnpackaged = value; + } } } diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.h b/dev/PushNotifications/PushNotificationReceivedEventArgs.h index fe1c49475f..a207d18cc0 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.h +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.h @@ -1,5 +1,6 @@ #pragma once #include "Microsoft.Windows.PushNotifications.PushNotificationReceivedEventArgs.g.h" +#include namespace winrt::Microsoft::Windows::PushNotifications::implementation { @@ -27,7 +28,8 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation const winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance m_backgroundTaskInstance{}; const winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs m_args = nullptr; - ULONG m_length = 0; - bool m_isBIAvailable = false; + ULONG m_length; + bool m_isBIAvailable; + bool m_handledUnpackaged = false; }; } diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl b/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl index 1aec1954ee..c27c6eac54 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl +++ b/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl @@ -23,7 +23,8 @@ interface INotificationsLongRunningPlatform : IUnknown HRESULT RegisterForegroundActivator([in] IWpnForegroundSink* sink, [in] LPCWSTR processName); - HRESULT UnregisterForegroundActivator([in] LPCWSTR processName); + HRESULT SendBackgroundNotification([in] LPCWSTR processName, [in, string] byte data[], [in] ULONG length); + }; [uuid(PUSHNOTIFICATIONS_LIBID_UUID)] diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp index ff23710c3e..f6213126f3 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp @@ -7,34 +7,20 @@ void ForegroundSinkManager::AddSink(std::wstring processName, IWpnForegroundSink* sink) { - // Maybe check if exists? m_foregroundMap[processName] = sink; } void ForegroundSinkManager::Remove(std::wstring processName) { - // Check if it exists m_foregroundMap.erase(processName); } -void ForegroundSinkManager::InvokeForegroundHandlers(ULONG payloadSize, byte* payload) +bool ForegroundSinkManager::InvokeForegroundHandlers(std::wstring processName, byte* payload, ULONG payloadSize) { - for (std::pair> sink : m_foregroundMap) + if (m_foregroundMap.find(processName) != m_foregroundMap.end()) { - sink.second->InvokeAll(payloadSize, payload); + m_foregroundMap[processName]->InvokeAll(payloadSize, payload); + return true; } + return false; } - -//*** -// Waiting for NotificationListener to be finished -// *** -//void ForegroundSinkManager::InvokeForegroundHandlers(std::string processName, byte* payload, ULONG payloadSize) -//{ -// THROW_HR_IF(E_INVALIDARG, !m_foregroundMap.contains(processName)); -// -// std::vector>> sinkContainer = m_foregroundMap[processName]; -// for (std::pair> sink : sinkContainer) -// { -// sink.second->InvokeAll(payload, payloadSize); -// } -//} diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h index 3a2cab9d24..3e0bd81434 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h @@ -15,9 +15,7 @@ class ForegroundSinkManager void Remove(std::wstring processName); - void InvokeForegroundHandlers(ULONG payloadSize, byte* payload); - - // void InvokeForegroundHandlers(std::wstring processName, byte* payload, ULONG payloadSize); + bool InvokeForegroundHandlers(std::wstring processName, byte* payload, ULONG payloadSize); private: std::unordered_map> m_foregroundMap = {}; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp index 8360feacdc..6c36d1de51 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp @@ -55,56 +55,31 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterF return E_NOTIMPL; } -STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterForegroundActivator(/*[in]*/ IWpnForegroundSink* sink, /*[in]*/ PCWSTR processName) +STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterForegroundActivator(_In_ IWpnForegroundSink* sink, _In_ PCWSTR processName) { RETURN_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); auto lock = m_lock.lock_exclusive(); m_foregroundSinkManager.AddSink(processName, sink); - SetForegroundTimer(); return S_OK; } -STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::UnregisterForegroundActivator(/*[in]*/ PCWSTR processName) +STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::SendBackgroundNotification(_In_ PCWSTR processName, _In_ byte* payload, _In_ ULONG payloadSize) { - RETURN_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); - auto lock = m_lock.lock_exclusive(); - - m_foregroundSinkManager.Remove(processName); return S_OK; } -void NotificationsLongRunningPlatformImpl::SetForegroundTimer() +void NotificationsLongRunningPlatformImpl::UnregisterForegroundActivator(_In_ PCWSTR processName) { - m_foregroundTimer.reset(CreateThreadpoolTimer( - [](PTP_CALLBACK_INSTANCE, _Inout_ PVOID platformPtr, _Inout_ PTP_TIMER) - { - NotificationsLongRunningPlatformImpl* platform = reinterpret_cast(platformPtr); - - if (platform != nullptr) - { - platform->SendForegroundNotification(); - } - }, - this, - nullptr)); - - THROW_LAST_ERROR_IF_NULL(m_foregroundTimer); - - // Negative times in SetThreadpoolTimer are relative. Allow 5 seconds to fire. - FILETIME dueTime{}; - *reinterpret_cast(&dueTime) = -static_cast(5000 * 10000); - - SetThreadpoolTimer(m_foregroundTimer.get(), &dueTime, 0, 0); + auto lock = m_lock.lock_exclusive(); + + m_foregroundSinkManager.Remove(processName); } -void NotificationsLongRunningPlatformImpl::SendForegroundNotification() +void NotificationsLongRunningPlatformImpl::DeliverPayload(PCWSTR processName, byte* payload, ULONG payloadSize) { - byte samplePayload[] = { 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, - 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x4c, 0x52, 0x50, 0x21 }; // Payload from the LRP! - - m_foregroundSinkManager.InvokeForegroundHandlers(sizeof(samplePayload), samplePayload); - - //m_foregroundSinkManager.InvokeForegroundHandlersOfProc("PushNotificationsDemoApp.exe", samplePayload, sizeof(samplePayload)); + if (!m_foregroundSinkManager.InvokeForegroundHandlers(processName, payload, payloadSize)) + { + SendBackgroundNotification(processName, payload, payloadSize); + } } diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h index d5aa6291dd..7da24a7a2e 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h @@ -21,18 +21,16 @@ Microsoft::WRL::RuntimeClass< STDMETHOD(RegisterFullTrustApplication)(_In_ PCWSTR processName, _In_ GUID remoteId, _Out_ GUID* appId) noexcept; - STDMETHOD(RegisterForegroundActivator)(/*[in]*/ IWpnForegroundSink* sink, _In_ PCWSTR processName); + STDMETHOD(RegisterForegroundActivator)(_In_ IWpnForegroundSink* sink, _In_ PCWSTR processName); - STDMETHOD(UnregisterForegroundActivator)(_In_ PCWSTR processName); + STDMETHOD(SendBackgroundNotification)(_In_ PCWSTR processName, _In_ byte* payload, _In_ ULONG payloadSize); /* Add your functions to retrieve the platform components */ private: - // Extra stuff for testing - void SendForegroundNotification(); - void SetForegroundTimer(); - wil::unique_threadpool_timer m_foregroundTimer; + void UnregisterForegroundActivator(PCWSTR processName); + void DeliverPayload(PCWSTR processName, byte* payload, ULONG payloadSize); wil::srwlock m_lock; diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index 71db75a673..382037440c 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -56,9 +56,8 @@ winrt::Windows::Foundation::IAsyncOperation RequestChan // Do stuff to process the raw payload std::string payloadString(payload.begin(), payload.end()); std::cout << "Push notification content received from FOREGROUND: " << payloadString << std::endl << std::endl; - // args.Handled(true); + args.Handled(true); }); - // Caller's responsibility to keep the channel alive co_return result.Channel(); } @@ -90,16 +89,7 @@ winrt::Microsoft::Windows::PushNotifications::PushNotificationChannel RequestCha int main() { - Sleep(10000); // Attach to debugger - - { - PushNotificationChannel channel = RequestChannel(); - } - - printf("Press 'Enter' at any time to exit App."); - std::cin.ignore(); - - /*PushNotificationActivationInfo info( + PushNotificationActivationInfo info( PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator, winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); // same clsid as app manifest @@ -140,7 +130,7 @@ int main() } // Don't unregister PushTrigger because we still want to receive push notifications from background infrastructure. - PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOptions::ComActivator);*/ + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOptions::ComActivator); return 0; } From 48a68b7f2d93ed99f0500e8ec5c23fcbcbbf06a8 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Mon, 30 Aug 2021 15:47:43 -0700 Subject: [PATCH 08/13] Fix first round of nits --- .../PushNotificationChannel.cpp | 23 +++---------- .../PushNotificationChannel.h | 2 +- .../PushNotificationReceivedEventArgs.cpp | 32 +++++++++---------- .../PushNotificationReceivedEventArgs.h | 6 ++-- .../winmain.cpp | 2 -- .../ForegroundSinkManager.cpp | 2 +- .../platform.cpp | 9 +----- .../platform.h | 1 - .../winmain.cpp | 2 -- 9 files changed, 27 insertions(+), 52 deletions(-) diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index 3aa2b9548b..a37cb9e650 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -51,7 +51,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::event_token PushNotificationChannel::PushReceived(winrt::Windows::TypedEventHandler handler) { - if (IsPackagedApp()) + if (IsPackagedAppScenario()) { return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) { @@ -82,7 +82,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void PushNotificationChannel::PushReceived(winrt::event_token const& token) noexcept { - if (IsPackagedApp()) + if (IsPackagedAppScenario()) { m_channel.PushNotificationReceived(token); } @@ -92,16 +92,8 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } } - HRESULT __stdcall PushNotificationChannel::InvokeAll(ULONG length, byte* start) noexcept try + HRESULT __stdcall PushNotificationChannel::InvokeAll(ULONG length, _In_ byte* start) noexcept try { - std::vector vec; - - for (int i = 0; (ULONG)i < length; i++) - { - vec.push_back(start[i]); - } - - com_array arr{ start, start + (length * sizeof(uint8_t)) }; m_foregroundHandlers(*this, winrt::make(start, length)); return S_OK; } @@ -113,13 +105,8 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } // Determines if the caller should be treated as packaged app or not. - bool PushNotificationChannel::IsPackagedApp() + bool PushNotificationChannel::IsPackagedAppScenario() { - if (AppModel::Identity::IsPackagedProcess() && IsBackgroundTaskBuilderAvailable()) - { - return true; - } - - return false; + return AppModel::Identity::IsPackagedProcess() && IsBackgroundTaskBuilderAvailable(); } } diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h index 1924969ea3..4ea97c4731 100644 --- a/dev/PushNotifications/PushNotificationChannel.h +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -26,7 +26,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation HRESULT __stdcall InvokeAll(ULONG length, byte* start) noexcept; private: - bool IsPackagedApp(); + bool IsPackagedAppScenario(); bool IsBackgroundTaskBuilderAvailable(); const winrt::Windows::Networking::PushNotifications::PushNotificationChannel m_channel{ nullptr }; diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp index 5a0e371f8f..a320bb22bc 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp @@ -25,34 +25,34 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::IBackgroundTaskInstance const& backgroundTask): m_backgroundTaskInstance(backgroundTask), - m_rawNotification(GetByteArrayFromBuffer(backgroundTask.TriggerDetails().as().ContentBytes())), - m_isBIAvailable(true) {} + m_rawNotificationPayload(GetByteArrayFromBuffer(backgroundTask.TriggerDetails().as().ContentBytes())), + m_isUnpackagedApp(true) {} PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args): m_args(args), - m_rawNotification(GetByteArrayFromBuffer(args.RawNotification().ContentBytes())), - m_isBIAvailable(true) {} + m_rawNotificationPayload(GetByteArrayFromBuffer(args.RawNotification().ContentBytes())), + m_isUnpackagedApp(true) {} PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(byte* payload, ULONG length): - m_rawNotification(payload), - m_length(length), - m_isBIAvailable(false) {} + m_rawNotificationPayload(payload), + m_rawNotificationPayloadLength(length), + m_isUnpackagedApp(false) {} byte* PushNotificationReceivedEventArgs::GetByteArrayFromBuffer(winrt::Windows::Storage::Streams::IBuffer buffer) { auto rawNotificationData = buffer.data(); - m_length = buffer.Length(); + m_rawNotificationPayloadLength = buffer.Length(); return rawNotificationData; } winrt::com_array PushNotificationReceivedEventArgs::Payload() { - return { m_rawNotification, m_rawNotification + (m_length * sizeof(uint8_t)) }; + return { m_rawNotificationPayload, m_rawNotificationPayload + (m_rawNotificationPayloadLength * sizeof(uint8_t)) }; } winrt::BackgroundTaskDeferral PushNotificationReceivedEventArgs::GetDeferral() { - if (m_isBIAvailable) + if (m_isUnpackagedApp) { THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); @@ -66,7 +66,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::event_token PushNotificationReceivedEventArgs::Canceled(winrt::BackgroundTaskCanceledEventHandler const& handler) { - if (m_isBIAvailable) + if (m_isUnpackagedApp) { THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); @@ -80,7 +80,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void PushNotificationReceivedEventArgs::Canceled(winrt::event_token const& token) noexcept { - if (m_isBIAvailable) + if (m_isUnpackagedApp) { THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); @@ -90,7 +90,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation bool PushNotificationReceivedEventArgs::Handled() { - if (m_isBIAvailable) + if (m_isUnpackagedApp) { THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); @@ -104,7 +104,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void PushNotificationReceivedEventArgs::Handled(bool value) { - if (m_isBIAvailable) + if (m_isUnpackagedApp) { THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); @@ -112,7 +112,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } else { - if (value) + if (!value) { wchar_t processName[1024]; THROW_HR_IF(ERROR_FILE_NOT_FOUND, GetModuleFileNameExW(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])) == 0); @@ -120,7 +120,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation wil::com_ptr notificationsLongRunningPlatform{ wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; - notificationsLongRunningPlatform->SendBackgroundNotification(processName, m_rawNotification, m_length); + THROW_IF_FAILED(notificationsLongRunningPlatform->SendBackgroundNotification(processName, m_rawNotificationPayload, m_rawNotificationPayloadLength)); } m_handledUnpackaged = value; diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.h b/dev/PushNotifications/PushNotificationReceivedEventArgs.h index a207d18cc0..f9809d15a2 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.h +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.h @@ -23,13 +23,13 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation private: - byte* m_rawNotification = nullptr; + byte* m_rawNotificationPayload = nullptr; + ULONG m_rawNotificationPayloadLength; const winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance m_backgroundTaskInstance{}; const winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs m_args = nullptr; - ULONG m_length; - bool m_isBIAvailable; + bool m_isUnpackagedApp; bool m_handledUnpackaged = false; }; } diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask.StartupTask/winmain.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask.StartupTask/winmain.cpp index 72ff5f6287..3e1c6ba159 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask.StartupTask/winmain.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask.StartupTask/winmain.cpp @@ -17,8 +17,6 @@ inline bool isRetriableRpcError(HRESULT hr) int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, PSTR /*lpCmdLine*/, int /*nCmdShow*/) { - Sleep(20000); - RETURN_IF_FAILED(::CoInitializeEx(nullptr, COINITBASE_MULTITHREADED)); auto scopeExit = wil::scope_exit( diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp index f6213126f3..96a7207740 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp @@ -19,7 +19,7 @@ bool ForegroundSinkManager::InvokeForegroundHandlers(std::wstring processName, b { if (m_foregroundMap.find(processName) != m_foregroundMap.end()) { - m_foregroundMap[processName]->InvokeAll(payloadSize, payload); + LOG_IF_FAILED(m_foregroundMap[processName]->InvokeAll(payloadSize, payload)); return true; } return false; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp index 6c36d1de51..7777215edb 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp @@ -18,7 +18,7 @@ void NotificationsLongRunningPlatformImpl::Initialize() // Schedule event signaling after 5 seconds. This is in case we don't have any apps to track in the LRP. // If we realize that we need to persist the LRP, timer should be canceled. m_shutdownTimerManager = std::make_unique(); - //m_shutdownTimerManager->Setup(); + m_shutdownTimerManager->Setup(); /* TODO: Verify registry and UDK list and make sure we have apps to be tracked */ @@ -76,10 +76,3 @@ void NotificationsLongRunningPlatformImpl::UnregisterForegroundActivator(_In_ PC m_foregroundSinkManager.Remove(processName); } -void NotificationsLongRunningPlatformImpl::DeliverPayload(PCWSTR processName, byte* payload, ULONG payloadSize) -{ - if (!m_foregroundSinkManager.InvokeForegroundHandlers(processName, payload, payloadSize)) - { - SendBackgroundNotification(processName, payload, payloadSize); - } -} diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h index 7da24a7a2e..d112a00569 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h @@ -30,7 +30,6 @@ Microsoft::WRL::RuntimeClass< private: void UnregisterForegroundActivator(PCWSTR processName); - void DeliverPayload(PCWSTR processName, byte* payload, ULONG payloadSize); wil::srwlock m_lock; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/winmain.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/winmain.cpp index 203517acfb..bf1d4fcd20 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/winmain.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/winmain.cpp @@ -21,8 +21,6 @@ using namespace Microsoft::WRL; int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, PSTR /*lpCmdLine*/, int /*nCmdShow*/) { - Sleep(20000); - RETURN_IF_FAILED(::CoInitializeEx(nullptr, COINITBASE_MULTITHREADED)); ComPtr platformFactory; From d7e6f1885fbc57c185938a0bf5a1c9fad2cba95b Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Mon, 30 Aug 2021 17:15:18 -0700 Subject: [PATCH 09/13] Still working on adding nits --- .../PushNotificationChannel.cpp | 7 ++++--- .../PushNotificationChannel.h | 2 +- .../PushNotificationReceivedEventArgs.cpp | 19 ++++++++----------- .../PushNotificationReceivedEventArgs.h | 5 ++--- .../ForegroundSinkManager.cpp | 2 +- .../ForegroundSinkManager.h | 2 +- .../platform.cpp | 2 +- 7 files changed, 18 insertions(+), 21 deletions(-) diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index a37cb9e650..25eff68f4c 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -13,6 +13,7 @@ namespace winrt::Windows { using namespace winrt::Windows::Networking::PushNotifications; using namespace winrt::Windows::Foundation; + using namespace winrt::Windows::Metadata; } namespace winrt::Microsoft { @@ -92,16 +93,16 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } } - HRESULT __stdcall PushNotificationChannel::InvokeAll(ULONG length, _In_ byte* start) noexcept try + HRESULT __stdcall PushNotificationChannel::InvokeAll(ULONG length, _In_ byte* payload) noexcept try { - m_foregroundHandlers(*this, winrt::make(start, length)); + m_foregroundHandlers(*this, winrt::make(payload, length)); return S_OK; } CATCH_RETURN() bool PushNotificationChannel::IsBackgroundTaskBuilderAvailable() { - return winrt::Windows::Metadata::ApiInformation::IsMethodPresent(L"Windows.ApplicationModel.Background.BackgroundTaskBuilder", L"SetTaskEntryPointClsid"); + return winrt::ApiInformation::IsMethodPresent(L"Windows.ApplicationModel.Background.BackgroundTaskBuilder", L"SetTaskEntryPointClsid"); } // Determines if the caller should be treated as packaged app or not. diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h index 4ea97c4731..4099a3c691 100644 --- a/dev/PushNotifications/PushNotificationChannel.h +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -23,7 +23,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void PushReceived(winrt::event_token const& token) noexcept; // IWpnForegroundSink - HRESULT __stdcall InvokeAll(ULONG length, byte* start) noexcept; + HRESULT __stdcall InvokeAll(ULONG length, byte* payload) noexcept; private: bool IsPackagedAppScenario(); diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp index a320bb22bc..456f875ef3 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp @@ -25,29 +25,26 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::IBackgroundTaskInstance const& backgroundTask): m_backgroundTaskInstance(backgroundTask), - m_rawNotificationPayload(GetByteArrayFromBuffer(backgroundTask.TriggerDetails().as().ContentBytes())), + m_rawNotificationPayload(BuildPayload(backgroundTask.TriggerDetails().as().ContentBytes().data(), backgroundTask.TriggerDetails().as().ContentBytes().Length())), m_isUnpackagedApp(true) {} PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args): m_args(args), - m_rawNotificationPayload(GetByteArrayFromBuffer(args.RawNotification().ContentBytes())), + m_rawNotificationPayload(BuildPayload(args.RawNotification().ContentBytes().data(), args.RawNotification().ContentBytes().Length())), m_isUnpackagedApp(true) {} PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(byte* payload, ULONG length): - m_rawNotificationPayload(payload), - m_rawNotificationPayloadLength(length), + m_rawNotificationPayload(BuildPayload(payload, length)), m_isUnpackagedApp(false) {} - byte* PushNotificationReceivedEventArgs::GetByteArrayFromBuffer(winrt::Windows::Storage::Streams::IBuffer buffer) + std::vector PushNotificationReceivedEventArgs::BuildPayload(uint8_t* payload, ULONG payloadLength) { - auto rawNotificationData = buffer.data(); - m_rawNotificationPayloadLength = buffer.Length(); - return rawNotificationData; + return { payload, payload + (payloadLength * sizeof(uint8_t)) }; } winrt::com_array PushNotificationReceivedEventArgs::Payload() { - return { m_rawNotificationPayload, m_rawNotificationPayload + (m_rawNotificationPayloadLength * sizeof(uint8_t)) }; + return { m_rawNotificationPayload.data(), m_rawNotificationPayload.data() + (m_rawNotificationPayload.size() * sizeof(uint8_t)) }; } winrt::BackgroundTaskDeferral PushNotificationReceivedEventArgs::GetDeferral() @@ -114,13 +111,13 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { if (!value) { - wchar_t processName[1024]; + wchar_t processName[MAX_PATH]; THROW_HR_IF(ERROR_FILE_NOT_FOUND, GetModuleFileNameExW(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])) == 0); wil::com_ptr notificationsLongRunningPlatform{ wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; - THROW_IF_FAILED(notificationsLongRunningPlatform->SendBackgroundNotification(processName, m_rawNotificationPayload, m_rawNotificationPayloadLength)); + THROW_IF_FAILED(notificationsLongRunningPlatform->SendBackgroundNotification(processName, m_rawNotificationPayload.data(), m_rawNotificationPayload.size())); } m_handledUnpackaged = value; diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.h b/dev/PushNotifications/PushNotificationReceivedEventArgs.h index f9809d15a2..19040f0bb1 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.h +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.h @@ -19,12 +19,11 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation bool Handled(); void Handled(bool value); - byte* GetByteArrayFromBuffer(winrt::Windows::Storage::Streams::IBuffer buffer); + std::vector BuildPayload(uint8_t* payload, ULONG payloadLength); private: - byte* m_rawNotificationPayload = nullptr; - ULONG m_rawNotificationPayloadLength; + std::vector m_rawNotificationPayload; const winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance m_backgroundTaskInstance{}; const winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs m_args = nullptr; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp index 96a7207740..4b7d8d320f 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp @@ -5,7 +5,7 @@ #include #include -void ForegroundSinkManager::AddSink(std::wstring processName, IWpnForegroundSink* sink) +void ForegroundSinkManager::Add(std::wstring processName, IWpnForegroundSink* sink) { m_foregroundMap[processName] = sink; } diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h index 3e0bd81434..fe25e15284 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h @@ -11,7 +11,7 @@ class ForegroundSinkManager public: ForegroundSinkManager() = default; - void AddSink(std::wstring processName, IWpnForegroundSink* sink); + void Add(std::wstring processName, IWpnForegroundSink* sink); void Remove(std::wstring processName); diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp index 7777215edb..50766d8352 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp @@ -60,7 +60,7 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterF RETURN_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); auto lock = m_lock.lock_exclusive(); - m_foregroundSinkManager.AddSink(processName, sink); + m_foregroundSinkManager.Add(processName, sink); return S_OK; } From 69c7445183686b5ec9c67dce50c329ee3dc1940f Mon Sep 17 00:00:00 2001 From: Eric Langlois Date: Tue, 31 Aug 2021 11:12:40 -0700 Subject: [PATCH 10/13] Fix following FI of main --- dev/PushNotifications/PushNotificationChannel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index 25eff68f4c..456d855646 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -102,7 +102,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation bool PushNotificationChannel::IsBackgroundTaskBuilderAvailable() { - return winrt::ApiInformation::IsMethodPresent(L"Windows.ApplicationModel.Background.BackgroundTaskBuilder", L"SetTaskEntryPointClsid"); + return winrt::Windows::ApiInformation::IsMethodPresent(L"Windows.ApplicationModel.Background.BackgroundTaskBuilder", L"SetTaskEntryPointClsid"); } // Determines if the caller should be treated as packaged app or not. From f992b5f2781b575b5147eeb68653c7e114f77842 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Tue, 31 Aug 2021 18:56:28 -0700 Subject: [PATCH 11/13] Addressing nits --- .../PushNotificationChannel.cpp | 34 +++++++++----- .../PushNotificationChannel.h | 5 +- .../PushNotificationDummyDeferral.h | 31 +++++++++++++ .../PushNotificationReceivedEventArgs.cpp | 46 +++++++++---------- .../PushNotificationReceivedEventArgs.h | 13 +++--- .../PushNotifications.vcxitems | 5 +- .../NotificationsLongRunningProcess.idl | 6 ++- .../ForegroundSinkManager.cpp | 22 ++++++--- .../ForegroundSinkManager.h | 9 ++-- .../platform.cpp | 13 +++--- .../platform.h | 9 ++-- dev/PushNotifications/externs.h | 5 ++ 12 files changed, 129 insertions(+), 69 deletions(-) create mode 100644 dev/PushNotifications/PushNotificationDummyDeferral.h diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index 25eff68f4c..c790de4883 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -8,6 +8,7 @@ #include #include #include "PushNotificationReceivedEventArgs.h" +#include "externs.h" namespace winrt::Windows { @@ -56,8 +57,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) { - auto strong = weak_self.get(); - if (strong) + if (auto strong = weak_self.get()) { handler(*strong, winrt::make(args)); }; @@ -65,17 +65,16 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } else { - if (!m_isRegisteredWithLRP) + auto lock = m_lock.lock_exclusive(); + if (!m_foregroundHandlerCount++) { wil::com_ptr notificationsLongRunningPlatform{ wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; - wchar_t processName[1024]; - THROW_HR_IF(ERROR_FILE_NOT_FOUND, GetModuleFileNameExW(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])) == 0); + wil::unique_cotaskmem_string processName; + THROW_IF_FAILED(GetCurrentProcessPath(processName)); - THROW_IF_FAILED(notificationsLongRunningPlatform->RegisterForegroundActivator(this, processName)); - - m_isRegisteredWithLRP = true; + THROW_IF_FAILED(notificationsLongRunningPlatform->RegisterForegroundActivator(this, processName.get())); } return m_foregroundHandlers.add(handler); } @@ -89,20 +88,33 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } else { + auto lock = m_lock.lock_exclusive(); m_foregroundHandlers.remove(token); + if (!--m_foregroundHandlerCount) + { + wil::com_ptr notificationsLongRunningPlatform{ + wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; + + wil::unique_cotaskmem_string processName; + THROW_IF_FAILED(GetCurrentProcessPath(processName)); + + THROW_IF_FAILED(notificationsLongRunningPlatform->UnregisterForegroundActivator(processName.get())); + } } } - HRESULT __stdcall PushNotificationChannel::InvokeAll(ULONG length, _In_ byte* payload) noexcept try + HRESULT __stdcall PushNotificationChannel::InvokeAll(_In_ ULONG length, _In_ byte* payload, _Out_ BOOL* foregroundHandled) noexcept try { - m_foregroundHandlers(*this, winrt::make(payload, length)); + auto args = winrt::make(payload, length); + m_foregroundHandlers(*this, args); + *foregroundHandled = args.Handled(); return S_OK; } CATCH_RETURN() bool PushNotificationChannel::IsBackgroundTaskBuilderAvailable() { - return winrt::ApiInformation::IsMethodPresent(L"Windows.ApplicationModel.Background.BackgroundTaskBuilder", L"SetTaskEntryPointClsid"); + return winrt::Windows::ApiInformation::IsMethodPresent(L"Windows.ApplicationModel.Background.BackgroundTaskBuilder", L"SetTaskEntryPointClsid"); } // Determines if the caller should be treated as packaged app or not. diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h index 4099a3c691..d3764fb823 100644 --- a/dev/PushNotifications/PushNotificationChannel.h +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -23,7 +23,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void PushReceived(winrt::event_token const& token) noexcept; // IWpnForegroundSink - HRESULT __stdcall InvokeAll(ULONG length, byte* payload) noexcept; + HRESULT __stdcall InvokeAll(_In_ ULONG length, _In_ byte* payload, _Out_ BOOL* foregroundHandled) noexcept; private: bool IsPackagedAppScenario(); @@ -31,8 +31,9 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation const winrt::Windows::Networking::PushNotifications::PushNotificationChannel m_channel{ nullptr }; - bool m_isRegisteredWithLRP = false; winrt::event m_foregroundHandlers; + ULONG m_foregroundHandlerCount = 0; + wil::srwlock m_lock; }; } diff --git a/dev/PushNotifications/PushNotificationDummyDeferral.h b/dev/PushNotifications/PushNotificationDummyDeferral.h new file mode 100644 index 0000000000..66513f53e7 --- /dev/null +++ b/dev/PushNotifications/PushNotificationDummyDeferral.h @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#pragma once +#include "pch.h" +#include +#include + +struct PushNotificationDummyDeferral : winrt::implements +{ + PushNotificationDummyDeferral() {} + + void Complete() + { + return; + } +}; + +struct PushNotificationDummyDeferralFactory : winrt::implements +{ + HRESULT __stdcall CreateInstance(_In_opt_ IUnknown* aggregateInterface, _In_ REFIID interfaceId, _Outptr_ VOID** object) noexcept final + { + RETURN_HR_IF(CLASS_E_NOAGGREGATION, aggregateInterface != nullptr); + return winrt::make().as(interfaceId, object); + } + + HRESULT __stdcall LockServer(BOOL) noexcept final + { + return S_OK; + } +}; diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp index 456f875ef3..29e3623f2f 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp @@ -11,6 +11,7 @@ #include "Microsoft.Windows.PushNotifications.PushNotificationReceivedEventArgs.g.cpp" #include #include +#include #include "ValueMarshaling.h" namespace winrt @@ -25,21 +26,26 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::IBackgroundTaskInstance const& backgroundTask): m_backgroundTaskInstance(backgroundTask), - m_rawNotificationPayload(BuildPayload(backgroundTask.TriggerDetails().as().ContentBytes().data(), backgroundTask.TriggerDetails().as().ContentBytes().Length())), - m_isUnpackagedApp(true) {} + m_rawNotificationPayload(BuildPayload(backgroundTask.TriggerDetails().as().ContentBytes())), + m_unpackagedAppScenario(false) {} PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args): m_args(args), - m_rawNotificationPayload(BuildPayload(args.RawNotification().ContentBytes().data(), args.RawNotification().ContentBytes().Length())), - m_isUnpackagedApp(true) {} + m_rawNotificationPayload(BuildPayload(args.RawNotification().ContentBytes())), + m_unpackagedAppScenario(false) {} - PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(byte* payload, ULONG length): + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(byte* const& payload, ULONG const& length) : m_rawNotificationPayload(BuildPayload(payload, length)), - m_isUnpackagedApp(false) {} + m_unpackagedAppScenario(true) {} - std::vector PushNotificationReceivedEventArgs::BuildPayload(uint8_t* payload, ULONG payloadLength) + std::vector PushNotificationReceivedEventArgs::BuildPayload(winrt::Windows::Storage::Streams::IBuffer const& buffer) { - return { payload, payload + (payloadLength * sizeof(uint8_t)) }; + return { buffer.data(), buffer.data() + (buffer.Length() * sizeof(uint8_t)) }; + } + + std::vector PushNotificationReceivedEventArgs::BuildPayload(byte* const& payload, ULONG const& length) + { + return { payload, payload + (length * sizeof(uint8_t)) }; } winrt::com_array PushNotificationReceivedEventArgs::Payload() @@ -49,7 +55,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::BackgroundTaskDeferral PushNotificationReceivedEventArgs::GetDeferral() { - if (m_isUnpackagedApp) + if (!m_unpackagedAppScenario) { THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); @@ -57,13 +63,14 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } else { - return nullptr; + auto dummyDeferral = winrt::make(); + return dummyDeferral.as(); } } winrt::event_token PushNotificationReceivedEventArgs::Canceled(winrt::BackgroundTaskCanceledEventHandler const& handler) { - if (m_isUnpackagedApp) + if (!m_unpackagedAppScenario) { THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); @@ -77,7 +84,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void PushNotificationReceivedEventArgs::Canceled(winrt::event_token const& token) noexcept { - if (m_isUnpackagedApp) + if (!m_unpackagedAppScenario) { THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); @@ -87,7 +94,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation bool PushNotificationReceivedEventArgs::Handled() { - if (m_isUnpackagedApp) + if (!m_unpackagedAppScenario) { THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); @@ -101,7 +108,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void PushNotificationReceivedEventArgs::Handled(bool value) { - if (m_isUnpackagedApp) + if (!m_unpackagedAppScenario) { THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); @@ -109,17 +116,6 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } else { - if (!value) - { - wchar_t processName[MAX_PATH]; - THROW_HR_IF(ERROR_FILE_NOT_FOUND, GetModuleFileNameExW(GetCurrentProcess(), NULL, processName, sizeof(processName) / sizeof(processName[0])) == 0); - - wil::com_ptr notificationsLongRunningPlatform{ - wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; - - THROW_IF_FAILED(notificationsLongRunningPlatform->SendBackgroundNotification(processName, m_rawNotificationPayload.data(), m_rawNotificationPayload.size())); - } - m_handledUnpackaged = value; } } diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.h b/dev/PushNotifications/PushNotificationReceivedEventArgs.h index 19040f0bb1..e4ef6761ef 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.h +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.h @@ -10,7 +10,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationReceivedEventArgs(winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance const& backgroundTask); PushNotificationReceivedEventArgs(winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs const& args); - PushNotificationReceivedEventArgs(byte* payload, ULONG length); + PushNotificationReceivedEventArgs(byte* const& payload, ULONG const& length); com_array Payload(); winrt::Windows::ApplicationModel::Background::BackgroundTaskDeferral GetDeferral(); @@ -19,16 +19,15 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation bool Handled(); void Handled(bool value); - std::vector BuildPayload(uint8_t* payload, ULONG payloadLength); - private: + std::vector BuildPayload(winrt::Windows::Storage::Streams::IBuffer const& buffer); + std::vector BuildPayload(byte* const& payload, ULONG const& length); - std::vector m_rawNotificationPayload; - + std::vector m_rawNotificationPayload; const winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance m_backgroundTaskInstance{}; const winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs m_args = nullptr; - bool m_isUnpackagedApp; - bool m_handledUnpackaged = false; + bool m_unpackagedAppScenario; + bool m_handledUnpackaged = true; }; } diff --git a/dev/PushNotifications/PushNotifications.vcxitems b/dev/PushNotifications/PushNotifications.vcxitems index ae0ad30459..6787c2d61b 100644 --- a/dev/PushNotifications/PushNotifications.vcxitems +++ b/dev/PushNotifications/PushNotifications.vcxitems @@ -1,4 +1,4 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) @@ -10,7 +10,7 @@ %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) - + @@ -35,5 +35,6 @@ + \ No newline at end of file diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl b/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl index c27c6eac54..a1320b647c 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl +++ b/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl @@ -11,7 +11,7 @@ import "ocidl.idl"; [pointer_default(unique)] interface IWpnForegroundSink : IUnknown { - HRESULT InvokeAll([in] ULONG length, [in, string] byte data[]); + HRESULT InvokeAll([in] ULONG length, [in, size_is(length)] byte* data, [out] BOOL* foregroundHandled); }; [object] @@ -23,7 +23,9 @@ interface INotificationsLongRunningPlatform : IUnknown HRESULT RegisterForegroundActivator([in] IWpnForegroundSink* sink, [in] LPCWSTR processName); - HRESULT SendBackgroundNotification([in] LPCWSTR processName, [in, string] byte data[], [in] ULONG length); + HRESULT UnregisterForegroundActivator([in] LPCWSTR processName); + + HRESULT SendBackgroundNotification([in] LPCWSTR processName, [in] ULONG length, [in, size_is(length)] byte* data); }; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp index 4b7d8d320f..1721f7f25c 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp @@ -5,22 +5,32 @@ #include #include -void ForegroundSinkManager::Add(std::wstring processName, IWpnForegroundSink* sink) +void ForegroundSinkManager::Add(std::wstring const& processName, IWpnForegroundSink* const& sink) { + auto lock = m_lock.lock_exclusive(); m_foregroundMap[processName] = sink; } -void ForegroundSinkManager::Remove(std::wstring processName) +void ForegroundSinkManager::Remove(std::wstring const& processName) { + auto lock = m_lock.lock_exclusive(); m_foregroundMap.erase(processName); } -bool ForegroundSinkManager::InvokeForegroundHandlers(std::wstring processName, byte* payload, ULONG payloadSize) +bool ForegroundSinkManager::InvokeForegroundHandlers(std::wstring const& processName, byte* const& payload, ULONG const& payloadSize) { - if (m_foregroundMap.find(processName) != m_foregroundMap.end()) + auto lock = m_lock.lock_exclusive(); + + auto it = m_foregroundMap.find(processName); + if (it != m_foregroundMap.end()) { - LOG_IF_FAILED(m_foregroundMap[processName]->InvokeAll(payloadSize, payload)); - return true; + BOOL foregroundHandled = true; + if (FAILED(it->second->InvokeAll(payloadSize, payload, &foregroundHandled))) + { + Remove(processName); + return false; + } + return foregroundHandled; } return false; } diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h index fe25e15284..16ff63e8c1 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h @@ -11,13 +11,16 @@ class ForegroundSinkManager public: ForegroundSinkManager() = default; - void Add(std::wstring processName, IWpnForegroundSink* sink); + void Add(std::wstring const& processName, IWpnForegroundSink* const& sink); - void Remove(std::wstring processName); + void Remove(std::wstring const& processName); - bool InvokeForegroundHandlers(std::wstring processName, byte* payload, ULONG payloadSize); + bool InvokeForegroundHandlers(std::wstring const& processName, byte* const& payload, ULONG const& payloadSize); private: + // An app can only have one activate foreground sink with Long Running Process. Event handlers in + // the sink are managed by the WindowsAppSDK. std::unordered_map> m_foregroundMap = {}; + wil::srwlock m_lock; }; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp index 50766d8352..34147c2e26 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp @@ -64,15 +64,16 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterF return S_OK; } -STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::SendBackgroundNotification(_In_ PCWSTR processName, _In_ byte* payload, _In_ ULONG payloadSize) -{ - return S_OK; -} - -void NotificationsLongRunningPlatformImpl::UnregisterForegroundActivator(_In_ PCWSTR processName) +STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::UnregisterForegroundActivator(_In_ PCWSTR processName) { + RETURN_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); auto lock = m_lock.lock_exclusive(); m_foregroundSinkManager.Remove(processName); + return S_OK; } +STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::SendBackgroundNotification(_In_ PCWSTR processName, _In_ ULONG payloadSize, _In_ byte* payload) +{ + return S_OK; +} diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h index d112a00569..129a586e8a 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h @@ -23,13 +23,12 @@ Microsoft::WRL::RuntimeClass< STDMETHOD(RegisterForegroundActivator)(_In_ IWpnForegroundSink* sink, _In_ PCWSTR processName); - STDMETHOD(SendBackgroundNotification)(_In_ PCWSTR processName, _In_ byte* payload, _In_ ULONG payloadSize); + STDMETHOD(UnregisterForegroundActivator)(_In_ PCWSTR processName); - /* Add your functions to retrieve the platform components */ - -private: + STDMETHOD(SendBackgroundNotification)(_In_ PCWSTR processName, _In_ ULONG payloadSize, _In_ byte* payload); - void UnregisterForegroundActivator(PCWSTR processName); + /* Add your functions to retrieve the platform components */ + private: wil::srwlock m_lock; diff --git a/dev/PushNotifications/externs.h b/dev/PushNotifications/externs.h index 19776f45fb..00edb56363 100644 --- a/dev/PushNotifications/externs.h +++ b/dev/PushNotifications/externs.h @@ -7,3 +7,8 @@ wil::unique_event& GetWaitHandleForArgs(); inline const winrt::hstring ACTIVATED_EVENT_ARGS_KEY = L"GlobalActivatedEventArgs"; + +inline HRESULT GetCurrentProcessPath(wil::unique_cotaskmem_string& processName) +{ + return wil::GetModuleFileNameExW(GetCurrentProcess(), nullptr, processName); +}; From ad2b0d0a8ec2d305bccfc3a78f4763c7c2bff409 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Tue, 31 Aug 2021 19:39:10 -0700 Subject: [PATCH 12/13] Use com_array instead of byte* --- .../ForegroundSinkManager.cpp | 4 ++-- .../PushNotificationsLongRunningTask/ForegroundSinkManager.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp index 1721f7f25c..4849a0735d 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp @@ -17,7 +17,7 @@ void ForegroundSinkManager::Remove(std::wstring const& processName) m_foregroundMap.erase(processName); } -bool ForegroundSinkManager::InvokeForegroundHandlers(std::wstring const& processName, byte* const& payload, ULONG const& payloadSize) +bool ForegroundSinkManager::InvokeForegroundHandlers(std::wstring const& processName, winrt::com_array const& payload, ULONG const& payloadSize) { auto lock = m_lock.lock_exclusive(); @@ -25,7 +25,7 @@ bool ForegroundSinkManager::InvokeForegroundHandlers(std::wstring const& process if (it != m_foregroundMap.end()) { BOOL foregroundHandled = true; - if (FAILED(it->second->InvokeAll(payloadSize, payload, &foregroundHandled))) + if (FAILED(it->second->InvokeAll(payloadSize, payload.data(), &foregroundHandled))) { Remove(processName); return false; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h index 16ff63e8c1..19e99bc885 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h @@ -15,7 +15,7 @@ class ForegroundSinkManager void Remove(std::wstring const& processName); - bool InvokeForegroundHandlers(std::wstring const& processName, byte* const& payload, ULONG const& payloadSize); + bool InvokeForegroundHandlers(std::wstring const& processName, winrt::com_array const& payload, ULONG const& payloadSize); private: // An app can only have one activate foreground sink with Long Running Process. Event handlers in From 23513161ee7ff285ebea3ffb07aaccb86a1c1942 Mon Sep 17 00:00:00 2001 From: Paul Purifoy <33183370+pmpurifoy@users.noreply.github.com> Date: Tue, 31 Aug 2021 19:39:44 -0700 Subject: [PATCH 13/13] Update dev/PushNotifications/PushNotificationDummyDeferral.h Co-authored-by: Daniel Ayala <14967941+danielayala94@users.noreply.github.com> --- dev/PushNotifications/PushNotificationDummyDeferral.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dev/PushNotifications/PushNotificationDummyDeferral.h b/dev/PushNotifications/PushNotificationDummyDeferral.h index 66513f53e7..35a3e826ba 100644 --- a/dev/PushNotifications/PushNotificationDummyDeferral.h +++ b/dev/PushNotifications/PushNotificationDummyDeferral.h @@ -10,10 +10,7 @@ struct PushNotificationDummyDeferral : winrt::implements