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