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