[SHELL32][APITESTS] Add tests of OpenAs_RunDLL
[reactos.git] / modules / rostests / apitests / shell32 / CUserNotification.cpp
1 /*
2 * PROJECT: ReactOS API tests
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Test for CUserNotification
5 * COPYRIGHT: Copyright 2018 Hermes Belusca-Maito
6 */
7
8 #include "shelltest.h"
9
10 #define NDEBUG
11 #include <debug.h>
12
13 #define ok_hr(status, expected) ok_hex(status, expected)
14
15 #define HRESULT_CANCELLED HRESULT_FROM_WIN32(ERROR_CANCELLED)
16
17
18 /* An implementation of the IQueryContinue interface */
19 class CQueryContinue : public IQueryContinue
20 {
21 private:
22 HRESULT m_hContinue;
23
24 public:
25 CQueryContinue(HRESULT hContinue = S_OK) : m_hContinue(hContinue) {}
26 ~CQueryContinue() {}
27
28 CQueryContinue& operator=(const CQueryContinue& qc)
29 {
30 if (this != &qc)
31 m_hContinue = qc.m_hContinue;
32 return *this;
33 }
34
35 CQueryContinue& operator=(HRESULT hContinue)
36 {
37 m_hContinue = hContinue;
38 return *this;
39 }
40
41 operator HRESULT()
42 {
43 return m_hContinue;
44 }
45
46 public:
47 // IUnknown
48 virtual ULONG STDMETHODCALLTYPE AddRef()
49 {
50 return 1;
51 }
52
53 virtual ULONG STDMETHODCALLTYPE Release()
54 {
55 return 0;
56 }
57
58 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
59 {
60 return S_OK;
61 }
62
63 // IQueryContinue
64 virtual HRESULT STDMETHODCALLTYPE QueryContinue(void)
65 {
66 // TRACE("IQueryContinue::QueryContinue() returning 0x%lx\n", m_hContinue);
67 return m_hContinue;
68 }
69 };
70
71
72 static void
73 TestNotification(void)
74 {
75 HRESULT hr;
76 CComPtr<IUserNotification> pUserNotif;
77 CQueryContinue queryContinue(S_OK);
78
79 // hr = pUserNotif.CoCreateInstance(CLSID_UserNotification);
80 hr = ::CoCreateInstance(CLSID_UserNotification, NULL, CLSCTX_ALL,
81 /*IID_PPV_ARG(IUserNotification, &pUserNotif)*/
82 IID_IUserNotification, (void**)&pUserNotif);
83 ok(hr == S_OK, "CoCreateInstance, hr = 0x%lx\n", hr);
84 if (FAILED(hr))
85 {
86 skip("Could not instantiate IUserNotification\n");
87 return;
88 }
89
90 /* Set an invalid icon for the notification icon */
91 hr = pUserNotif->SetIconInfo((HICON)0xdeadbeef, L"Tooltip text");
92 ok_hr(hr, S_OK);
93
94 #if 0
95 /* Seting an invalid string would crash the application */
96 hr = pUserNotif->SetIconInfo(NULL, (LPCWSTR)0xdeadbeef);
97 ok_hr(hr, S_OK);
98 #endif
99
100 /* Set a default icon for the notification icon */
101 hr = pUserNotif->SetIconInfo(NULL, L"Tooltip text");
102 ok_hr(hr, S_OK);
103
104 /*
105 * Since just displaying a notification icon without balloon hangs (expected),
106 * for making this test automatable we instead just test balloon functionality
107 * where timeouts can be programmed.
108 */
109
110 /* Set up a balloon associated to the notification icon */
111 hr = pUserNotif->SetBalloonInfo(L"Balloon title", L"Balloon text", NIIF_ERROR);
112 ok_hr(hr, S_OK);
113
114 /*
115 * Try to display twice the balloon if the user cancels it.
116 * Without setting balloon retry, we would wait for a very long time...
117 */
118 hr = pUserNotif->SetBalloonRetry(2000, 1000, 2);
119 ok_hr(hr, S_OK);
120
121 /* Display the balloon and also the tooltip if one points on the icon */
122 hr = pUserNotif->Show(NULL, 0);
123 ok_hr(hr, HRESULT_CANCELLED);
124
125 /*
126 * Setting icon information *after* having enabled balloon info,
127 * allows to automatically set the notification icon according
128 * to the dwInfoFlags passed to SetBalloonInfo() and by giving
129 * NULL to the hIcon parameter of SetIconInfo().
130 */
131 hr = pUserNotif->SetIconInfo(NULL, NULL);
132 ok_hr(hr, S_OK);
133
134 /* Display the balloon and also the tooltip if one points on the icon */
135 hr = pUserNotif->Show(NULL, 0);
136 ok_hr(hr, HRESULT_CANCELLED);
137
138 /*
139 * This line shows the balloon, but without title nor icon in it.
140 * Note that the balloon icon is not displayed when not setting any title.
141 */
142 hr = pUserNotif->SetBalloonInfo(NULL, L"Balloon text", NIIF_WARNING);
143 ok_hr(hr, S_OK);
144
145 hr = pUserNotif->Show(NULL, 0);
146 ok_hr(hr, HRESULT_CANCELLED);
147
148
149 /* Test support of the IQueryContinue interface */
150
151 hr = pUserNotif->SetBalloonInfo(L"Balloon title", L"Balloon text", NIIF_WARNING);
152 ok_hr(hr, S_OK);
153
154 hr = pUserNotif->Show(&queryContinue, 2000); /* Timeout of 2 seconds */
155 ok_hr(hr, HRESULT_CANCELLED);
156
157 #if 0 // Commented because this test (the Show() call) is unreliable.
158 /* Try to hide the balloon by setting an empty string (can use either NULL or L"") */
159 hr = pUserNotif->SetBalloonInfo(L"Balloon title", NULL, NIIF_WARNING);
160 ok_hr(hr, S_OK);
161
162 hr = pUserNotif->Show(&queryContinue, 2000); /* Timeout of 2 seconds */
163 ok_hr(hr, HRESULT_CANCELLED);
164 #endif
165
166 hr = pUserNotif->SetBalloonInfo(L"Balloon title", L"Balloon text", NIIF_WARNING);
167 ok_hr(hr, S_OK);
168
169 queryContinue = S_FALSE;
170 hr = pUserNotif->Show(&queryContinue, 2000); /* Timeout of 2 seconds */
171 ok_hr(hr, S_FALSE);
172 }
173
174 DWORD
175 CALLBACK
176 TestThread(LPVOID lpParam)
177 {
178 /* Initialize COM */
179 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
180
181 /* Start the test */
182 TestNotification();
183
184 /* Cleanup and return */
185 CoUninitialize();
186 return 0;
187 }
188
189 START_TEST(CUserNotification)
190 {
191 HANDLE hThread;
192 DWORD dwWait;
193
194 /* We create a test thread, because the notification tests can hang */
195 hThread = CreateThread(NULL, 0, TestThread, NULL, 0, NULL);
196 ok(hThread != NULL, "CreateThread failed with error 0x%lu\n", GetLastError());
197 if (!hThread)
198 {
199 skip("Could not create the CUserNotification test thread!");
200 return;
201 }
202
203 /* Wait a maximum of 1:30 for the thread to finish (the timeout tests take some time) */
204 dwWait = WaitForSingleObject(hThread, 90 * 1000);
205 ok(dwWait == WAIT_OBJECT_0, "WaitForSingleObject returned %lu, expected WAIT_OBJECT_0\n", dwWait);
206
207 /* Cleanup and return */
208 CloseHandle(hThread);
209 }