[COMCTL32_WINETEST]
[reactos.git] / rostests / winetests / comctl32 / mru.c
1 /*
2 * comctl32 MRU unit tests
3 *
4 * Copyright (C) 2004 Jon Griffiths <jon_p_griffiths@yahoo.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20 #include <stdarg.h>
21
22 #include <windef.h>
23 #include <winbase.h>
24 //#include "wingdi.h"
25 #include <winuser.h>
26 //#include "winnls.h"
27 #include <winreg.h>
28 #include <commctrl.h>
29 //#include "shlwapi.h"
30
31 #include <wine/test.h>
32
33 /* Keys for testing MRU functions */
34 #define REG_TEST_BASEKEYA "Software\\Wine"
35 #define REG_TEST_BASESUBKEYA "Test"
36 #define REG_TEST_KEYA REG_TEST_BASEKEYA "\\" REG_TEST_BASESUBKEYA
37 #define REG_TEST_SUBKEYA "MRUTest"
38 #define REG_TEST_FULLKEY REG_TEST_KEYA "\\" REG_TEST_SUBKEYA
39
40 /* Undocumented MRU functions */
41 typedef struct tagMRUINFOA
42 {
43 DWORD cbSize;
44 UINT uMax;
45 UINT fFlags;
46 HKEY hKey;
47 LPCSTR lpszSubKey;
48 int (CALLBACK *lpfnCompare)(LPCSTR, LPCSTR);
49 } MRUINFOA;
50
51 typedef struct tagMRUINFOW
52 {
53 DWORD cbSize;
54 UINT uMax;
55 UINT fFlags;
56 HKEY hKey;
57 LPCWSTR lpszSubKey;
58 int (CALLBACK *lpfnCompare)(LPCWSTR, LPCWSTR);
59 } MRUINFOW;
60
61 #define MRU_STRING 0 /* this one's invented */
62 #define MRU_BINARY 1
63 #define MRU_CACHEWRITE 2
64
65 #define LIST_SIZE 3 /* Max entries for each mru */
66
67 static HMODULE hComctl32;
68 static HANDLE (WINAPI *pCreateMRUListA)(MRUINFOA*);
69 static void (WINAPI *pFreeMRUList)(HANDLE);
70 static INT (WINAPI *pAddMRUStringA)(HANDLE,LPCSTR);
71 static INT (WINAPI *pEnumMRUListA)(HANDLE,INT,LPVOID,DWORD);
72 static INT (WINAPI *pEnumMRUListW)(HANDLE,INT,LPVOID,DWORD);
73 static HANDLE (WINAPI *pCreateMRUListLazyA)(MRUINFOA*, DWORD, DWORD, DWORD);
74 static HANDLE (WINAPI *pCreateMRUListLazyW)(MRUINFOW*, DWORD, DWORD, DWORD);
75 static INT (WINAPI *pFindMRUData)(HANDLE, LPCVOID, DWORD, LPINT);
76 static INT (WINAPI *pAddMRUData)(HANDLE, LPCVOID, DWORD);
77 static HANDLE (WINAPI *pCreateMRUListW)(MRUINFOW*);
78
79 static void InitPointers(void)
80 {
81 pCreateMRUListA = (void*)GetProcAddress(hComctl32,(LPCSTR)151);
82 pFreeMRUList = (void*)GetProcAddress(hComctl32,(LPCSTR)152);
83 pAddMRUStringA = (void*)GetProcAddress(hComctl32,(LPCSTR)153);
84 pEnumMRUListA = (void*)GetProcAddress(hComctl32,(LPCSTR)154);
85 pCreateMRUListLazyA = (void*)GetProcAddress(hComctl32,(LPCSTR)157);
86 pAddMRUData = (void*)GetProcAddress(hComctl32,(LPCSTR)167);
87 pFindMRUData = (void*)GetProcAddress(hComctl32,(LPCSTR)169);
88 pCreateMRUListW = (void*)GetProcAddress(hComctl32,(LPCSTR)400);
89 pEnumMRUListW = (void*)GetProcAddress(hComctl32,(LPCSTR)403);
90 pCreateMRUListLazyW = (void*)GetProcAddress(hComctl32,(LPCSTR)404);
91 }
92
93 /* Based on RegDeleteTreeW from dlls/advapi32/registry.c */
94 static LSTATUS mru_RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey)
95 {
96 LONG ret;
97 DWORD dwMaxSubkeyLen, dwMaxValueLen;
98 DWORD dwMaxLen, dwSize;
99 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
100 HKEY hSubKey = hKey;
101
102 if(lpszSubKey)
103 {
104 ret = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
105 if (ret) return ret;
106 }
107
108 /* Get highest length for keys, values */
109 ret = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, NULL,
110 &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
111 if (ret) goto cleanup;
112
113 dwMaxSubkeyLen++;
114 dwMaxValueLen++;
115 dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
116 if (dwMaxLen > sizeof(szNameBuf)/sizeof(CHAR))
117 {
118 /* Name too big: alloc a buffer for it */
119 if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(CHAR))))
120 {
121 ret = ERROR_NOT_ENOUGH_MEMORY;
122 goto cleanup;
123 }
124 }
125
126
127 /* Recursively delete all the subkeys */
128 while (TRUE)
129 {
130 dwSize = dwMaxLen;
131 if (RegEnumKeyExA(hSubKey, 0, lpszName, &dwSize, NULL,
132 NULL, NULL, NULL)) break;
133
134 ret = mru_RegDeleteTreeA(hSubKey, lpszName);
135 if (ret) goto cleanup;
136 }
137
138 if (lpszSubKey)
139 ret = RegDeleteKeyA(hKey, lpszSubKey);
140 else
141 while (TRUE)
142 {
143 dwSize = dwMaxLen;
144 if (RegEnumValueA(hKey, 0, lpszName, &dwSize,
145 NULL, NULL, NULL, NULL)) break;
146
147 ret = RegDeleteValueA(hKey, lpszName);
148 if (ret) goto cleanup;
149 }
150
151 cleanup:
152 /* Free buffer if allocated */
153 if (lpszName != szNameBuf)
154 HeapFree( GetProcessHeap(), 0, lpszName);
155 if(lpszSubKey)
156 RegCloseKey(hSubKey);
157 return ret;
158 }
159
160 static BOOL create_reg_entries(void)
161 {
162 HKEY hKey = NULL;
163
164 ok(!RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_FULLKEY, &hKey),
165 "Couldn't create test key \"%s\"\n", REG_TEST_KEYA);
166 if (!hKey) return FALSE;
167 RegCloseKey(hKey);
168 return TRUE;
169 }
170
171 static void delete_reg_entries(void)
172 {
173 HKEY hKey;
174
175 if (RegOpenKeyExA(HKEY_CURRENT_USER, REG_TEST_BASEKEYA, 0, KEY_ALL_ACCESS,
176 &hKey))
177 return;
178 mru_RegDeleteTreeA(hKey, REG_TEST_BASESUBKEYA);
179 RegCloseKey(hKey);
180 }
181
182 static void check_reg_entries(const char *mrulist, const char**items)
183 {
184 char buff[128];
185 HKEY hKey = NULL;
186 DWORD type, size, ret;
187 unsigned int i;
188
189 ok(!RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_FULLKEY, &hKey),
190 "Couldn't open test key \"%s\"\n", REG_TEST_FULLKEY);
191 if (!hKey) return;
192
193 type = REG_SZ;
194 size = sizeof(buff);
195 buff[0] = '\0';
196 ret = RegQueryValueExA(hKey, "MRUList", NULL, &type, (LPBYTE)buff, &size);
197
198 ok(!ret && buff[0], "Checking MRU: got %d from RegQueryValueExW\n", ret);
199 if(ret || !buff[0]) return;
200
201 ok(strcmp(buff, mrulist) == 0, "Checking MRU: Expected list %s, got %s\n",
202 mrulist, buff);
203 if(strcmp(buff, mrulist)) return;
204
205 for (i = 0; i < strlen(mrulist); i++)
206 {
207 char name[2];
208 name[0] = mrulist[i];
209 name[1] = '\0';
210 type = REG_SZ;
211 size = sizeof(buff);
212 buff[0] = '\0';
213 ret = RegQueryValueExA(hKey, name, NULL, &type, (LPBYTE)buff, &size);
214 ok(!ret && buff[0],
215 "Checking MRU item %d ('%c'): got %d from RegQueryValueExW\n",
216 i, mrulist[i], ret);
217 if(ret || !buff[0]) return;
218 ok(!strcmp(buff, items[mrulist[i]-'a']),
219 "Checking MRU item %d ('%c'): expected \"%s\", got \"%s\"\n",
220 i, mrulist[i], buff, items[mrulist[i] - 'a']);
221 }
222 }
223
224 static int CALLBACK cmp_mru_strA(LPCSTR data1, LPCSTR data2)
225 {
226 return lstrcmpiA(data1, data2);
227 }
228
229 static void test_MRUListA(void)
230 {
231 const char *checks[LIST_SIZE+1];
232 MRUINFOA infoA;
233 HANDLE hMRU;
234 HKEY hKey;
235 INT iRet;
236
237 if (!pCreateMRUListA || !pFreeMRUList || !pAddMRUStringA || !pEnumMRUListA)
238 {
239 skip("MRU entry points not found\n");
240 return;
241 }
242
243 if (0)
244 {
245 /* Create (NULL) - crashes native */
246 hMRU = pCreateMRUListA(NULL);
247 }
248
249 /* size too small */
250 infoA.cbSize = sizeof(infoA) - 2;
251 infoA.uMax = LIST_SIZE;
252 infoA.fFlags = MRU_STRING;
253 infoA.hKey = NULL;
254 infoA.lpszSubKey = REG_TEST_SUBKEYA;
255 infoA.lpfnCompare = cmp_mru_strA;
256
257 SetLastError(0);
258 hMRU = pCreateMRUListA(&infoA);
259 ok (!hMRU && !GetLastError(),
260 "CreateMRUListA(too small) expected NULL,0 got %p,%d\n",
261 hMRU, GetLastError());
262
263 /* size too big */
264 infoA.cbSize = sizeof(infoA) + 2;
265 infoA.uMax = LIST_SIZE;
266 infoA.fFlags = MRU_STRING;
267 infoA.hKey = NULL;
268 infoA.lpszSubKey = REG_TEST_SUBKEYA;
269 infoA.lpfnCompare = cmp_mru_strA;
270
271 SetLastError(0);
272 hMRU = pCreateMRUListA(&infoA);
273 ok (!hMRU && !GetLastError(),
274 "CreateMRUListA(too big) expected NULL,0 got %p,%d\n",
275 hMRU, GetLastError());
276
277 /* NULL hKey */
278 infoA.cbSize = sizeof(infoA);
279 infoA.uMax = LIST_SIZE;
280 infoA.fFlags = MRU_STRING;
281 infoA.hKey = NULL;
282 infoA.lpszSubKey = REG_TEST_SUBKEYA;
283 infoA.lpfnCompare = cmp_mru_strA;
284
285 SetLastError(0);
286 hMRU = pCreateMRUListA(&infoA);
287 ok (!hMRU && !GetLastError(),
288 "CreateMRUListA(NULL key) expected NULL,0 got %p,%d\n",
289 hMRU, GetLastError());
290
291 /* NULL subkey name */
292 infoA.cbSize = sizeof(infoA);
293 infoA.uMax = LIST_SIZE;
294 infoA.fFlags = MRU_STRING;
295 infoA.hKey = NULL;
296 infoA.lpszSubKey = NULL;
297 infoA.lpfnCompare = cmp_mru_strA;
298
299 SetLastError(0);
300 hMRU = pCreateMRUListA(&infoA);
301 ok (!hMRU && !GetLastError(),
302 "CreateMRUListA(NULL name) expected NULL,0 got %p,%d\n",
303 hMRU, GetLastError());
304
305 /* Create a string MRU */
306 ok(!RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEYA, &hKey),
307 "Couldn't create test key \"%s\"\n", REG_TEST_KEYA);
308 if (!hKey) return;
309
310 infoA.cbSize = sizeof(infoA);
311 infoA.uMax = LIST_SIZE;
312 infoA.fFlags = MRU_STRING;
313 infoA.hKey = hKey;
314 infoA.lpszSubKey = REG_TEST_SUBKEYA;
315 infoA.lpfnCompare = cmp_mru_strA;
316
317 hMRU = pCreateMRUListA(&infoA);
318 ok(hMRU && !GetLastError(),
319 "CreateMRUListA(string) expected non-NULL,0 got %p,%d\n",
320 hMRU, GetLastError());
321
322 if (hMRU)
323 {
324 char buffer[255];
325 checks[0] = "Test 1";
326 checks[1] = "Test 2";
327 checks[2] = "Test 3";
328 checks[3] = "Test 4";
329
330 /* Add (NULL list) */
331 SetLastError(0);
332 iRet = pAddMRUStringA(NULL, checks[0]);
333 ok(iRet == -1 && !GetLastError(),
334 "AddMRUStringA(NULL list) expected -1,0 got %d,%d\n",
335 iRet, GetLastError());
336
337 /* Add (NULL string) */
338 if (0)
339 {
340 /* Some native versions crash when passed NULL or fail to SetLastError() */
341 SetLastError(0);
342 iRet = pAddMRUStringA(hMRU, NULL);
343 ok(iRet == 0 && GetLastError() == ERROR_INVALID_PARAMETER,
344 "AddMRUStringA(NULL str) expected 0,ERROR_INVALID_PARAMETER got %d,%d\n",
345 iRet, GetLastError());
346 }
347
348 /* Add 3 strings. Check the registry is correct after each add */
349 SetLastError(0);
350 iRet = pAddMRUStringA(hMRU, checks[0]);
351 ok(iRet == 0 && !GetLastError(),
352 "AddMRUStringA(1) expected 0,0 got %d,%d\n",
353 iRet, GetLastError());
354 check_reg_entries("a", checks);
355
356 SetLastError(0);
357 iRet = pAddMRUStringA(hMRU, checks[1]);
358 ok(iRet == 1 && !GetLastError(),
359 "AddMRUStringA(2) expected 1,0 got %d,%d\n",
360 iRet, GetLastError());
361 check_reg_entries("ba", checks);
362
363 SetLastError(0);
364 iRet = pAddMRUStringA(hMRU, checks[2]);
365 ok(iRet == 2 && !GetLastError(),
366 "AddMRUStringA(2) expected 2,0 got %d,%d\n",
367 iRet, GetLastError());
368 check_reg_entries("cba", checks);
369
370 /* Add a duplicate of the 2nd string - it should move to the front,
371 * but keep the same index in the registry.
372 */
373 SetLastError(0);
374 iRet = pAddMRUStringA(hMRU, checks[1]);
375 ok(iRet == 1 && !GetLastError(),
376 "AddMRUStringA(re-add 1) expected 1,0 got %d,%d\n",
377 iRet, GetLastError());
378 check_reg_entries("bca", checks);
379
380 /* Add a new string - replaces the oldest string + moves to the front */
381 SetLastError(0);
382 iRet = pAddMRUStringA(hMRU, checks[3]);
383 ok(iRet == 0 && !GetLastError(),
384 "AddMRUStringA(add new) expected 0,0 got %d,%d\n",
385 iRet, GetLastError());
386 checks[0] = checks[3];
387 check_reg_entries("abc", checks);
388
389 /* NULL buffer = get list size */
390 iRet = pEnumMRUListA(hMRU, 0, NULL, 0);
391 ok(iRet == 3 || iRet == -1 /* Vista */, "EnumMRUList expected %d or -1, got %d\n", LIST_SIZE, iRet);
392
393 /* negative item pos = get list size */
394 iRet = pEnumMRUListA(hMRU, -1, NULL, 0);
395 ok(iRet == 3 || iRet == -1 /* Vista */, "EnumMRUList expected %d or -1, got %d\n", LIST_SIZE, iRet);
396
397 /* negative item pos = get list size */
398 iRet = pEnumMRUListA(hMRU, -5, NULL, 0);
399 ok(iRet == 3 || iRet == -1 /* Vista */, "EnumMRUList expected %d or -1, got %d\n", LIST_SIZE, iRet);
400
401 /* negative item pos = get list size */
402 iRet = pEnumMRUListA(hMRU, -1, buffer, 255);
403 ok(iRet == 3, "EnumMRUList expected %d, got %d\n", LIST_SIZE, iRet);
404
405 /* negative item pos = get list size */
406 iRet = pEnumMRUListA(hMRU, -5, buffer, 255);
407 ok(iRet == 3, "EnumMRUList expected %d, got %d\n", LIST_SIZE, iRet);
408
409 /* check entry 0 */
410 buffer[0] = 0;
411 iRet = pEnumMRUListA(hMRU, 0, buffer, 255);
412 ok(iRet == lstrlenA(checks[3]), "EnumMRUList expected %d, got %d\n", lstrlenA(checks[3]), iRet);
413 ok(strcmp(buffer, checks[3]) == 0, "EnumMRUList expected %s, got %s\n", checks[3], buffer);
414
415 /* check entry 0 with a too small buffer */
416 buffer[0] = 0; /* overwritten with 'T' */
417 buffer[1] = 'A'; /* overwritten with 0 */
418 buffer[2] = 'A'; /* unchanged */
419 buffer[3] = 0; /* unchanged */
420 iRet = pEnumMRUListA(hMRU, 0, buffer, 2);
421 ok(iRet == lstrlenA(checks[3]), "EnumMRUList expected %d, got %d\n", lstrlenA(checks[3]), iRet);
422 ok(strcmp(buffer, "T") == 0, "EnumMRUList expected %s, got %s\n", "T", buffer);
423 /* make sure space after buffer has old values */
424 ok(buffer[2] == 'A', "EnumMRUList expected %02x, got %02x\n", 'A', buffer[2]);
425
426 /* check entry 1 */
427 buffer[0] = 0;
428 iRet = pEnumMRUListA(hMRU, 1, buffer, 255);
429 ok(iRet == lstrlenA(checks[1]), "EnumMRUList expected %d, got %d\n", lstrlenA(checks[1]), iRet);
430 ok(strcmp(buffer, checks[1]) == 0, "EnumMRUList expected %s, got %s\n", checks[1], buffer);
431
432 /* check entry 2 */
433 buffer[0] = 0;
434 iRet = pEnumMRUListA(hMRU, 2, buffer, 255);
435 ok(iRet == lstrlenA(checks[2]), "EnumMRUList expected %d, got %d\n", lstrlenA(checks[2]), iRet);
436 ok(strcmp(buffer, checks[2]) == 0, "EnumMRUList expected %s, got %s\n", checks[2], buffer);
437
438 /* check out of bounds entry 3 */
439 strcpy(buffer, "dummy");
440 iRet = pEnumMRUListA(hMRU, 3, buffer, 255);
441 ok(iRet == -1, "EnumMRUList expected %d, got %d\n", -1, iRet);
442 ok(strcmp(buffer, "dummy") == 0, "EnumMRUList expected unchanged buffer %s, got %s\n", "dummy", buffer);
443
444 /* Finished with this MRU */
445 pFreeMRUList(hMRU);
446 }
447
448 /* FreeMRUList(NULL) crashes on Win98 OSR0 */
449 }
450
451 typedef struct {
452 MRUINFOA mruA;
453 BOOL ret;
454 } create_lazya_t;
455
456 static const create_lazya_t create_lazyA[] = {
457 {{ sizeof(MRUINFOA) + 1, 0, 0, HKEY_CURRENT_USER, NULL, NULL }, FALSE },
458 {{ sizeof(MRUINFOA) - 1, 0, 0, HKEY_CURRENT_USER, NULL, NULL }, FALSE },
459 {{ sizeof(MRUINFOA) + 1, 0, 0, HKEY_CURRENT_USER, "WineTest", NULL }, TRUE },
460 {{ sizeof(MRUINFOA) - 1, 0, 0, HKEY_CURRENT_USER, "WineTest", NULL }, TRUE },
461 {{ sizeof(MRUINFOA), 0, 0, HKEY_CURRENT_USER, "WineTest", NULL }, TRUE },
462 {{ sizeof(MRUINFOA), 0, 0, HKEY_CURRENT_USER, NULL, NULL }, FALSE },
463 {{ sizeof(MRUINFOA), 0, 0, NULL, "WineTest", NULL }, FALSE },
464 {{ 0, 0, 0, NULL, "WineTest", NULL }, FALSE },
465 {{ 0, 0, 0, HKEY_CURRENT_USER, "WineTest", NULL }, TRUE }
466 };
467
468 static void test_CreateMRUListLazyA(void)
469 {
470 int i;
471
472 if (!pCreateMRUListLazyA || !pFreeMRUList)
473 {
474 win_skip("CreateMRUListLazyA or FreeMRUList entry points not found\n");
475 return;
476 }
477
478 for (i = 0; i < sizeof(create_lazyA)/sizeof(create_lazya_t); i++)
479 {
480 const create_lazya_t *ptr = &create_lazyA[i];
481 HANDLE hMRU;
482
483 hMRU = pCreateMRUListLazyA((MRUINFOA*)&ptr->mruA, 0, 0, 0);
484 if (ptr->ret)
485 {
486 ok(hMRU != NULL, "%d: got %p\n", i, hMRU);
487 pFreeMRUList(hMRU);
488 }
489 else
490 ok(hMRU == NULL, "%d: got %p\n", i, hMRU);
491 }
492 }
493
494 static void test_EnumMRUList(void)
495 {
496 if (!pEnumMRUListA || !pEnumMRUListW)
497 {
498 win_skip("EnumMRUListA/EnumMRUListW entry point not found\n");
499 return;
500 }
501
502 /* NULL handle */
503 if (0)
504 {
505 /* crashes on NT4, passed on Win2k, XP, 2k3, Vista, 2k8 */
506 pEnumMRUListA(NULL, 0, NULL, 0);
507 pEnumMRUListW(NULL, 0, NULL, 0);
508 }
509 }
510
511 static void test_FindMRUData(void)
512 {
513 INT iRet;
514
515 if (!pFindMRUData)
516 {
517 win_skip("FindMRUData entry point not found\n");
518 return;
519 }
520
521 /* NULL handle */
522 iRet = pFindMRUData(NULL, NULL, 0, NULL);
523 ok(iRet == -1, "FindMRUData expected -1, got %d\n", iRet);
524 }
525
526 static void test_AddMRUData(void)
527 {
528 INT iRet;
529
530 if (!pAddMRUData)
531 {
532 win_skip("AddMRUData entry point not found\n");
533 return;
534 }
535
536 /* NULL handle */
537 iRet = pFindMRUData(NULL, NULL, 0, NULL);
538 ok(iRet == -1, "AddMRUData expected -1, got %d\n", iRet);
539 }
540
541 static void test_CreateMRUListW(void)
542 {
543 static const WCHAR mrutestW[] = {'M','R','U','T','e','s','t',0};
544 MRUINFOW infoW;
545 void *named;
546 HKEY hKey;
547 HANDLE hMru;
548
549 if (!pCreateMRUListW)
550 {
551 win_skip("CreateMRUListW entry point not found\n");
552 return;
553 }
554
555 /* exported by name too on recent versions */
556 named = GetProcAddress(hComctl32, "CreateMRUListW");
557 if (named)
558 ok(named == pCreateMRUListW, "got %p, expected %p\n", named, pCreateMRUListW);
559
560 ok(!RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEYA, &hKey),
561 "Couldn't create test key \"%s\"\n", REG_TEST_KEYA);
562
563 infoW.cbSize = sizeof(infoW);
564 infoW.uMax = 1;
565 infoW.fFlags = 0;
566 infoW.lpszSubKey = mrutestW;
567 infoW.hKey = hKey;
568 infoW.lpfnCompare = NULL;
569
570 hMru = pCreateMRUListW(&infoW);
571 ok(hMru != NULL, "got %p\n", hMru);
572 pFreeMRUList(hMru);
573
574 /* smaller size */
575 infoW.cbSize = sizeof(infoW) - 1;
576 infoW.uMax = 1;
577 infoW.fFlags = 0;
578 infoW.lpszSubKey = mrutestW;
579 infoW.hKey = hKey;
580 infoW.lpfnCompare = NULL;
581
582 hMru = pCreateMRUListW(&infoW);
583 ok(hMru != NULL, "got %p\n", hMru);
584 pFreeMRUList(hMru);
585
586 /* increased size */
587 infoW.cbSize = sizeof(infoW) + 1;
588 infoW.uMax = 1;
589 infoW.fFlags = 0;
590 infoW.lpszSubKey = mrutestW;
591 infoW.hKey = hKey;
592 infoW.lpfnCompare = NULL;
593
594 hMru = pCreateMRUListW(&infoW);
595 ok(hMru != NULL, "got %p\n", hMru);
596 pFreeMRUList(hMru);
597
598 /* zero size */
599 infoW.cbSize = 0;
600 infoW.uMax = 1;
601 infoW.fFlags = 0;
602 infoW.lpszSubKey = mrutestW;
603 infoW.hKey = hKey;
604 infoW.lpfnCompare = NULL;
605
606 hMru = pCreateMRUListW(&infoW);
607 ok(hMru != NULL, "got %p\n", hMru);
608 pFreeMRUList(hMru);
609
610 /* NULL hKey */
611 infoW.cbSize = sizeof(infoW);
612 infoW.uMax = 1;
613 infoW.fFlags = 0;
614 infoW.lpszSubKey = mrutestW;
615 infoW.hKey = NULL;
616 infoW.lpfnCompare = NULL;
617
618 hMru = pCreateMRUListW(&infoW);
619 ok(hMru == NULL, "got %p\n", hMru);
620
621 RegCloseKey(hKey);
622 }
623
624 static void test_CreateMRUListLazyW(void)
625 {
626 static const WCHAR mrutestW[] = {'M','R','U','T','e','s','t',0};
627 MRUINFOW infoW;
628 void *named;
629 HKEY hKey;
630 HANDLE hMru;
631
632 if (!pCreateMRUListLazyW)
633 {
634 win_skip("CreateMRUListLazyW entry point not found\n");
635 return;
636 }
637
638 /* check that it's not exported by name */
639 named = GetProcAddress(hComctl32, "CreateMRUListLazyW");
640 ok(named == NULL, "got %p\n", named);
641
642 ok(!RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEYA, &hKey),
643 "Couldn't create test key \"%s\"\n", REG_TEST_KEYA);
644
645 infoW.cbSize = sizeof(infoW);
646 infoW.uMax = 1;
647 infoW.fFlags = 0;
648 infoW.lpszSubKey = mrutestW;
649 infoW.hKey = hKey;
650 infoW.lpfnCompare = NULL;
651
652 hMru = pCreateMRUListLazyW(&infoW, 0, 0, 0);
653 ok(hMru != NULL, "got %p\n", hMru);
654 pFreeMRUList(hMru);
655
656 /* smaller size */
657 infoW.cbSize = sizeof(infoW) - 1;
658 infoW.uMax = 1;
659 infoW.fFlags = 0;
660 infoW.lpszSubKey = mrutestW;
661 infoW.hKey = hKey;
662 infoW.lpfnCompare = NULL;
663
664 hMru = pCreateMRUListLazyW(&infoW, 0, 0, 0);
665 ok(hMru != NULL, "got %p\n", hMru);
666 pFreeMRUList(hMru);
667
668 /* increased size */
669 infoW.cbSize = sizeof(infoW) + 1;
670 infoW.uMax = 1;
671 infoW.fFlags = 0;
672 infoW.lpszSubKey = mrutestW;
673 infoW.hKey = hKey;
674 infoW.lpfnCompare = NULL;
675
676 hMru = pCreateMRUListLazyW(&infoW, 0, 0, 0);
677 ok(hMru != NULL, "got %p\n", hMru);
678 pFreeMRUList(hMru);
679
680 /* zero size */
681 infoW.cbSize = 0;
682 infoW.uMax = 1;
683 infoW.fFlags = 0;
684 infoW.lpszSubKey = mrutestW;
685 infoW.hKey = hKey;
686 infoW.lpfnCompare = NULL;
687
688 hMru = pCreateMRUListLazyW(&infoW, 0, 0, 0);
689 ok(hMru != NULL, "got %p\n", hMru);
690 pFreeMRUList(hMru);
691
692 /* NULL hKey */
693 infoW.cbSize = sizeof(infoW);
694 infoW.uMax = 1;
695 infoW.fFlags = 0;
696 infoW.lpszSubKey = mrutestW;
697 infoW.hKey = NULL;
698 infoW.lpfnCompare = NULL;
699
700 hMru = pCreateMRUListLazyW(&infoW, 0, 0, 0);
701 ok(hMru == NULL, "got %p\n", hMru);
702
703 RegCloseKey(hKey);
704 }
705
706 START_TEST(mru)
707 {
708 hComctl32 = GetModuleHandleA("comctl32.dll");
709
710 delete_reg_entries();
711 if (!create_reg_entries())
712 return;
713
714 InitPointers();
715
716 test_MRUListA();
717 test_CreateMRUListLazyA();
718 test_CreateMRUListLazyW();
719 test_EnumMRUList();
720 test_FindMRUData();
721 test_AddMRUData();
722 test_CreateMRUListW();
723
724 delete_reg_entries();
725 }