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 win_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 } 726