ReactOS  0.4.14-dev-317-g96040ec
IACLCustomMRU.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 IACLCustomMRU objects
5  * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #define _UNICODE
9 #define UNICODE
10 #include <apitest.h>
11 #include <shlobj.h>
12 #include <atlbase.h>
13 #include <atlstr.h>
14 #include <atlcom.h>
15 #include <atlwin.h>
16 
17 // Yes, gcc at it again, let's validate everything found inside unused templates!
19 
20 #include <shellutils.h>
21 #include <shlwapi.h>
22 #include <strsafe.h>
23 #include <initguid.h>
24 
25 #define ok_hex_(file, line, key, expression, result) \
26  do { \
27  int _value = (expression); \
28  ok_(file, line)(_value == (result), "Wrong value for '%s', expected: " #result " (0x%x), got: 0x%x for %c\n", \
29  #expression, (int)(result), _value, (char)key); \
30  } while (0)
31 
32 
33 
34 struct CCoInit
35 {
38  HRESULT hres;
39 };
40 
41 
42 DEFINE_GUID(IID_IACLCustomMRU, 0xf729fc5e, 0x8769, 0x4f3e, 0xbd, 0xb2, 0xd7, 0xb5, 0x0f, 0xd2, 0x27, 0x5b);
43 static const WCHAR szTestPath[] = L"TESTPATH_BROWSEUI_APITEST";
44 
45 #undef INTERFACE
46 #define INTERFACE IACLCustomMRU
47 
48 /* based on https://msdn.microsoft.com/en-gb/library/windows/desktop/bb776380(v=vs.85).aspx */
49 DECLARE_INTERFACE_IID_(IACLCustomMRU, IUnknown, "F729FC5E-8769-4F3E-BDB2-D7B50FD2275B")
50 {
51  // *** IUnknown methods ***
55 
56  // *** IACLCustomMRU methods ***
57  STDMETHOD(Initialize) (THIS_ LPCWSTR pwszMRURegKey, DWORD dwMax) PURE;
58  STDMETHOD(AddMRUString) (THIS_ LPCWSTR pwszEntry) PURE;
59 };
60 
61 
62 static void Cleanup_Testdata()
63 {
64  CRegKey tmp;
67 }
68 
69 #define verify_mru(mru, ...) verify_mru_(__FILE__, __LINE__, mru, __VA_ARGS__, NULL)
70 static void verify_mru_(const char* file, int line, IACLCustomMRU* mru, PCWSTR MRUString, ...)
71 {
72 
73  CRegKey key;
75 
76  va_list args;
77  va_start(args, MRUString);
78  PCWSTR Entry;
79  WCHAR Key = L'a';
80  while ((Entry = va_arg(args, PCWSTR)))
81  {
83  ULONG nChars = _countof(Value);
84  CStringW tmp;
85  tmp += Key;
86  LSTATUS Status = key.QueryStringValue(tmp, Value, &nChars);
88  if (Status == ERROR_SUCCESS)
89  {
90  ok_(file, line)(!wcscmp(Value, Entry), "Expected value %c to be %S, was %S\n", (char)Key, Entry, Value);
91  }
92  Key++;
93  }
94  va_end(args);
95 
96  if (Key != L'a')
97  {
99  ULONG nChars = _countof(Value);
100  LSTATUS Status = key.QueryStringValue(L"MRUList", Value, &nChars);
102  if (Status == ERROR_SUCCESS)
103  {
104  ok_(file, line)(!wcscmp(Value, MRUString), "Expected MRUList to be %S, was %S\n", MRUString, Value);
105  }
106  }
107 }
108 
109 
110 static void
112 {
113  CComPtr<IACLCustomMRU> CustomMRU;
114  HRESULT hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
115  ok_hex(hr, S_OK);
116  if (!SUCCEEDED(hr))
117  return;
118 
120 
121  /* Initialize with a NULL name will cause an AV */
122  //hr = CustomMRU->Initialize(NULL, 0);
123 
124  hr = CustomMRU->Initialize(szTestPath, 0);
125  ok_hex(hr, S_OK);
126  /* Adding an entry with a dwMax of 0 will cause an AV */
127 
128  /* Calling it again will resize */
129  hr = CustomMRU->Initialize(szTestPath, 3);
130  ok_hex(hr, S_OK);
131  verify_mru(CustomMRU, L"");
132 
133  hr = CustomMRU->AddMRUString(L"FIRST_ENTRY");
134  ok_hex(hr, S_OK);
135  verify_mru(CustomMRU, L"a", L"FIRST_ENTRY");
136 
137  hr = CustomMRU->AddMRUString(L"SECOND_ENTRY");
138  ok_hex(hr, S_OK);
139  verify_mru(CustomMRU, L"ba", L"FIRST_ENTRY", L"SECOND_ENTRY");
140 
141  hr = CustomMRU->AddMRUString(L"THIRD_ENTRY");
142  ok_hex(hr, S_OK);
143  verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
144 
145  /* First entry is replaced */
146  hr = CustomMRU->AddMRUString(L"FOURTH_ENTRY");
147  ok_hex(hr, S_OK);
148  verify_mru(CustomMRU, L"acb", L"FOURTH_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
149 
150  /* Second entry is replaced */
151  hr = CustomMRU->AddMRUString(L"FIFTH_ENTRY");
152  ok_hex(hr, S_OK);
153  verify_mru(CustomMRU, L"bac", L"FOURTH_ENTRY", L"FIFTH_ENTRY", L"THIRD_ENTRY");
154 }
155 
156 
157 static void FillDefault(IACLCustomMRU* CustomMRU)
158 {
160  HRESULT hr = CustomMRU->Initialize(szTestPath, 3);
161  ok_hex(hr, S_OK);
162  hr = CustomMRU->AddMRUString(L"FIRST_ENTRY");
163  ok_hex(hr, S_OK);
164  hr = CustomMRU->AddMRUString(L"SECOND_ENTRY");
165  ok_hex(hr, S_OK);
166  hr = CustomMRU->AddMRUString(L"THIRD_ENTRY");
167  ok_hex(hr, S_OK);
168 }
169 
170 static void
172 {
173  CComPtr<IACLCustomMRU> CustomMRU;
174  HRESULT hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
175  ok_hex(hr, S_OK);
176  if (!SUCCEEDED(hr))
177  return;
178 
180  FillDefault(CustomMRU);
181  verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
182 
183  /* Add the first entry again */
184  hr = CustomMRU->AddMRUString(L"FIRST_ENTRY");
185  ok_hex(hr, S_OK);
186  /* No change */
187  verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
188 
189  CustomMRU.Release();
190  /* Now the order is updated */
191  verify_mru(NULL, L"acb", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
192 
193 
194  hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
195  ok_hex(hr, S_OK);
196  if (!SUCCEEDED(hr))
197  return;
198 
200  FillDefault(CustomMRU);
201  verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
202 
203 
204  /* Add the first entry again */
205  hr = CustomMRU->AddMRUString(L"FIRST_ENTRY");
206  ok_hex(hr, S_OK);
207  /* No change */
208  verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
209 
210  hr = CustomMRU->AddMRUString(L"SOMETHING_ELSE");
211  ok_hex(hr, S_OK);
212  /* Now all changes are persisted */
213  verify_mru(CustomMRU, L"bac", L"FIRST_ENTRY", L"SOMETHING_ELSE", L"THIRD_ENTRY");
214 }
215 
216 static void
218 {
219  CComPtr<IACLCustomMRU> CustomMRU;
220  HRESULT hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
221  ok_hex(hr, S_OK);
222  if (!SUCCEEDED(hr))
223  return;
224 
226 
227  /* Still returnes success */
228  hr = CustomMRU->Initialize(szTestPath, 30);
229  ok_hex(hr, S_OK);
230 
231  for (int n = 0; n < 30; ++n)
232  {
233  CStringW tmp;
234  tmp.Format(L"%d", n);
235 
236  hr = CustomMRU->AddMRUString(tmp);
237  ok_hex(hr, S_OK);
238  }
239  /* But is starting to wrap around */
240  verify_mru(CustomMRU, L"a}|{zyxwvutsrqponmlkjihgfedcb", L"29",
241  L"1", L"2", L"3", L"4", L"5", L"6", L"7", L"8", L"9",
242  L"10", L"11", L"12", L"13", L"14", L"15", L"16", L"17", L"18", L"19",
243  L"20", L"21", L"22", L"23", L"24", L"25", L"26", L"27", L"28");
244 
246 }
247 
248 static void
250 {
251  CComPtr<IACLCustomMRU> CustomMRU;
252  HRESULT hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
253  ok_hex(hr, S_OK);
254  if (!SUCCEEDED(hr))
255  return;
256 
258  FillDefault(CustomMRU);
259  verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
260 
261  CustomMRU.Release();
262 
263  hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
264  ok_hex(hr, S_OK);
265  if (!SUCCEEDED(hr))
266  return;
267 
268  hr = CustomMRU->Initialize(szTestPath, 3);
269  ok_hex(hr, S_OK);
270 
271  /* First entry is replaced */
272  hr = CustomMRU->AddMRUString(L"FOURTH_ENTRY");
273  ok_hex(hr, S_OK);
274  verify_mru(CustomMRU, L"acb", L"FOURTH_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
275 
276  CustomMRU.Release();
277 
278  hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
279  ok_hex(hr, S_OK);
280  if (!SUCCEEDED(hr))
281  return;
282 
283  hr = CustomMRU->Initialize(szTestPath, 3);
284  ok_hex(hr, S_OK);
285 
286  /* Second entry is replaced */
287  hr = CustomMRU->AddMRUString(L"FIFTH_ENTRY");
288  ok_hex(hr, S_OK);
289  verify_mru(CustomMRU, L"bac", L"FOURTH_ENTRY", L"FIFTH_ENTRY", L"THIRD_ENTRY");
290 
291  CustomMRU.Release();
292 
293  hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
294  ok_hex(hr, S_OK);
295  if (!SUCCEEDED(hr))
296  return;
297 
298 
299  /* Save some garbage */
300  CRegKey key;
302  key.SetStringValue(L"MRUList", L"b**");
303  key.Close();
304 
305  hr = CustomMRU->Initialize(szTestPath, 3);
306  ok_hex(hr, S_OK);
307 
308  CustomMRU.Release();
309 
310  /* Not cleaned up */
311  verify_mru(CustomMRU, L"b**", L"FOURTH_ENTRY", L"FIFTH_ENTRY", L"THIRD_ENTRY");
312 
313  hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
314  ok_hex(hr, S_OK);
315  if (!SUCCEEDED(hr))
316  return;
317 
318  hr = CustomMRU->Initialize(szTestPath, 3);
319  ok_hex(hr, S_OK);
320 
321  /* Now it's just cleaned up */
322  hr = CustomMRU->AddMRUString(L"SIXTH_ENTRY");
323  ok_hex(hr, S_OK);
324  verify_mru(CustomMRU, L"ab", L"SIXTH_ENTRY");
325 
326  CustomMRU.Release();
327 
328  hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
329  ok_hex(hr, S_OK);
330  if (!SUCCEEDED(hr))
331  return;
332 
334  FillDefault(CustomMRU);
335  verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
336 
337  CustomMRU.Release();
338 
339  hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
340  ok_hex(hr, S_OK);
341  if (!SUCCEEDED(hr))
342  return;
343 
345  key.SetStringValue(L"MRUList", L"baccccc");
346  key.Close();
347 
348  hr = CustomMRU->Initialize(szTestPath, 3);
349  ok_hex(hr, S_OK);
350  CustomMRU.Release();
351 
352  verify_mru(CustomMRU, L"baccccc", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
353 
354  hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
355  ok_hex(hr, S_OK);
356  if (!SUCCEEDED(hr))
357  return;
358 
359  hr = CustomMRU->Initialize(szTestPath, 3);
360  ok_hex(hr, S_OK);
361 
362  hr = CustomMRU->AddMRUString(L"FOURTH_ENTRY");
363  ok_hex(hr, S_OK);
364  verify_mru(CustomMRU, L"a", L"FOURTH_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
365 
366  CustomMRU.Release();
368 
369  hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
370  ok_hex(hr, S_OK);
371  if (!SUCCEEDED(hr))
372  return;
373 
374  hr = CustomMRU->Initialize(szTestPath, 3);
375  ok_hex(hr, S_OK);
376  if (!SUCCEEDED(hr))
377  return;
378 
379  hr = CustomMRU->AddMRUString(L"FIRST_ENTRY");
380  ok_hex(hr, S_OK);
381  verify_mru(CustomMRU, L"a", L"FIRST_ENTRY");
382 
383  CustomMRU.Release();
384 
386  key.SetStringValue(L"MRUList", L"aaa");
387  key.Close();
388 
389  hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
390  ok_hex(hr, S_OK);
391  if (!SUCCEEDED(hr))
392  return;
393 
394  hr = CustomMRU->Initialize(szTestPath, 3);
395  ok_hex(hr, S_OK);
396  if (!SUCCEEDED(hr))
397  return;
398 
399  hr = CustomMRU->AddMRUString(L"SECOND_ENTRY");
400  ok_hex(hr, S_OK);
401  verify_mru(CustomMRU, L"ba", L"FIRST_ENTRY", L"SECOND_ENTRY");
402 }
403 
404 START_TEST(IACLCustomMRU)
405 {
406  CCoInit init;
407  ok_hex(init.hres, S_OK);
408  if (!SUCCEEDED(init.hres))
409  return;
410 
415 
417 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define REFIID
Definition: guiddef.h:118
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG Key
Definition: fatprocs.h:2697
#define THIS_
Definition: basetyps.h:65
#define ERROR_SUCCESS
Definition: deptool.c:10
HRESULT hr
Definition: shlfolder.c:183
struct _Entry Entry
Definition: kefuncs.h:640
_In_ BOOLEAN Release
Definition: classpnp.h:929
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
HRESULT hres
Definition: ACPPage.cpp:82
#define THIS
Definition: basetyps.h:66
#define KEY_READ
Definition: nt_native.h:1023
REFIID riid
Definition: precomp.h:44
#define _countof(array)
Definition: fontsub.cpp:30
#define HKEY_CURRENT_USER
Definition: winreg.h:11
ULONG DbgPrint(PCH Format,...)
static void test_IACLCustomMRU_Continue()
REFIID LPVOID * ppv
Definition: atlbase.h:39
GLdouble n
Definition: glext.h:7729
DECLARE_INTERFACE_IID_(IACLCustomMRU, IUnknown, "F729FC5E-8769-4F3E-BDB2-D7B50FD2275B")
void __cdecl Format(UINT nFormatID,...)
Definition: cstringt.h:668
NTSTATUS QueryInterface(IN PDEVICE_OBJECT DeviceObject, IN CONST GUID InterfaceType, IN LONG Size, IN LONG Version, OUT PVOID Interface)
Definition: fdo.c:532
#define IID_PPV_ARG(Itype, ppType)
Definition: match.c:390
static void verify_mru_(const char *file, int line, IACLCustomMRU *mru, PCWSTR MRUString,...)
#define ok_hex(expression, result)
Definition: atltest.h:94
static int init
Definition: wintirpc.c:33
#define ok_hex_(file, line, key, expression, result)
#define STDMETHOD(m)
Definition: basetyps.h:62
LONG DeleteSubKey(LPCTSTR lpszSubKey)
Definition: atlbase.h:1316
#define va_end(ap)
Definition: acmsvcex.h:90
CHAR * PCH
Definition: ntbasedef.h:398
smooth NULL
Definition: ftsmooth.c:416
unsigned char
Definition: typeof.h:29
Definition: parser.c:48
char * va_list
Definition: acmsvcex.h:78
DEFINE_GUID(IID_IACLCustomMRU, 0xf729fc5e, 0x8769, 0x4f3e, 0xbd, 0xb2, 0xd7, 0xb5, 0x0f, 0xd2, 0x27, 0x5b)
#define KEY_WRITE
Definition: nt_native.h:1031
static void test_IACLCustomMRU_Basics()
static const WCHAR szTestPath[]
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:77
#define MAX_PATH
Definition: compat.h:26
LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired=KEY_READ|KEY_WRITE)
Definition: atlbase.h:1070
unsigned long DWORD
Definition: ntddk_ex.h:95
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
static void Cleanup_Testdata()
static const WCHAR L[]
Definition: oid.c:1250
static void FillDefault(IACLCustomMRU *CustomMRU)
static void test_IACLCustomMRU_UpdateOrder()
HKEY key
Definition: reg.c:42
Status
Definition: gdiplustypes.h:24
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define va_arg(ap, T)
Definition: acmsvcex.h:89
#define S_OK
Definition: intsafe.h:59
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
void Release()
Definition: atlcomcli.h:140
BOOL Initialize(HINSTANCE hInstance)
Definition: msconfig.c:341
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define verify_mru(mru,...)
#define PURE
Definition: basetyps.h:64
static ULONG WINAPI AddRef(IStream *iface)
Definition: clist.c:90
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
unsigned int ULONG
Definition: retypes.h:1
static void test_IACLCustomMRU_ExtraChars()
#define STDMETHOD_(t, m)
Definition: basetyps.h:63
#define args
Definition: format.c:66
base of all file and directory entries
Definition: entries.h:82
#define SUCCEEDED(hr)
Definition: intsafe.h:57
#define ok_(x1, x2)
Definition: atltest.h:61
Definition: path.c:42
Definition: fci.c:126
START_TEST(IACLCustomMRU)