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