1 /* * Copyright (C) 2016-2019 Mohammed Boujemaoui <mohabouje@gmail.com> 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of 4 * this software and associated documentation files (the "Software"), to deal in 5 * the Software without restriction, including without limitation the rights to 6 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 * the Software, and to permit persons to whom the Software is furnished to do so, 8 * subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in all 11 * copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 */ 20 21 #ifndef WINTOASTLIB_H 22 #define WINTOASTLIB_H 23 #include <Windows.h> 24 #include <sdkddkver.h> 25 #include <WinUser.h> 26 #include <ShObjIdl.h> 27 #include <wrl/implements.h> 28 #include <wrl/event.h> 29 #include <windows.ui.notifications.h> 30 #include <strsafe.h> 31 #include <Psapi.h> 32 #include <ShlObj.h> 33 #include <roapi.h> 34 #include <propvarutil.h> 35 #include <functiondiscoverykeys.h> 36 #include <iostream> 37 #include <winstring.h> 38 #include <string.h> 39 #include <vector> 40 #include <map> 41 using namespace Microsoft::WRL; 42 using namespace ABI::Windows::Data::Xml::Dom; 43 using namespace ABI::Windows::Foundation; 44 using namespace ABI::Windows::UI::Notifications; 45 using namespace Windows::Foundation; 46 47 48 namespace WinToastLib { 49 50 class IWinToastHandler { 51 public: 52 enum WinToastDismissalReason { 53 UserCanceled = ToastDismissalReason::ToastDismissalReason_UserCanceled, 54 ApplicationHidden = ToastDismissalReason::ToastDismissalReason_ApplicationHidden, 55 TimedOut = ToastDismissalReason::ToastDismissalReason_TimedOut 56 }; 57 virtual ~IWinToastHandler() = default; 58 virtual void toastActivated() const = 0; 59 virtual void toastActivated(int actionIndex) const = 0; 60 virtual void toastDismissed(WinToastDismissalReason state) const = 0; 61 virtual void toastFailed() const = 0; 62 }; 63 64 class WinToastTemplate { 65 public: 66 enum Duration { System, Short, Long }; 67 enum AudioOption { Default = 0, Silent, Loop }; 68 enum TextField { FirstLine = 0, SecondLine, ThirdLine }; 69 enum WinToastTemplateType { 70 ImageAndText01 = ToastTemplateType::ToastTemplateType_ToastImageAndText01, 71 ImageAndText02 = ToastTemplateType::ToastTemplateType_ToastImageAndText02, 72 ImageAndText03 = ToastTemplateType::ToastTemplateType_ToastImageAndText03, 73 ImageAndText04 = ToastTemplateType::ToastTemplateType_ToastImageAndText04, 74 Text01 = ToastTemplateType::ToastTemplateType_ToastText01, 75 Text02 = ToastTemplateType::ToastTemplateType_ToastText02, 76 Text03 = ToastTemplateType::ToastTemplateType_ToastText03, 77 Text04 = ToastTemplateType::ToastTemplateType_ToastText04, 78 }; 79 80 enum AudioSystemFile { 81 DefaultSound, 82 IM, 83 Mail, 84 Reminder, 85 SMS, 86 Alarm, 87 Alarm2, 88 Alarm3, 89 Alarm4, 90 Alarm5, 91 Alarm6, 92 Alarm7, 93 Alarm8, 94 Alarm9, 95 Alarm10, 96 Call, 97 Call1, 98 Call2, 99 Call3, 100 Call4, 101 Call5, 102 Call6, 103 Call7, 104 Call8, 105 Call9, 106 Call10, 107 }; 108 109 110 WinToastTemplate(_In_ WinToastTemplateType type = WinToastTemplateType::ImageAndText02); 111 ~WinToastTemplate(); 112 113 void setFirstLine(_In_ const std::wstring& text); 114 void setSecondLine(_In_ const std::wstring& text); 115 void setThirdLine(_In_ const std::wstring& text); 116 void setTextField(_In_ const std::wstring& txt, _In_ TextField pos); 117 void setAttributionText(_In_ const std::wstring & attributionText); 118 void setImagePath(_In_ const std::wstring& imgPath); 119 void setAudioPath(_In_ WinToastTemplate::AudioSystemFile audio); 120 void setAudioPath(_In_ const std::wstring& audioPath); 121 void setAudioOption(_In_ WinToastTemplate::AudioOption audioOption); 122 void setDuration(_In_ Duration duration); 123 void setExpiration(_In_ INT64 millisecondsFromNow); 124 void addAction(_In_ const std::wstring& label); 125 126 std::size_t textFieldsCount() const; 127 std::size_t actionsCount() const; 128 bool hasImage() const; 129 const std::vector<std::wstring>& textFields() const; 130 const std::wstring& textField(_In_ TextField pos) const; 131 const std::wstring& actionLabel(_In_ std::size_t pos) const; 132 const std::wstring& imagePath() const; 133 const std::wstring& audioPath() const; 134 const std::wstring& attributionText() const; 135 INT64 expiration() const; 136 WinToastTemplateType type() const; 137 WinToastTemplate::AudioOption audioOption() const; 138 Duration duration() const; 139 private: 140 std::vector<std::wstring> _textFields{}; 141 std::vector<std::wstring> _actions{}; 142 std::wstring _imagePath{}; 143 std::wstring _audioPath{}; 144 std::wstring _attributionText{}; 145 INT64 _expiration{0}; 146 AudioOption _audioOption{WinToastTemplate::AudioOption::Default}; 147 WinToastTemplateType _type{WinToastTemplateType::Text01}; 148 Duration _duration{Duration::System}; 149 }; 150 151 class WinToast { 152 public: 153 enum WinToastError { 154 NoError = 0, 155 NotInitialized, 156 SystemNotSupported, 157 ShellLinkNotCreated, 158 InvalidAppUserModelID, 159 InvalidParameters, 160 InvalidHandler, 161 NotDisplayed, 162 UnknownError 163 }; 164 165 enum ShortcutResult { 166 SHORTCUT_UNCHANGED = 0, 167 SHORTCUT_WAS_CHANGED = 1, 168 SHORTCUT_WAS_CREATED = 2, 169 170 SHORTCUT_MISSING_PARAMETERS = -1, 171 SHORTCUT_INCOMPATIBLE_OS = -2, 172 SHORTCUT_COM_INIT_FAILURE = -3, 173 SHORTCUT_CREATE_FAILED = -4 174 }; 175 176 enum ShortcutPolicy { 177 /* Don't check, create, or modify a shortcut. */ 178 SHORTCUT_POLICY_IGNORE = 0, 179 /* Require a shortcut with matching AUMI, don't create or modify an existing one. */ 180 SHORTCUT_POLICY_REQUIRE_NO_CREATE = 1, 181 /* Require a shortcut with matching AUMI, create if missing, modify if not matching. 182 * This is the default. */ 183 SHORTCUT_POLICY_REQUIRE_CREATE = 2, 184 }; 185 186 WinToast(void); 187 virtual ~WinToast(); 188 static WinToast* instance(); 189 static bool isCompatible(); 190 static bool isSupportingModernFeatures(); 191 static std::wstring configureAUMI(_In_ const std::wstring& companyName, 192 _In_ const std::wstring& productName, 193 _In_ const std::wstring& subProduct = std::wstring(), 194 _In_ const std::wstring& versionInformation = std::wstring()); 195 static const std::wstring& strerror(_In_ WinToastError error); 196 virtual bool initialize(_Out_ WinToastError* error = nullptr); 197 virtual bool isInitialized() const; 198 virtual bool hideToast(_In_ INT64 id); 199 virtual INT64 showToast(_In_ const WinToastTemplate& toast, _In_ IWinToastHandler* handler, _Out_ WinToastError* error = nullptr); 200 virtual void clear(); 201 virtual enum ShortcutResult createShortcut(); 202 203 const std::wstring& appName() const; 204 const std::wstring& appUserModelId() const; 205 void setAppUserModelId(_In_ const std::wstring& aumi); 206 void setAppName(_In_ const std::wstring& appName); 207 void setShortcutPolicy(_In_ ShortcutPolicy policy); 208 209 protected: 210 bool _isInitialized{false}; 211 bool _hasCoInitialized{false}; 212 ShortcutPolicy _shortcutPolicy{SHORTCUT_POLICY_REQUIRE_CREATE}; 213 std::wstring _appName{}; 214 std::wstring _aumi{}; 215 std::map<INT64, ComPtr<IToastNotification>> _buffer{}; 216 217 HRESULT validateShellLinkHelper(_Out_ bool& wasChanged); 218 HRESULT createShellLinkHelper(); 219 HRESULT setImageFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& path); 220 HRESULT setAudioFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& path, _In_opt_ WinToastTemplate::AudioOption option = WinToastTemplate::AudioOption::Default); 221 HRESULT setTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& text, _In_ UINT32 pos); 222 HRESULT setAttributionTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& text); 223 HRESULT addActionHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& action, _In_ const std::wstring& arguments); 224 HRESULT addDurationHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& duration); 225 ComPtr<IToastNotifier> notifier(_In_ bool* succeded) const; 226 void setError(_Out_ WinToastError* error, _In_ WinToastError value); 227 }; 228 } 229 #endif // WINTOASTLIB_H 230