ReactOS  0.4.15-dev-1171-gab82533
CUserNotification.cpp
Go to the documentation of this file.
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:
23 
24 public:
25  CQueryContinue(HRESULT hContinue = S_OK) : m_hContinue(hContinue) {}
27 
29  {
30  if (this != &qc)
32  return *this;
33  }
34 
36  {
37  m_hContinue = hContinue;
38  return *this;
39  }
40 
41  operator HRESULT()
42  {
43  return m_hContinue;
44  }
45 
46 public:
47  // IUnknown
49  {
50  return 1;
51  }
52 
54  {
55  return 0;
56  }
57 
59  {
60  return S_OK;
61  }
62 
63  // IQueryContinue
65  {
66  // TRACE("IQueryContinue::QueryContinue() returning 0x%lx\n", m_hContinue);
67  return m_hContinue;
68  }
69 };
70 
71 
72 static 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)UlongToHandle(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);
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);
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);
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 */
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 */
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
177 {
178  /* Initialize COM */
180 
181  /* Start the test */
183 
184  /* Cleanup and return */
185  CoUninitialize();
186  return 0;
187 }
188 
190 {
191  HANDLE hThread;
192  DWORD dwWait;
193 
194  /* We create a test thread, because the notification tests can hang */
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!\n");
200  return;
201  }
202 
203  /* Wait a maximum of 60 seconds for the thread to finish (the timeout tests take some time) */
204  dwWait = WaitForSingleObject(hThread, 60 * 1000);
205  ok(dwWait == WAIT_OBJECT_0, "WaitForSingleObject returned %lu, expected WAIT_OBJECT_0\n", dwWait);
206 
207  /* Cleanup and return */
209 }
#define HRESULT
Definition: msvc.h:7
static HICON
Definition: imagelist.c:84
#define REFIID
Definition: guiddef.h:118
#define CloseHandle
Definition: compat.h:487
HRESULT hr
Definition: shlfolder.c:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
REFIID riid
Definition: precomp.h:44
#define CALLBACK
Definition: compat.h:35
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
CQueryContinue & operator=(const CQueryContinue &qc)
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define S_FALSE
Definition: winerror.h:2357
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:136
smooth NULL
Definition: ftsmooth.c:416
START_TEST(CUserNotification)
#define WAIT_OBJECT_0
Definition: winbase.h:387
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
LONG HRESULT
Definition: typedefs.h:79
#define UlongToHandle(ul)
Definition: basetsd.h:97
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
unsigned long DWORD
Definition: ntddk_ex.h:95
#define HRESULT_CANCELLED
DWORD CALLBACK TestThread(LPVOID lpParam)
static void TestNotification(void)
static const WCHAR L[]
Definition: oid.c:1250
CQueryContinue(HRESULT hContinue=S_OK)
REFIID LPVOID * ppvObject
Definition: precomp.h:44
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
virtual HRESULT STDMETHODCALLTYPE QueryContinue(void)
#define S_OK
Definition: intsafe.h:51
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
#define ok(value,...)
Definition: atltest.h:57
HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
Definition: compobj.c:2002
HANDLE hThread
Definition: wizard.c:27
#define skip(...)
Definition: atltest.h:64
CQueryContinue & operator=(HRESULT hContinue)
unsigned int ULONG
Definition: retypes.h:1
virtual ULONG STDMETHODCALLTYPE Release()
#define ok_hr(status, expected)
virtual ULONG STDMETHODCALLTYPE AddRef()