1 /*
2  * PROJECT:     ReactOS api tests
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Test for IACLCustomMRU objects
5  * COPYRIGHT:   Copyright 2017-2020 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!
18 ULONG DbgPrint(PCH Format,...);
19 
20 #include <shellutils.h>
21 #include <shlwapi.h>
22 #include <strsafe.h>
23 #include <initguid.h>
24 
25 #define ok_hex2(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 #define ok_wstri(x, y) \
33     ok(lstrcmpiW(x, y) == 0, "Wrong string. Expected '%S', got '%S'\n", y, x)
34 
35 struct CCoInit
36 {
37     CCoInit() { hres = CoInitialize(NULL); }
38     ~CCoInit() { if (SUCCEEDED(hres)) { CoUninitialize(); } }
39     HRESULT hres;
40 };
41 
42 
43 DEFINE_GUID(IID_IACLCustomMRU,             0xf729fc5e, 0x8769, 0x4f3e, 0xbd, 0xb2, 0xd7, 0xb5, 0x0f, 0xd2, 0x27, 0x5b);
44 static const WCHAR szTestPath[] = L"TESTPATH_BROWSEUI_APITEST";
45 
46 #undef INTERFACE
47 #define INTERFACE IACLCustomMRU
48 
49 /* based on https://msdn.microsoft.com/en-gb/library/windows/desktop/bb776380(v=vs.85).aspx */
50 DECLARE_INTERFACE_IID_(IACLCustomMRU, IUnknown, "F729FC5E-8769-4F3E-BDB2-D7B50FD2275B")
51 {
52     // *** IUnknown methods ***
53     STDMETHOD(QueryInterface) (THIS_ REFIID riid, void **ppv) PURE;
54     STDMETHOD_(ULONG, AddRef) (THIS)PURE;
55     STDMETHOD_(ULONG, Release) (THIS)PURE;
56 
57     // *** IACLCustomMRU methods ***
58     STDMETHOD(Initialize) (THIS_ LPCWSTR pwszMRURegKey, DWORD dwMax) PURE;
59     STDMETHOD(AddMRUString) (THIS_ LPCWSTR pwszEntry) PURE;
60 };
61 
62 
63 static void Cleanup_Testdata()
64 {
65     CRegKey tmp;
66     if (!tmp.Open(HKEY_CURRENT_USER, NULL, KEY_READ | KEY_WRITE))
67         tmp.DeleteSubKey(szTestPath);
68 }
69 
70 #define verify_mru(mru, ...)     verify_mru_(__FILE__, __LINE__, mru, __VA_ARGS__, NULL)
71 static void verify_mru_(const char* file, int line, IACLCustomMRU* mru, PCWSTR MRUString, ...)
72 {
73 
74     CRegKey key;
75     key.Open(HKEY_CURRENT_USER, szTestPath);
76 
77     va_list args;
78     va_start(args, MRUString);
79     PCWSTR Entry;
80     WCHAR Key = L'a';
81     while ((Entry = va_arg(args, PCWSTR)))
82     {
83         WCHAR Value[MAX_PATH];
84         ULONG nChars = _countof(Value);
85         CStringW tmp;
86         tmp += Key;
87         LSTATUS Status = key.QueryStringValue(tmp, Value, &nChars);
88         ok_hex2(file, line, Key, Status, ERROR_SUCCESS);
89         if (Status == ERROR_SUCCESS)
90         {
91             ok_(file, line)(!wcscmp(Value, Entry), "Expected value %c to be %S, was %S\n", (char)Key, Entry, Value);
92         }
93         Key++;
94     }
95     va_end(args);
96 
97     if (Key != L'a')
98     {
99         WCHAR Value[MAX_PATH];
100         ULONG nChars = _countof(Value);
101         LSTATUS Status = key.QueryStringValue(L"MRUList", Value, &nChars);
102         ok_hex2(file, line, Key, Status, ERROR_SUCCESS);
103         if (Status == ERROR_SUCCESS)
104         {
105             ok_(file, line)(!wcscmp(Value, MRUString), "Expected MRUList to be %S, was %S\n", MRUString, Value);
106         }
107     }
108 }
109 
110 
111 static void
112 test_IACLCustomMRU_Basics()
113 {
114     CComPtr<IACLCustomMRU> CustomMRU;
115     HRESULT hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
116     ok_hex(hr, S_OK);
117     if (!SUCCEEDED(hr))
118         return;
119 
120     Cleanup_Testdata();
121 
122     /* Initialize with a NULL name will cause an AV */
123     //hr = CustomMRU->Initialize(NULL, 0);
124 
125     hr = CustomMRU->Initialize(szTestPath, 0);
126     ok_hex(hr, S_OK);
127     /* Adding an entry with a dwMax of 0 will cause an AV */
128 
129     /* Calling it again will resize */
130     hr = CustomMRU->Initialize(szTestPath, 3);
131     ok_hex(hr, S_OK);
132     verify_mru(CustomMRU, L"");
133 
134     hr = CustomMRU->AddMRUString(L"FIRST_ENTRY");
135     ok_hex(hr, S_OK);
136     verify_mru(CustomMRU, L"a", L"FIRST_ENTRY");
137 
138     hr = CustomMRU->AddMRUString(L"SECOND_ENTRY");
139     ok_hex(hr, S_OK);
140     verify_mru(CustomMRU, L"ba", L"FIRST_ENTRY", L"SECOND_ENTRY");
141 
142     hr = CustomMRU->AddMRUString(L"THIRD_ENTRY");
143     ok_hex(hr, S_OK);
144     verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
145 
146     /* First entry is replaced */
147     hr = CustomMRU->AddMRUString(L"FOURTH_ENTRY");
148     ok_hex(hr, S_OK);
149     verify_mru(CustomMRU, L"acb", L"FOURTH_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
150 
151     /* Second entry is replaced */
152     hr = CustomMRU->AddMRUString(L"FIFTH_ENTRY");
153     ok_hex(hr, S_OK);
154     verify_mru(CustomMRU, L"bac", L"FOURTH_ENTRY", L"FIFTH_ENTRY", L"THIRD_ENTRY");
155 }
156 
157 
158 static void FillDefault(IACLCustomMRU* CustomMRU)
159 {
160     Cleanup_Testdata();
161     HRESULT hr = CustomMRU->Initialize(szTestPath, 3);
162     ok_hex(hr, S_OK);
163     hr = CustomMRU->AddMRUString(L"FIRST_ENTRY");
164     ok_hex(hr, S_OK);
165     hr = CustomMRU->AddMRUString(L"SECOND_ENTRY");
166     ok_hex(hr, S_OK);
167     hr = CustomMRU->AddMRUString(L"THIRD_ENTRY");
168     ok_hex(hr, S_OK);
169 }
170 
171 static void
172 test_IACLCustomMRU_UpdateOrder()
173 {
174     CComPtr<IACLCustomMRU> CustomMRU;
175     HRESULT hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
176     ok_hex(hr, S_OK);
177     if (!SUCCEEDED(hr))
178         return;
179 
180     Cleanup_Testdata();
181     FillDefault(CustomMRU);
182     verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
183 
184     /* Add the first entry again */
185     hr = CustomMRU->AddMRUString(L"FIRST_ENTRY");
186     ok_hex(hr, S_OK);
187     /* No change */
188     verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
189 
190     CustomMRU.Release();
191     /* Now the order is updated */
192     verify_mru(NULL, L"acb", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
193 
194 
195     hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
196     ok_hex(hr, S_OK);
197     if (!SUCCEEDED(hr))
198         return;
199 
200     Cleanup_Testdata();
201     FillDefault(CustomMRU);
202     verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
203 
204 
205     /* Add the first entry again */
206     hr = CustomMRU->AddMRUString(L"FIRST_ENTRY");
207     ok_hex(hr, S_OK);
208     /* No change */
209     verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
210 
211     hr = CustomMRU->AddMRUString(L"SOMETHING_ELSE");
212     ok_hex(hr, S_OK);
213     /* Now all changes are persisted */
214     verify_mru(CustomMRU, L"bac", L"FIRST_ENTRY", L"SOMETHING_ELSE", L"THIRD_ENTRY");
215 }
216 
217 static void
218 test_IACLCustomMRU_ExtraChars()
219 {
220     CComPtr<IACLCustomMRU> CustomMRU;
221     HRESULT hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
222     ok_hex(hr, S_OK);
223     if (!SUCCEEDED(hr))
224         return;
225 
226     Cleanup_Testdata();
227 
228     /* Still returnes success */
229     hr = CustomMRU->Initialize(szTestPath, 30);
230     ok_hex(hr, S_OK);
231 
232     for (int n = 0; n < 30; ++n)
233     {
234         CStringW tmp;
235         tmp.Format(L"%d", n);
236 
237         hr = CustomMRU->AddMRUString(tmp);
238         ok_hex(hr, S_OK);
239     }
240     /* But is starting to wrap around */
241     verify_mru(CustomMRU, L"a}|{zyxwvutsrqponmlkjihgfedcb", L"29",
242                L"1", L"2", L"3", L"4", L"5", L"6", L"7", L"8", L"9",
243                L"10", L"11", L"12", L"13", L"14", L"15", L"16", L"17", L"18", L"19",
244                L"20", L"21", L"22", L"23", L"24", L"25", L"26", L"27", L"28");
245 
246     Cleanup_Testdata();
247 }
248 
249 static void
250 test_IACLCustomMRU_Continue()
251 {
252     CComPtr<IACLCustomMRU> CustomMRU;
253     HRESULT hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
254     ok_hex(hr, S_OK);
255     if (!SUCCEEDED(hr))
256         return;
257 
258     Cleanup_Testdata();
259     FillDefault(CustomMRU);
260     verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
261 
262     CustomMRU.Release();
263 
264     hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
265     ok_hex(hr, S_OK);
266     if (!SUCCEEDED(hr))
267         return;
268 
269     hr = CustomMRU->Initialize(szTestPath, 3);
270     ok_hex(hr, S_OK);
271 
272     /* First entry is replaced */
273     hr = CustomMRU->AddMRUString(L"FOURTH_ENTRY");
274     ok_hex(hr, S_OK);
275     verify_mru(CustomMRU, L"acb", L"FOURTH_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
276 
277     CustomMRU.Release();
278 
279     hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
280     ok_hex(hr, S_OK);
281     if (!SUCCEEDED(hr))
282         return;
283 
284     hr = CustomMRU->Initialize(szTestPath, 3);
285     ok_hex(hr, S_OK);
286 
287     /* Second entry is replaced */
288     hr = CustomMRU->AddMRUString(L"FIFTH_ENTRY");
289     ok_hex(hr, S_OK);
290     verify_mru(CustomMRU, L"bac", L"FOURTH_ENTRY", L"FIFTH_ENTRY", L"THIRD_ENTRY");
291 
292     CustomMRU.Release();
293 
294     hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
295     ok_hex(hr, S_OK);
296     if (!SUCCEEDED(hr))
297         return;
298 
299 
300     /* Save some garbage */
301     CRegKey key;
302     key.Open(HKEY_CURRENT_USER, szTestPath);
303     key.SetStringValue(L"MRUList", L"b**");
304     key.Close();
305 
306     hr = CustomMRU->Initialize(szTestPath, 3);
307     ok_hex(hr, S_OK);
308 
309     CustomMRU.Release();
310 
311     /* Not cleaned up */
312     verify_mru(CustomMRU, L"b**", L"FOURTH_ENTRY", L"FIFTH_ENTRY", L"THIRD_ENTRY");
313 
314     hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
315     ok_hex(hr, S_OK);
316     if (!SUCCEEDED(hr))
317         return;
318 
319     hr = CustomMRU->Initialize(szTestPath, 3);
320     ok_hex(hr, S_OK);
321 
322     /* Now it's just cleaned up */
323     hr = CustomMRU->AddMRUString(L"SIXTH_ENTRY");
324     ok_hex(hr, S_OK);
325     verify_mru(CustomMRU, L"ab", L"SIXTH_ENTRY");
326 
327     CustomMRU.Release();
328 
329     hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
330     ok_hex(hr, S_OK);
331     if (!SUCCEEDED(hr))
332         return;
333 
334     Cleanup_Testdata();
335     FillDefault(CustomMRU);
336     verify_mru(CustomMRU, L"cba", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
337 
338     CustomMRU.Release();
339 
340     hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
341     ok_hex(hr, S_OK);
342     if (!SUCCEEDED(hr))
343         return;
344 
345     key.Open(HKEY_CURRENT_USER, szTestPath);
346     key.SetStringValue(L"MRUList", L"baccccc");
347     key.Close();
348 
349     hr = CustomMRU->Initialize(szTestPath, 3);
350     ok_hex(hr, S_OK);
351     CustomMRU.Release();
352 
353     verify_mru(CustomMRU, L"baccccc", L"FIRST_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
354 
355     hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
356     ok_hex(hr, S_OK);
357     if (!SUCCEEDED(hr))
358         return;
359 
360     hr = CustomMRU->Initialize(szTestPath, 3);
361     ok_hex(hr, S_OK);
362 
363     hr = CustomMRU->AddMRUString(L"FOURTH_ENTRY");
364     ok_hex(hr, S_OK);
365     verify_mru(CustomMRU, L"a", L"FOURTH_ENTRY", L"SECOND_ENTRY", L"THIRD_ENTRY");
366 
367     CustomMRU.Release();
368     Cleanup_Testdata();
369 
370     hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
371     ok_hex(hr, S_OK);
372     if (!SUCCEEDED(hr))
373         return;
374 
375     hr = CustomMRU->Initialize(szTestPath, 3);
376     ok_hex(hr, S_OK);
377     if (!SUCCEEDED(hr))
378         return;
379 
380     hr = CustomMRU->AddMRUString(L"FIRST_ENTRY");
381     ok_hex(hr, S_OK);
382     verify_mru(CustomMRU, L"a", L"FIRST_ENTRY");
383 
384     CustomMRU.Release();
385 
386     key.Open(HKEY_CURRENT_USER, szTestPath);
387     key.SetStringValue(L"MRUList", L"aaa");
388     key.Close();
389 
390     hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL, IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
391     ok_hex(hr, S_OK);
392     if (!SUCCEEDED(hr))
393         return;
394 
395     hr = CustomMRU->Initialize(szTestPath, 3);
396     ok_hex(hr, S_OK);
397     if (!SUCCEEDED(hr))
398         return;
399 
400     hr = CustomMRU->AddMRUString(L"SECOND_ENTRY");
401     ok_hex(hr, S_OK);
402     verify_mru(CustomMRU, L"ba", L"FIRST_ENTRY", L"SECOND_ENTRY");
403 }
404 
405 #define TYPED_URLS_KEY L"Software\\Microsoft\\Internet Explorer\\TypedURLs"
406 
407 static void
408 RestoreTypedURLs(const CStringW& url1, const CStringW& url2)
409 {
410     CRegKey key;
411     key.Open(HKEY_CURRENT_USER, TYPED_URLS_KEY, KEY_WRITE);
412     if (url1 != L"")
413         key.SetStringValue(L"url1", url1);
414     if (url2 != L"")
415         key.SetStringValue(L"url2", url2);
416 }
417 
418 static void
419 test_IACLCustomMRU_TypedURLs() // TypedURLs is special case
420 {
421     CStringW url1, url2; // Save values
422     {
423         CRegKey key;
424         key.Open(HKEY_CURRENT_USER, TYPED_URLS_KEY, KEY_READ | KEY_WRITE);
425 
426         WCHAR Value[MAX_PATH];
427         ULONG cch = _countof(Value);
428         LSTATUS Status = key.QueryStringValue(L"url1", Value, &cch);
429         if (!Status)
430             url1 = Value;
431 
432         cch = _countof(Value);
433         Status = key.QueryStringValue(L"url2", Value, &cch);
434         if (!Status)
435             url2 = Value;
436 
437         // Set values
438         key.SetStringValue(L"url1", L"aaa");
439         key.SetStringValue(L"url2", L"bbb");
440     }
441 
442     CComPtr<IACLCustomMRU> CustomMRU;
443     HRESULT hr = CoCreateInstance(CLSID_ACLCustomMRU, NULL, CLSCTX_ALL,
444                                   IID_PPV_ARG(IACLCustomMRU, &CustomMRU));
445     ok_hex(hr, S_OK);
446     if (FAILED(hr))
447     {
448         skip("IACLCustomMRU was NULL\n");
449         RestoreTypedURLs(url1, url2);
450         return;
451     }
452 
453     CComPtr<IACList> ACList;
454     hr = CustomMRU->QueryInterface(IID_PPV_ARG(IACList, &ACList));
455     ok_hex(hr, S_OK);
456     if (SUCCEEDED(hr))
457     {
458         hr = ACList->Expand(L"C:");
459         ok_hex(hr, E_NOTIMPL);
460         hr = ACList->Expand(L"C:\\");
461         ok_hex(hr, E_NOTIMPL);
462         hr = ACList->Expand(L"C:\\Program Files");
463         ok_hex(hr, E_NOTIMPL);
464         hr = ACList->Expand(L"C:\\Program Files\\");
465         ok_hex(hr, E_NOTIMPL);
466         hr = ACList->Expand(L"http://");
467         ok_hex(hr, E_NOTIMPL);
468         hr = ACList->Expand(L"https://");
469         ok_hex(hr, E_NOTIMPL);
470         hr = ACList->Expand(L"https://google.co.jp/");
471         ok_hex(hr, E_NOTIMPL);
472     }
473 
474     hr = CustomMRU->Initialize(TYPED_URLS_KEY, 64);
475     ok_hex(hr, S_OK);
476 
477     if (ACList)
478     {
479         hr = ACList->Expand(L"C:");
480         ok_hex(hr, E_NOTIMPL);
481         hr = ACList->Expand(L"C:\\");
482         ok_hex(hr, E_NOTIMPL);
483         hr = ACList->Expand(L"C:\\Program Files");
484         ok_hex(hr, E_NOTIMPL);
485         hr = ACList->Expand(L"C:\\Program Files\\");
486         ok_hex(hr, E_NOTIMPL);
487         hr = ACList->Expand(L"http://");
488         ok_hex(hr, E_NOTIMPL);
489         hr = ACList->Expand(L"https://");
490         ok_hex(hr, E_NOTIMPL);
491         hr = ACList->Expand(L"https://google.co.jp/");
492         ok_hex(hr, E_NOTIMPL);
493     }
494 
495     CComPtr<IEnumString> pEnum;
496     hr = CustomMRU->QueryInterface(IID_PPV_ARG(IEnumString, &pEnum));
497     ok_hex(hr, S_OK);
498     if (FAILED(hr))
499     {
500         skip("IEnumString was NULL\n");
501         RestoreTypedURLs(url1, url2);
502         return;
503     }
504 
505     CComPtr<IEnumString> pEnumClone;
506     hr = pEnum->Clone(&pEnumClone);
507     ok_hex(hr, E_NOTIMPL);
508 
509     hr = pEnum->Skip(1);
510     ok_hex(hr, E_NOTIMPL);
511 
512 #define INVALID_LPOLESTR ((LPOLESTR)(LONG_PTR)0xDEADBEEF)
513     LPOLESTR apsz[2] = { NULL, INVALID_LPOLESTR };
514     ULONG c = 0;
515     hr = pEnum->Next(2, apsz, &c);
516     ok_hex(hr, S_OK);
517     ok_wstri(apsz[0], L"aaa");
518     ok_int(c, 1);
519     ok(apsz[1] == INVALID_LPOLESTR, "apsz[1] was '%S'\n", apsz[1]);
520     CoTaskMemFree(apsz[0]);
521 
522     LPOLESTR psz = INVALID_LPOLESTR;
523     c = 0;
524     hr = pEnum->Next(0, &psz, &c);
525     ok_hex(hr, S_OK);
526     ok(psz == INVALID_LPOLESTR, "psz was '%S'\n", psz);
527     ok_int(c, 0);
528 
529     psz = NULL;
530     c = 0;
531     hr = pEnum->Next(1, &psz, &c);
532     ok_hex(hr, S_OK);
533     ok_wstri(psz, L"bbb");
534     ok_int(c, 1);
535     CoTaskMemFree(psz);
536 
537     hr = CustomMRU->AddMRUString(L"https://google.co.jp");
538     ok_hex(hr, E_FAIL);
539     hr = CustomMRU->AddMRUString(L"C:");
540     ok_hex(hr, E_FAIL);
541     hr = CustomMRU->AddMRUString(L"C:\\");
542     ok_hex(hr, E_FAIL);
543 
544     RestoreTypedURLs(url1, url2);
545 }
546 
547 START_TEST(IACLCustomMRU)
548 {
549     CCoInit init;
550     ok_hex(init.hres, S_OK);
551     if (!SUCCEEDED(init.hres))
552         return;
553 
554     test_IACLCustomMRU_Basics();
555     test_IACLCustomMRU_UpdateOrder();
556     test_IACLCustomMRU_ExtraChars();
557     test_IACLCustomMRU_Continue();
558     test_IACLCustomMRU_TypedURLs();
559 
560     Cleanup_Testdata();
561 }
562