// dllmain.cpp : Defines the entry point for the DLL application. #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include #include #include #include #include "DesktopToasts.h" #include "DesktopNotificationManagerCompat.h" #define RETURN_IF_FAILED(hr) do { HRESULT _hrTemp = hr; if (FAILED(_hrTemp)) { return _hrTemp; } } while (false) using namespace ABI::Windows::Data::Xml::Dom; using namespace ABI::Windows::UI::Notifications; using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; DesktopToastActivateHandler g_handler = nullptr; void* g_handlerContext = nullptr; class DECLSPEC_UUID("E407B70A-1FBD-4D5E-8822-231C69102472") NotificationActivator WrlSealed WrlFinal : public RuntimeClass, INotificationActivationCallback> { public: virtual HRESULT STDMETHODCALLTYPE Activate( _In_ LPCWSTR appUserModelId, _In_ LPCWSTR invokedArgs, _In_reads_(dataCount) const NOTIFICATION_USER_INPUT_DATA * data, ULONG dataCount) override { if (g_handler) g_handler(g_handlerContext, invokedArgs); return S_OK; } }; // Flag class as COM creatable CoCreatableClass(NotificationActivator); HRESULT Initialize(LPCWSTR appUserModelId, DesktopToastActivateHandler handler, void* handlerContext) { RETURN_IF_FAILED(DesktopNotificationManagerCompat::RegisterAumidAndComServer(appUserModelId, __uuidof(NotificationActivator))); RETURN_IF_FAILED(DesktopNotificationManagerCompat::RegisterActivator()); g_handler = handler; g_handlerContext = handlerContext; return S_OK; } HRESULT SetNodeValueString(HSTRING inputString, IXmlNode* node, IXmlDocument* xml) { ComPtr inputText; RETURN_IF_FAILED(xml->CreateTextNode(inputString, &inputText)); ComPtr inputTextNode; RETURN_IF_FAILED(inputText.As(&inputTextNode)); ComPtr appendedChild; return node->AppendChild(inputTextNode.Get(), &appendedChild); } _Use_decl_annotations_ HRESULT SetTextValues(const PCWSTR* textValues, UINT32 textValuesCount, IXmlDocument* toastXml) { ComPtr nodeList; RETURN_IF_FAILED(toastXml->GetElementsByTagName(HStringReference(L"text").Get(), &nodeList)); UINT32 nodeListLength; RETURN_IF_FAILED(nodeList->get_Length(&nodeListLength)); // If a template was chosen with fewer text elements, also change the amount of strings // passed to this method. RETURN_IF_FAILED(textValuesCount <= nodeListLength ? S_OK : E_INVALIDARG); for (UINT32 i = 0; i < textValuesCount; i++) { ComPtr textNode; RETURN_IF_FAILED(nodeList->Item(i, &textNode)); RETURN_IF_FAILED(SetNodeValueString(HStringReference(textValues[i]).Get(), textNode.Get(), toastXml)); } return S_OK; } HRESULT DisplaySimpleToast(LPCWSTR title, LPCWSTR text) { // Construct XML ComPtr doc; HRESULT hr = DesktopNotificationManagerCompat::CreateXmlDocumentFromString(L"", &doc); if (SUCCEEDED(hr)) { PCWSTR textValues[] = { title, text }; SetTextValues(textValues, ARRAYSIZE(textValues), doc.Get()); // Create the notifier // Classic Win32 apps MUST use the compat method to create the notifier ComPtr notifier; hr = DesktopNotificationManagerCompat::CreateToastNotifier(¬ifier); if (SUCCEEDED(hr)) { // Create the notification itself (using helper method from compat library) ComPtr toast; hr = DesktopNotificationManagerCompat::CreateToastNotification(doc.Get(), &toast); if (SUCCEEDED(hr)) { // And show it! hr = notifier->Show(toast.Get()); } } } return hr; } BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }