1 /* 2 * Unit tests for shelllinks 3 * 4 * Copyright 2004 Mike McCormack 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 22 #define COBJMACROS 23 24 #include "initguid.h" 25 #include "windows.h" 26 #include "shlguid.h" 27 #include "shobjidl.h" 28 #include "shlobj.h" 29 #include "shellapi.h" 30 #include "commoncontrols.h" 31 32 #include "wine/heap.h" 33 #include "wine/test.h" 34 35 #include "shell32_test.h" 36 37 #ifdef __REACTOS__ 38 #include <reactos/undocshell.h> 39 #endif 40 41 #ifndef SLDF_HAS_LOGO3ID 42 # define SLDF_HAS_LOGO3ID 0x00000800 /* not available in the Vista SDK */ 43 #endif 44 45 static void (WINAPI *pILFree)(LPITEMIDLIST); 46 static BOOL (WINAPI *pILIsEqual)(LPCITEMIDLIST, LPCITEMIDLIST); 47 static HRESULT (WINAPI *pSHILCreateFromPath)(LPCWSTR, LPITEMIDLIST *,DWORD*); 48 static HRESULT (WINAPI *pSHGetFolderLocation)(HWND,INT,HANDLE,DWORD,PIDLIST_ABSOLUTE*); 49 static HRESULT (WINAPI *pSHDefExtractIconA)(LPCSTR, int, UINT, HICON*, HICON*, UINT); 50 static HRESULT (WINAPI *pSHGetStockIconInfo)(SHSTOCKICONID, UINT, SHSTOCKICONINFO *); 51 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR, LPSTR, DWORD); 52 static DWORD (WINAPI *pGetShortPathNameA)(LPCSTR, LPSTR, DWORD); 53 static UINT (WINAPI *pSHExtractIconsW)(LPCWSTR, int, int, int, HICON *, UINT *, UINT, UINT); 54 static BOOL (WINAPI *pIsProcessDPIAware)(void); 55 56 static const GUID _IID_IShellLinkDataList = { 57 0x45e2b4ae, 0xb1c3, 0x11d0, 58 { 0xb9, 0x2f, 0x00, 0xa0, 0xc9, 0x03, 0x12, 0xe1 } 59 }; 60 61 62 /* For some reason SHILCreateFromPath does not work on Win98 and 63 * SHSimpleIDListFromPathA does not work on NT4. But if we call both we 64 * get what we want on all platforms. 65 */ 66 static LPITEMIDLIST (WINAPI *pSHSimpleIDListFromPathAW)(LPCVOID); 67 68 static LPITEMIDLIST path_to_pidl(const char* path) 69 { 70 LPITEMIDLIST pidl; 71 72 if (!pSHSimpleIDListFromPathAW) 73 { 74 HMODULE hdll=GetModuleHandleA("shell32.dll"); 75 pSHSimpleIDListFromPathAW=(void*)GetProcAddress(hdll, (char*)162); 76 if (!pSHSimpleIDListFromPathAW) 77 win_skip("SHSimpleIDListFromPathAW not found in shell32.dll\n"); 78 } 79 80 pidl=NULL; 81 /* pSHSimpleIDListFromPathAW maps to A on non NT platforms */ 82 if (pSHSimpleIDListFromPathAW && (GetVersion() & 0x80000000)) 83 pidl=pSHSimpleIDListFromPathAW(path); 84 85 if (!pidl) 86 { 87 WCHAR* pathW; 88 HRESULT r; 89 int len; 90 91 len=MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0); 92 pathW = heap_alloc(len * sizeof(WCHAR)); 93 MultiByteToWideChar(CP_ACP, 0, path, -1, pathW, len); 94 95 r=pSHILCreateFromPath(pathW, &pidl, NULL); 96 ok(r == S_OK, "SHILCreateFromPath failed (0x%08x)\n", r); 97 heap_free(pathW); 98 } 99 return pidl; 100 } 101 102 103 /* 104 * Test manipulation of an IShellLink's properties. 105 */ 106 107 static void test_get_set(void) 108 { 109 HRESULT r; 110 IShellLinkA *sl; 111 IShellLinkW *slW = NULL; 112 char mypath[MAX_PATH]; 113 char buffer[INFOTIPSIZE]; 114 WIN32_FIND_DATAA finddata; 115 LPITEMIDLIST pidl, tmp_pidl; 116 const char * str; 117 int i; 118 WORD w; 119 120 r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 121 &IID_IShellLinkA, (LPVOID*)&sl); 122 ok(r == S_OK, "no IID_IShellLinkA (0x%08x)\n", r); 123 if (r != S_OK) 124 return; 125 126 /* Test Getting / Setting the description */ 127 strcpy(buffer,"garbage"); 128 r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer)); 129 ok(r == S_OK, "GetDescription failed (0x%08x)\n", r); 130 ok(*buffer=='\0', "GetDescription returned '%s'\n", buffer); 131 132 str="Some description"; 133 r = IShellLinkA_SetDescription(sl, str); 134 ok(r == S_OK, "SetDescription failed (0x%08x)\n", r); 135 136 strcpy(buffer,"garbage"); 137 r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer)); 138 ok(r == S_OK, "GetDescription failed (0x%08x)\n", r); 139 ok(strcmp(buffer,str)==0, "GetDescription returned '%s'\n", buffer); 140 141 r = IShellLinkA_SetDescription(sl, NULL); 142 ok(r == S_OK, "SetDescription failed (0x%08x)\n", r); 143 144 strcpy(buffer,"garbage"); 145 r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer)); 146 ok(r == S_OK, "GetDescription failed (0x%08x)\n", r); 147 ok(*buffer=='\0' || broken(strcmp(buffer,str)==0), "GetDescription returned '%s'\n", buffer); /* NT4 */ 148 149 /* Test Getting / Setting the work directory */ 150 strcpy(buffer,"garbage"); 151 r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer)); 152 ok(r == S_OK, "GetWorkingDirectory failed (0x%08x)\n", r); 153 ok(*buffer=='\0', "GetWorkingDirectory returned '%s'\n", buffer); 154 155 str="c:\\nonexistent\\directory"; 156 r = IShellLinkA_SetWorkingDirectory(sl, str); 157 ok(r == S_OK, "SetWorkingDirectory failed (0x%08x)\n", r); 158 159 strcpy(buffer,"garbage"); 160 r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer)); 161 ok(r == S_OK, "GetWorkingDirectory failed (0x%08x)\n", r); 162 ok(lstrcmpiA(buffer,str)==0, "GetWorkingDirectory returned '%s'\n", buffer); 163 164 /* Test Getting / Setting the path */ 165 strcpy(buffer,"garbage"); 166 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); 167 ok(r == S_FALSE || broken(r == S_OK) /* NT4/W2K */, "GetPath failed (0x%08x)\n", r); 168 ok(*buffer=='\0', "GetPath returned '%s'\n", buffer); 169 170 strcpy(buffer,"garbage"); 171 memset(&finddata, 0xaa, sizeof(finddata)); 172 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), &finddata, SLGP_RAWPATH); 173 ok(r == S_FALSE || broken(r == S_OK) /* NT4/W2K */, "GetPath failed (0x%08x)\n", r); 174 ok(*buffer=='\0', "GetPath returned '%s'\n", buffer); 175 ok(finddata.dwFileAttributes == 0, "unexpected attributes %x\n", finddata.dwFileAttributes); 176 ok(finddata.cFileName[0] == 0, "unexpected filename '%s'\n", finddata.cFileName); 177 178 r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 179 &IID_IShellLinkW, (LPVOID*)&slW); 180 ok(r == S_OK, "CoCreateInstance failed (0x%08x)\n", r); 181 if (!slW /* Win9x */ || !pGetLongPathNameA /* NT4 */) 182 skip("SetPath with NULL parameter crashes on Win9x and some NT4\n"); 183 else 184 { 185 IShellLinkW_Release(slW); 186 r = IShellLinkA_SetPath(sl, NULL); 187 ok(r==E_INVALIDARG || 188 broken(r==S_OK), /* Some Win95 and NT4 */ 189 "SetPath returned wrong error (0x%08x)\n", r); 190 } 191 192 r = IShellLinkA_SetPath(sl, ""); 193 ok(r==S_OK, "SetPath failed (0x%08x)\n", r); 194 195 strcpy(buffer,"garbage"); 196 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); 197 ok(r == S_FALSE, "GetPath failed (0x%08x)\n", r); 198 ok(*buffer=='\0', "GetPath returned '%s'\n", buffer); 199 200 /* Win98 returns S_FALSE, but WinXP returns S_OK */ 201 str="c:\\nonexistent\\file"; 202 r = IShellLinkA_SetPath(sl, str); 203 ok(r==S_FALSE || r==S_OK, "SetPath failed (0x%08x)\n", r); 204 205 strcpy(buffer,"garbage"); 206 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); 207 ok(r == S_OK, "GetPath failed (0x%08x)\n", r); 208 ok(lstrcmpiA(buffer,str)==0, "GetPath returned '%s'\n", buffer); 209 210 strcpy(buffer,"garbage"); 211 memset(&finddata, 0xaa, sizeof(finddata)); 212 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), &finddata, SLGP_RAWPATH); 213 ok(r == S_OK, "GetPath failed (0x%08x)\n", r); 214 ok(lstrcmpiA(buffer,str)==0, "GetPath returned '%s'\n", buffer); 215 ok(finddata.dwFileAttributes == 0, "unexpected attributes %x\n", finddata.dwFileAttributes); 216 ok(lstrcmpiA(finddata.cFileName, "file") == 0, "unexpected filename '%s'\n", finddata.cFileName); 217 218 /* Get some real path to play with */ 219 GetWindowsDirectoryA( mypath, sizeof(mypath)-12 ); 220 strcat(mypath, "\\regedit.exe"); 221 222 /* Test the interaction of SetPath and SetIDList */ 223 tmp_pidl=NULL; 224 r = IShellLinkA_GetIDList(sl, &tmp_pidl); 225 ok(r == S_OK, "GetIDList failed (0x%08x)\n", r); 226 if (r == S_OK) 227 { 228 BOOL ret; 229 230 strcpy(buffer,"garbage"); 231 ret = SHGetPathFromIDListA(tmp_pidl, buffer); 232 ok(ret, "SHGetPathFromIDListA failed\n"); 233 if (ret) 234 ok(lstrcmpiA(buffer,str)==0, "GetIDList returned '%s'\n", buffer); 235 pILFree(tmp_pidl); 236 } 237 238 pidl=path_to_pidl(mypath); 239 ok(pidl!=NULL, "path_to_pidl returned a NULL pidl\n"); 240 241 if (pidl) 242 { 243 LPITEMIDLIST second_pidl; 244 245 r = IShellLinkA_SetIDList(sl, pidl); 246 ok(r == S_OK, "SetIDList failed (0x%08x)\n", r); 247 248 tmp_pidl=NULL; 249 r = IShellLinkA_GetIDList(sl, &tmp_pidl); 250 ok(r == S_OK, "GetIDList failed (0x%08x)\n", r); 251 ok(tmp_pidl && pILIsEqual(pidl, tmp_pidl), 252 "GetIDList returned an incorrect pidl\n"); 253 254 r = IShellLinkA_GetIDList(sl, &second_pidl); 255 ok(r == S_OK, "GetIDList failed (0x%08x)\n", r); 256 ok(second_pidl && pILIsEqual(pidl, second_pidl), 257 "GetIDList returned an incorrect pidl\n"); 258 ok(second_pidl != tmp_pidl, "pidls are the same\n"); 259 260 pILFree(second_pidl); 261 pILFree(tmp_pidl); 262 pILFree(pidl); 263 264 strcpy(buffer,"garbage"); 265 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); 266 ok(r == S_OK, "GetPath failed (0x%08x)\n", r); 267 ok(lstrcmpiA(buffer, mypath)==0, "GetPath returned '%s'\n", buffer); 268 269 strcpy(buffer,"garbage"); 270 memset(&finddata, 0xaa, sizeof(finddata)); 271 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), &finddata, SLGP_RAWPATH); 272 ok(r == S_OK, "GetPath failed (0x%08x)\n", r); 273 ok(lstrcmpiA(buffer, mypath)==0, "GetPath returned '%s'\n", buffer); 274 ok(finddata.dwFileAttributes != 0, "unexpected attributes %x\n", finddata.dwFileAttributes); 275 ok(lstrcmpiA(finddata.cFileName, "regedit.exe") == 0, "unexpected filename '%s'\n", finddata.cFileName); 276 } 277 278 if (pSHGetFolderLocation) 279 { 280 LPITEMIDLIST pidl_controls; 281 282 r = pSHGetFolderLocation(NULL, CSIDL_CONTROLS, NULL, 0, &pidl_controls); 283 ok(r == S_OK, "SHGetFolderLocation failed (0x%08x)\n", r); 284 285 r = IShellLinkA_SetIDList(sl, pidl_controls); 286 ok(r == S_OK, "SetIDList failed (0x%08x)\n", r); 287 288 strcpy(buffer,"garbage"); 289 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); 290 ok(r == S_FALSE, "GetPath failed (0x%08x)\n", r); 291 ok(buffer[0] == 0, "GetPath returned '%s'\n", buffer); 292 293 strcpy(buffer,"garbage"); 294 memset(&finddata, 0xaa, sizeof(finddata)); 295 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), &finddata, SLGP_RAWPATH); 296 ok(r == S_FALSE, "GetPath failed (0x%08x)\n", r); 297 ok(buffer[0] == 0, "GetPath returned '%s'\n", buffer); 298 ok(finddata.dwFileAttributes == 0, "unexpected attributes %x\n", finddata.dwFileAttributes); 299 ok(finddata.cFileName[0] == 0, "unexpected filename '%s'\n", finddata.cFileName); 300 301 pILFree(pidl_controls); 302 } 303 304 /* test path with quotes (IShellLinkA_SetPath returns S_FALSE on W2K and below and S_OK on XP and above */ 305 r = IShellLinkA_SetPath(sl, "\"c:\\nonexistent\\file\""); 306 ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r); 307 308 strcpy(buffer,"garbage"); 309 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); 310 ok(r==S_OK, "GetPath failed (0x%08x)\n", r); 311 todo_wine ok(!strcmp(buffer, "C:\\nonexistent\\file") || 312 broken(!strcmp(buffer, "C:\\\"c:\\nonexistent\\file\"")), /* NT4 */ 313 "case doesn't match\n"); 314 315 r = IShellLinkA_SetPath(sl, "\"c:\\foo"); 316 ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r); 317 318 r = IShellLinkA_SetPath(sl, "\"\"c:\\foo"); 319 ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r); 320 321 r = IShellLinkA_SetPath(sl, "c:\\foo\""); 322 ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r); 323 324 r = IShellLinkA_SetPath(sl, "\"\"c:\\foo\""); 325 ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r); 326 327 r = IShellLinkA_SetPath(sl, "\"\"c:\\foo\"\""); 328 ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r); 329 330 /* Test Getting / Setting the arguments */ 331 strcpy(buffer,"garbage"); 332 r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer)); 333 ok(r == S_OK, "GetArguments failed (0x%08x)\n", r); 334 ok(*buffer=='\0', "GetArguments returned '%s'\n", buffer); 335 336 str="param1 \"spaced param2\""; 337 r = IShellLinkA_SetArguments(sl, str); 338 ok(r == S_OK, "SetArguments failed (0x%08x)\n", r); 339 340 strcpy(buffer,"garbage"); 341 r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer)); 342 ok(r == S_OK, "GetArguments failed (0x%08x)\n", r); 343 ok(strcmp(buffer,str)==0, "GetArguments returned '%s'\n", buffer); 344 345 strcpy(buffer,"garbage"); 346 r = IShellLinkA_SetArguments(sl, NULL); 347 ok(r == S_OK, "SetArguments failed (0x%08x)\n", r); 348 r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer)); 349 ok(r == S_OK, "GetArguments failed (0x%08x)\n", r); 350 ok(!buffer[0] || strcmp(buffer,str)==0, "GetArguments returned '%s'\n", buffer); 351 352 strcpy(buffer,"garbage"); 353 r = IShellLinkA_SetArguments(sl, ""); 354 ok(r == S_OK, "SetArguments failed (0x%08x)\n", r); 355 r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer)); 356 ok(r == S_OK, "GetArguments failed (0x%08x)\n", r); 357 ok(!buffer[0], "GetArguments returned '%s'\n", buffer); 358 359 /* Test Getting / Setting showcmd */ 360 i=0xdeadbeef; 361 r = IShellLinkA_GetShowCmd(sl, &i); 362 ok(r == S_OK, "GetShowCmd failed (0x%08x)\n", r); 363 ok(i==SW_SHOWNORMAL, "GetShowCmd returned %d\n", i); 364 365 r = IShellLinkA_SetShowCmd(sl, SW_SHOWMAXIMIZED); 366 ok(r == S_OK, "SetShowCmd failed (0x%08x)\n", r); 367 368 i=0xdeadbeef; 369 r = IShellLinkA_GetShowCmd(sl, &i); 370 ok(r == S_OK, "GetShowCmd failed (0x%08x)\n", r); 371 ok(i==SW_SHOWMAXIMIZED, "GetShowCmd returned %d'\n", i); 372 373 /* Test Getting / Setting the icon */ 374 i=0xdeadbeef; 375 strcpy(buffer,"garbage"); 376 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i); 377 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r); 378 ok(*buffer=='\0', "GetIconLocation returned '%s'\n", buffer); 379 ok(i==0, "GetIconLocation returned %d\n", i); 380 381 str="c:\\nonexistent\\file"; 382 r = IShellLinkA_SetIconLocation(sl, str, 0xbabecafe); 383 ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r); 384 385 i=0xdeadbeef; 386 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i); 387 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r); 388 ok(lstrcmpiA(buffer,str)==0, "GetIconLocation returned '%s'\n", buffer); 389 ok(i==0xbabecafe, "GetIconLocation returned %d'\n", i); 390 391 /* Test Getting / Setting the hot key */ 392 w=0xbeef; 393 r = IShellLinkA_GetHotkey(sl, &w); 394 ok(r == S_OK, "GetHotkey failed (0x%08x)\n", r); 395 ok(w==0, "GetHotkey returned %d\n", w); 396 397 r = IShellLinkA_SetHotkey(sl, 0x5678); 398 ok(r == S_OK, "SetHotkey failed (0x%08x)\n", r); 399 400 w=0xbeef; 401 r = IShellLinkA_GetHotkey(sl, &w); 402 ok(r == S_OK, "GetHotkey failed (0x%08x)\n", r); 403 ok(w==0x5678, "GetHotkey returned %d'\n", w); 404 405 IShellLinkA_Release(sl); 406 } 407 408 409 /* 410 * Test saving and loading .lnk files 411 */ 412 413 #define lok ok_(__FILE__, line) 414 #define check_lnk(a,b,c) check_lnk_(__LINE__, (a), (b), (c)) 415 416 void create_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int save_fails) 417 { 418 HRESULT r; 419 IShellLinkA *sl; 420 IPersistFile *pf; 421 422 r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 423 &IID_IShellLinkA, (LPVOID*)&sl); 424 lok(r == S_OK, "no IID_IShellLinkA (0x%08x)\n", r); 425 if (r != S_OK) 426 return; 427 428 if (desc->description) 429 { 430 r = IShellLinkA_SetDescription(sl, desc->description); 431 lok(r == S_OK, "SetDescription failed (0x%08x)\n", r); 432 } 433 if (desc->workdir) 434 { 435 r = IShellLinkA_SetWorkingDirectory(sl, desc->workdir); 436 lok(r == S_OK, "SetWorkingDirectory failed (0x%08x)\n", r); 437 } 438 if (desc->path) 439 { 440 r = IShellLinkA_SetPath(sl, desc->path); 441 lok(SUCCEEDED(r), "SetPath failed (0x%08x)\n", r); 442 } 443 if (desc->pidl) 444 { 445 r = IShellLinkA_SetIDList(sl, desc->pidl); 446 lok(r == S_OK, "SetIDList failed (0x%08x)\n", r); 447 } 448 if (desc->arguments) 449 { 450 r = IShellLinkA_SetArguments(sl, desc->arguments); 451 lok(r == S_OK, "SetArguments failed (0x%08x)\n", r); 452 } 453 if (desc->showcmd) 454 { 455 r = IShellLinkA_SetShowCmd(sl, desc->showcmd); 456 lok(r == S_OK, "SetShowCmd failed (0x%08x)\n", r); 457 } 458 if (desc->icon) 459 { 460 r = IShellLinkA_SetIconLocation(sl, desc->icon, desc->icon_id); 461 lok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r); 462 } 463 if (desc->hotkey) 464 { 465 r = IShellLinkA_SetHotkey(sl, desc->hotkey); 466 lok(r == S_OK, "SetHotkey failed (0x%08x)\n", r); 467 } 468 469 r = IShellLinkA_QueryInterface(sl, &IID_IPersistFile, (void**)&pf); 470 lok(r == S_OK, "no IID_IPersistFile (0x%08x)\n", r); 471 if (r == S_OK) 472 { 473 LPOLESTR str; 474 475 if (0) 476 { 477 /* crashes on XP */ 478 IPersistFile_GetCurFile(pf, NULL); 479 } 480 481 /* test GetCurFile before ::Save */ 482 str = (LPWSTR)0xdeadbeef; 483 r = IPersistFile_GetCurFile(pf, &str); 484 lok(r == S_FALSE || 485 broken(r == S_OK), /* shell32 < 5.0 */ 486 "got 0x%08x\n", r); 487 lok(str == NULL, "got %p\n", str); 488 489 r = IPersistFile_Save(pf, path, TRUE); 490 todo_wine_if (save_fails) 491 lok(r == S_OK, "save failed (0x%08x)\n", r); 492 493 /* test GetCurFile after ::Save */ 494 r = IPersistFile_GetCurFile(pf, &str); 495 lok(r == S_OK, "got 0x%08x\n", r); 496 lok(str != NULL || 497 broken(str == NULL), /* shell32 < 5.0 */ 498 "Didn't expect NULL\n"); 499 if (str != NULL) 500 { 501 IMalloc *pmalloc; 502 503 lok(!winetest_strcmpW(path, str), "Expected %s, got %s\n", 504 wine_dbgstr_w(path), wine_dbgstr_w(str)); 505 506 SHGetMalloc(&pmalloc); 507 IMalloc_Free(pmalloc, str); 508 } 509 else 510 win_skip("GetCurFile fails on shell32 < 5.0\n"); 511 512 IPersistFile_Release(pf); 513 } 514 515 IShellLinkA_Release(sl); 516 } 517 518 static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int todo) 519 { 520 HRESULT r; 521 IShellLinkA *sl; 522 IPersistFile *pf; 523 char buffer[INFOTIPSIZE]; 524 LPOLESTR str; 525 526 r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 527 &IID_IShellLinkA, (LPVOID*)&sl); 528 lok(r == S_OK, "no IID_IShellLinkA (0x%08x)\n", r); 529 if (r != S_OK) 530 return; 531 532 r = IShellLinkA_QueryInterface(sl, &IID_IPersistFile, (LPVOID*)&pf); 533 lok(r == S_OK, "no IID_IPersistFile (0x%08x)\n", r); 534 if (r != S_OK) 535 { 536 IShellLinkA_Release(sl); 537 return; 538 } 539 540 /* test GetCurFile before ::Load */ 541 str = (LPWSTR)0xdeadbeef; 542 r = IPersistFile_GetCurFile(pf, &str); 543 lok(r == S_FALSE || 544 broken(r == S_OK), /* shell32 < 5.0 */ 545 "got 0x%08x\n", r); 546 lok(str == NULL, "got %p\n", str); 547 548 r = IPersistFile_Load(pf, path, STGM_READ); 549 lok(r == S_OK, "load failed (0x%08x)\n", r); 550 551 /* test GetCurFile after ::Save */ 552 r = IPersistFile_GetCurFile(pf, &str); 553 lok(r == S_OK, "got 0x%08x\n", r); 554 lok(str != NULL || 555 broken(str == NULL), /* shell32 < 5.0 */ 556 "Didn't expect NULL\n"); 557 if (str != NULL) 558 { 559 IMalloc *pmalloc; 560 561 lok(!winetest_strcmpW(path, str), "Expected %s, got %s\n", 562 wine_dbgstr_w(path), wine_dbgstr_w(str)); 563 564 SHGetMalloc(&pmalloc); 565 IMalloc_Free(pmalloc, str); 566 } 567 else 568 win_skip("GetCurFile fails on shell32 < 5.0\n"); 569 570 IPersistFile_Release(pf); 571 if (r != S_OK) 572 { 573 IShellLinkA_Release(sl); 574 return; 575 } 576 577 if (desc->description) 578 { 579 strcpy(buffer,"garbage"); 580 r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer)); 581 lok(r == S_OK, "GetDescription failed (0x%08x)\n", r); 582 todo_wine_if ((todo & 0x1) != 0) 583 lok(strcmp(buffer, desc->description)==0, "GetDescription returned '%s' instead of '%s'\n", 584 buffer, desc->description); 585 } 586 if (desc->workdir) 587 { 588 strcpy(buffer,"garbage"); 589 r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer)); 590 lok(r == S_OK, "GetWorkingDirectory failed (0x%08x)\n", r); 591 todo_wine_if ((todo & 0x2) != 0) 592 lok(lstrcmpiA(buffer, desc->workdir)==0, "GetWorkingDirectory returned '%s' instead of '%s'\n", 593 buffer, desc->workdir); 594 } 595 if (desc->path) 596 { 597 strcpy(buffer,"garbage"); 598 r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); 599 lok(SUCCEEDED(r), "GetPath failed (0x%08x)\n", r); 600 todo_wine_if ((todo & 0x4) != 0) 601 lok(lstrcmpiA(buffer, desc->path)==0, "GetPath returned '%s' instead of '%s'\n", 602 buffer, desc->path); 603 } 604 if (desc->pidl) 605 { 606 LPITEMIDLIST pidl=NULL; 607 r = IShellLinkA_GetIDList(sl, &pidl); 608 lok(r == S_OK, "GetIDList failed (0x%08x)\n", r); 609 todo_wine_if ((todo & 0x8) != 0) 610 lok(pILIsEqual(pidl, desc->pidl), "GetIDList returned an incorrect pidl\n"); 611 } 612 if (desc->showcmd) 613 { 614 int i=0xdeadbeef; 615 r = IShellLinkA_GetShowCmd(sl, &i); 616 lok(r == S_OK, "GetShowCmd failed (0x%08x)\n", r); 617 todo_wine_if ((todo & 0x10) != 0) 618 lok(i==desc->showcmd, "GetShowCmd returned 0x%0x instead of 0x%0x\n", 619 i, desc->showcmd); 620 } 621 if (desc->icon) 622 { 623 int i=0xdeadbeef; 624 strcpy(buffer,"garbage"); 625 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i); 626 lok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r); 627 todo_wine_if ((todo & 0x20) != 0) { 628 lok(lstrcmpiA(buffer, desc->icon)==0, "GetIconLocation returned '%s' instead of '%s'\n", 629 buffer, desc->icon); 630 lok(i==desc->icon_id, "GetIconLocation returned 0x%0x instead of 0x%0x\n", 631 i, desc->icon_id); 632 } 633 } 634 if (desc->hotkey) 635 { 636 WORD i=0xbeef; 637 r = IShellLinkA_GetHotkey(sl, &i); 638 lok(r == S_OK, "GetHotkey failed (0x%08x)\n", r); 639 todo_wine_if ((todo & 0x40) != 0) 640 lok(i==desc->hotkey, "GetHotkey returned 0x%04x instead of 0x%04x\n", 641 i, desc->hotkey); 642 } 643 644 IShellLinkA_Release(sl); 645 } 646 647 static void test_load_save(void) 648 { 649 WCHAR lnkfile[MAX_PATH]; 650 char lnkfileA[MAX_PATH]; 651 static const char lnkfileA_name[] = "\\test.lnk"; 652 653 lnk_desc_t desc; 654 char mypath[MAX_PATH]; 655 char mydir[MAX_PATH]; 656 char realpath[MAX_PATH]; 657 char* p; 658 HANDLE hf; 659 DWORD r; 660 661 if (!pGetLongPathNameA) 662 { 663 win_skip("GetLongPathNameA is not available\n"); 664 return; 665 } 666 667 /* Don't used a fixed path for the test.lnk file */ 668 GetTempPathA(MAX_PATH, lnkfileA); 669 lstrcatA(lnkfileA, lnkfileA_name); 670 MultiByteToWideChar(CP_ACP, 0, lnkfileA, -1, lnkfile, MAX_PATH); 671 672 /* Save an empty .lnk file */ 673 memset(&desc, 0, sizeof(desc)); 674 create_lnk(lnkfile, &desc, 0); 675 676 /* It should come back as a bunch of empty strings */ 677 desc.description=""; 678 desc.workdir=""; 679 desc.path=""; 680 desc.arguments=""; 681 desc.icon=""; 682 check_lnk(lnkfile, &desc, 0x0); 683 684 /* Point a .lnk file to nonexistent files */ 685 desc.description=""; 686 desc.workdir="c:\\Nonexitent\\work\\directory"; 687 desc.path="c:\\nonexistent\\path"; 688 desc.pidl=NULL; 689 desc.arguments=""; 690 desc.showcmd=0; 691 desc.icon="c:\\nonexistent\\icon\\file"; 692 desc.icon_id=1234; 693 desc.hotkey=0; 694 create_lnk(lnkfile, &desc, 0); 695 check_lnk(lnkfile, &desc, 0x0); 696 697 r=GetModuleFileNameA(NULL, mypath, sizeof(mypath)); 698 ok(r<sizeof(mypath), "GetModuleFileName failed (%d)\n", r); 699 strcpy(mydir, mypath); 700 p=strrchr(mydir, '\\'); 701 if (p) 702 *p='\0'; 703 704 /* IShellLink returns path in long form */ 705 if (!pGetLongPathNameA(mypath, realpath, MAX_PATH)) strcpy( realpath, mypath ); 706 707 /* Overwrite the existing lnk file and point it to existing files */ 708 desc.description="test 2"; 709 desc.workdir=mydir; 710 desc.path=realpath; 711 desc.pidl=NULL; 712 desc.arguments="/option1 /option2 \"Some string\""; 713 desc.showcmd=SW_SHOWNORMAL; 714 desc.icon=mypath; 715 desc.icon_id=0; 716 desc.hotkey=0x1234; 717 create_lnk(lnkfile, &desc, 0); 718 check_lnk(lnkfile, &desc, 0x0); 719 720 /* Test omitting .exe from an absolute path */ 721 p=strrchr(realpath, '.'); 722 if (p) 723 *p='\0'; 724 725 desc.description="absolute path without .exe"; 726 desc.workdir=mydir; 727 desc.path=realpath; 728 desc.pidl=NULL; 729 desc.arguments="/option1 /option2 \"Some string\""; 730 desc.showcmd=SW_SHOWNORMAL; 731 desc.icon=mypath; 732 desc.icon_id=0; 733 desc.hotkey=0x1234; 734 create_lnk(lnkfile, &desc, 0); 735 strcat(realpath, ".exe"); 736 check_lnk(lnkfile, &desc, 0x4); 737 738 /* Overwrite the existing lnk file and test link to a command on the path */ 739 desc.description="command on path"; 740 desc.workdir=mypath; 741 desc.path="rundll32.exe"; 742 desc.pidl=NULL; 743 desc.arguments="/option1 /option2 \"Some string\""; 744 desc.showcmd=SW_SHOWNORMAL; 745 desc.icon=mypath; 746 desc.icon_id=0; 747 desc.hotkey=0x1234; 748 create_lnk(lnkfile, &desc, 0); 749 /* Check that link is created to proper location */ 750 SearchPathA( NULL, desc.path, NULL, MAX_PATH, realpath, NULL); 751 desc.path=realpath; 752 check_lnk(lnkfile, &desc, 0x0); 753 754 /* Test omitting .exe from a command on the path */ 755 desc.description="command on path without .exe"; 756 desc.workdir=mypath; 757 desc.path="rundll32"; 758 desc.pidl=NULL; 759 desc.arguments="/option1 /option2 \"Some string\""; 760 desc.showcmd=SW_SHOWNORMAL; 761 desc.icon=mypath; 762 desc.icon_id=0; 763 desc.hotkey=0x1234; 764 create_lnk(lnkfile, &desc, 0); 765 /* Check that link is created to proper location */ 766 SearchPathA( NULL, "rundll32", NULL, MAX_PATH, realpath, NULL); 767 desc.path=realpath; 768 check_lnk(lnkfile, &desc, 0x4); 769 770 /* Create a temporary non-executable file */ 771 r=GetTempPathA(sizeof(mypath), mypath); 772 ok(r<sizeof(mypath), "GetTempPath failed (%d), err %d\n", r, GetLastError()); 773 r=pGetLongPathNameA(mypath, mydir, sizeof(mydir)); 774 ok(r<sizeof(mydir), "GetLongPathName failed (%d), err %d\n", r, GetLastError()); 775 p=strrchr(mydir, '\\'); 776 if (p) 777 *p='\0'; 778 779 strcpy(mypath, mydir); 780 strcat(mypath, "\\test.txt"); 781 hf = CreateFileA(mypath, GENERIC_WRITE, 0, NULL, 782 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 783 CloseHandle(hf); 784 785 /* Overwrite the existing lnk file and test link to an existing non-executable file */ 786 desc.description="non-executable file"; 787 desc.workdir=mydir; 788 desc.path=mypath; 789 desc.pidl=NULL; 790 desc.arguments=""; 791 desc.showcmd=SW_SHOWNORMAL; 792 desc.icon=mypath; 793 desc.icon_id=0; 794 desc.hotkey=0x1234; 795 create_lnk(lnkfile, &desc, 0); 796 check_lnk(lnkfile, &desc, 0x0); 797 798 r=pGetShortPathNameA(mydir, mypath, sizeof(mypath)); 799 ok(r<sizeof(mypath), "GetShortPathName failed (%d), err %d\n", r, GetLastError()); 800 801 strcpy(realpath, mypath); 802 strcat(realpath, "\\test.txt"); 803 strcat(mypath, "\\\\test.txt"); 804 805 /* Overwrite the existing lnk file and test link to a short path with double backslashes */ 806 desc.description="non-executable file"; 807 desc.workdir=mydir; 808 desc.path=mypath; 809 desc.pidl=NULL; 810 desc.arguments=""; 811 desc.showcmd=SW_SHOWNORMAL; 812 desc.icon=mypath; 813 desc.icon_id=0; 814 desc.hotkey=0x1234; 815 create_lnk(lnkfile, &desc, 0); 816 desc.path=realpath; 817 check_lnk(lnkfile, &desc, 0x0); 818 819 r = DeleteFileA(mypath); 820 ok(r, "failed to delete file %s (%d)\n", mypath, GetLastError()); 821 822 /* Create a temporary .bat file */ 823 strcpy(mypath, mydir); 824 strcat(mypath, "\\test.bat"); 825 hf = CreateFileA(mypath, GENERIC_WRITE, 0, NULL, 826 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 827 CloseHandle(hf); 828 829 strcpy(realpath, mypath); 830 831 p=strrchr(mypath, '.'); 832 if (p) 833 *p='\0'; 834 835 /* Try linking to the .bat file without the extension */ 836 desc.description="batch file"; 837 desc.workdir=mydir; 838 desc.path=mypath; 839 desc.pidl=NULL; 840 desc.arguments=""; 841 desc.showcmd=SW_SHOWNORMAL; 842 desc.icon=mypath; 843 desc.icon_id=0; 844 desc.hotkey=0x1234; 845 create_lnk(lnkfile, &desc, 0); 846 desc.path = realpath; 847 check_lnk(lnkfile, &desc, 0x4); 848 849 r = DeleteFileA(realpath); 850 ok(r, "failed to delete file %s (%d)\n", realpath, GetLastError()); 851 852 /* FIXME: Also test saving a .lnk pointing to a pidl that cannot be 853 * represented as a path. 854 */ 855 856 /* DeleteFileW is not implemented on Win9x */ 857 r=DeleteFileA(lnkfileA); 858 ok(r, "failed to delete link '%s' (%d)\n", lnkfileA, GetLastError()); 859 } 860 861 static void test_datalink(void) 862 { 863 static const WCHAR lnk[] = { 864 ':',':','{','9','d','b','1','1','8','6','e','-','4','0','d','f','-','1', 865 '1','d','1','-','a','a','8','c','-','0','0','c','0','4','f','b','6','7', 866 '8','6','3','}',':','2','6',',','!','!','g','x','s','f','(','N','g',']', 867 'q','F','`','H','{','L','s','A','C','C','E','S','S','F','i','l','e','s', 868 '>','p','l','T',']','j','I','{','j','f','(','=','1','&','L','[','-','8', 869 '1','-',']',':',':',0 }; 870 static const WCHAR comp[] = { 871 '2','6',',','!','!','g','x','s','f','(','N','g',']','q','F','`','H','{', 872 'L','s','A','C','C','E','S','S','F','i','l','e','s','>','p','l','T',']', 873 'j','I','{','j','f','(','=','1','&','L','[','-','8','1','-',']',0 }; 874 IShellLinkDataList *dl = NULL; 875 IShellLinkW *sl = NULL; 876 HRESULT r; 877 DWORD flags = 0; 878 EXP_DARWIN_LINK *dar; 879 880 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 881 &IID_IShellLinkW, (LPVOID*)&sl ); 882 ok( r == S_OK || 883 broken(r == E_NOINTERFACE), /* Win9x */ 884 "CoCreateInstance failed (0x%08x)\n", r); 885 if (!sl) 886 { 887 win_skip("no shelllink\n"); 888 return; 889 } 890 891 r = IShellLinkW_QueryInterface( sl, &_IID_IShellLinkDataList, (LPVOID*) &dl ); 892 ok( r == S_OK || 893 broken(r == E_NOINTERFACE), /* NT4 */ 894 "IShellLinkW_QueryInterface failed (0x%08x)\n", r); 895 896 if (!dl) 897 { 898 win_skip("no datalink interface\n"); 899 IShellLinkW_Release( sl ); 900 return; 901 } 902 903 flags = 0; 904 r = IShellLinkDataList_GetFlags( dl, &flags ); 905 ok( r == S_OK, "GetFlags failed\n"); 906 ok( flags == 0, "GetFlags returned wrong flags\n"); 907 908 dar = (void*)-1; 909 r = IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG, (LPVOID*) &dar ); 910 ok( r == E_FAIL, "CopyDataBlock failed\n"); 911 ok( dar == NULL, "should be null\n"); 912 913 if (!pGetLongPathNameA /* NT4 */) 914 skip("SetPath with NULL parameter crashes on NT4\n"); 915 else 916 { 917 r = IShellLinkW_SetPath(sl, NULL); 918 ok(r == E_INVALIDARG, "SetPath returned wrong error (0x%08x)\n", r); 919 } 920 921 r = IShellLinkW_SetPath(sl, lnk); 922 ok(r == S_OK, "SetPath failed\n"); 923 924 if (0) 925 { 926 /* the following crashes */ 927 IShellLinkDataList_GetFlags( dl, NULL ); 928 } 929 930 flags = 0; 931 r = IShellLinkDataList_GetFlags( dl, &flags ); 932 ok( r == S_OK, "GetFlags failed\n"); 933 /* SLDF_HAS_LOGO3ID is no longer supported on Vista+, filter it out */ 934 ok( (flags & (~ SLDF_HAS_LOGO3ID)) == SLDF_HAS_DARWINID, 935 "GetFlags returned wrong flags\n"); 936 937 dar = NULL; 938 r = IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG, (LPVOID*) &dar ); 939 ok( r == S_OK, "CopyDataBlock failed\n"); 940 941 ok( dar && ((DATABLOCK_HEADER*)dar)->dwSignature == EXP_DARWIN_ID_SIG, "signature wrong\n"); 942 ok( dar && 0==lstrcmpW(dar->szwDarwinID, comp ), "signature wrong\n"); 943 944 LocalFree( dar ); 945 946 IShellLinkDataList_Release( dl ); 947 IShellLinkW_Release( sl ); 948 } 949 950 static void test_shdefextracticon(void) 951 { 952 HICON hiconlarge=NULL, hiconsmall=NULL; 953 HRESULT res; 954 955 if (!pSHDefExtractIconA) 956 { 957 win_skip("SHDefExtractIconA is unavailable\n"); 958 return; 959 } 960 961 res = pSHDefExtractIconA("shell32.dll", 0, 0, &hiconlarge, &hiconsmall, MAKELONG(16,24)); 962 ok(SUCCEEDED(res), "SHDefExtractIconA failed, res=%x\n", res); 963 ok(hiconlarge != NULL, "got null hiconlarge\n"); 964 ok(hiconsmall != NULL, "got null hiconsmall\n"); 965 DestroyIcon(hiconlarge); 966 DestroyIcon(hiconsmall); 967 968 hiconsmall = NULL; 969 res = pSHDefExtractIconA("shell32.dll", 0, 0, NULL, &hiconsmall, MAKELONG(16,24)); 970 ok(SUCCEEDED(res), "SHDefExtractIconA failed, res=%x\n", res); 971 ok(hiconsmall != NULL, "got null hiconsmall\n"); 972 DestroyIcon(hiconsmall); 973 974 res = pSHDefExtractIconA("shell32.dll", 0, 0, NULL, NULL, MAKELONG(16,24)); 975 ok(SUCCEEDED(res), "SHDefExtractIconA failed, res=%x\n", res); 976 } 977 978 static void test_GetIconLocation(void) 979 { 980 IShellLinkW *slW; 981 IShellLinkA *sl; 982 const char *str; 983 char buffer[INFOTIPSIZE], mypath[MAX_PATH]; 984 int i; 985 HRESULT r; 986 LPITEMIDLIST pidl; 987 988 r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 989 &IID_IShellLinkA, (LPVOID*)&sl); 990 ok(r == S_OK, "no IID_IShellLinkA (0x%08x)\n", r); 991 if(r != S_OK) 992 return; 993 994 i = 0xdeadbeef; 995 strcpy(buffer, "garbage"); 996 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i); 997 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r); 998 ok(*buffer == '\0', "GetIconLocation returned '%s'\n", buffer); 999 ok(i == 0, "GetIconLocation returned %d\n", i); 1000 1001 str = "c:\\some\\path"; 1002 r = IShellLinkA_SetPath(sl, str); 1003 ok(r == S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r); 1004 1005 i = 0xdeadbeef; 1006 strcpy(buffer, "garbage"); 1007 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i); 1008 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r); 1009 ok(*buffer == '\0', "GetIconLocation returned '%s'\n", buffer); 1010 ok(i == 0, "GetIconLocation returned %d\n", i); 1011 1012 GetWindowsDirectoryA(mypath, sizeof(mypath) - 12); 1013 strcat(mypath, "\\regedit.exe"); 1014 pidl = path_to_pidl(mypath); 1015 r = IShellLinkA_SetIDList(sl, pidl); 1016 ok(r == S_OK, "SetPath failed (0x%08x)\n", r); 1017 pILFree(pidl); 1018 1019 i = 0xdeadbeef; 1020 strcpy(buffer, "garbage"); 1021 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i); 1022 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r); 1023 ok(*buffer == '\0', "GetIconLocation returned '%s'\n", buffer); 1024 ok(i == 0, "GetIconLocation returned %d\n", i); 1025 1026 str = "c:\\nonexistent\\file"; 1027 r = IShellLinkA_SetIconLocation(sl, str, 0xbabecafe); 1028 ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r); 1029 1030 i = 0xdeadbeef; 1031 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i); 1032 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r); 1033 ok(lstrcmpiA(buffer,str) == 0, "GetIconLocation returned '%s'\n", buffer); 1034 ok(i == 0xbabecafe, "GetIconLocation returned %#x.\n", i); 1035 1036 r = IShellLinkA_SetIconLocation(sl, NULL, 0xcafefe); 1037 ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r); 1038 1039 i = 0xdeadbeef; 1040 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i); 1041 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r); 1042 ok(!*buffer, "GetIconLocation returned '%s'\n", buffer); 1043 ok(i == 0xcafefe, "GetIconLocation returned %#x.\n", i); 1044 1045 r = IShellLinkA_QueryInterface(sl, &IID_IShellLinkW, (void **)&slW); 1046 ok(SUCCEEDED(r), "Failed to get IShellLinkW, hr %#x.\n", r); 1047 1048 str = "c:\\nonexistent\\file"; 1049 r = IShellLinkA_SetIconLocation(sl, str, 0xbabecafe); 1050 ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r); 1051 1052 r = IShellLinkA_SetIconLocation(sl, NULL, 0xcafefe); 1053 ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r); 1054 1055 i = 0xdeadbeef; 1056 r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i); 1057 ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r); 1058 ok(!*buffer, "GetIconLocation returned '%s'\n", buffer); 1059 ok(i == 0xcafefe, "GetIconLocation returned %#x.\n", i); 1060 1061 IShellLinkW_Release(slW); 1062 IShellLinkA_Release(sl); 1063 } 1064 1065 static void test_SHGetStockIconInfo(void) 1066 { 1067 BYTE buffer[sizeof(SHSTOCKICONINFO) + 16]; 1068 SHSTOCKICONINFO *sii = (SHSTOCKICONINFO *) buffer; 1069 HRESULT hr; 1070 INT i; 1071 1072 /* not present before vista */ 1073 if (!pSHGetStockIconInfo) 1074 { 1075 win_skip("SHGetStockIconInfo not available\n"); 1076 return; 1077 } 1078 1079 /* negative values are handled */ 1080 memset(buffer, '#', sizeof(buffer)); 1081 sii->cbSize = sizeof(SHSTOCKICONINFO); 1082 hr = pSHGetStockIconInfo(SIID_INVALID, SHGSI_ICONLOCATION, sii); 1083 ok(hr == E_INVALIDARG, "-1: got 0x%x (expected E_INVALIDARG)\n", hr); 1084 1085 /* max. id for vista is 140 (no definition exists for this value) */ 1086 for (i = SIID_DOCNOASSOC; i <= SIID_CLUSTEREDDRIVE; i++) 1087 { 1088 memset(buffer, '#', sizeof(buffer)); 1089 sii->cbSize = sizeof(SHSTOCKICONINFO); 1090 hr = pSHGetStockIconInfo(i, SHGSI_ICONLOCATION, sii); 1091 1092 ok(hr == S_OK, 1093 "%3d: got 0x%x, iSysImageIndex: 0x%x, iIcon: 0x%x (expected S_OK)\n", 1094 i, hr, sii->iSysImageIndex, sii->iIcon); 1095 1096 if ((hr == S_OK) && (winetest_debug > 1)) 1097 trace("%3d: got iSysImageIndex %3d, iIcon %3d and %s\n", i, sii->iSysImageIndex, 1098 sii->iIcon, wine_dbgstr_w(sii->szPath)); 1099 } 1100 1101 /* test invalid icons indices that are invalid for all platforms */ 1102 for (i = SIID_MAX_ICONS; i < (SIID_MAX_ICONS + 25) ; i++) 1103 { 1104 memset(buffer, '#', sizeof(buffer)); 1105 sii->cbSize = sizeof(SHSTOCKICONINFO); 1106 hr = pSHGetStockIconInfo(i, SHGSI_ICONLOCATION, sii); 1107 ok(hr == E_INVALIDARG, "%3d: got 0x%x (expected E_INVALIDARG)\n", i, hr); 1108 todo_wine { 1109 ok(sii->iSysImageIndex == -1, "%d: got iSysImageIndex %d\n", i, sii->iSysImageIndex); 1110 ok(sii->iIcon == -1, "%d: got iIcon %d\n", i, sii->iIcon); 1111 } 1112 } 1113 1114 /* test more returned SHSTOCKICONINFO elements without extra flags */ 1115 memset(buffer, '#', sizeof(buffer)); 1116 sii->cbSize = sizeof(SHSTOCKICONINFO); 1117 hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, sii); 1118 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr); 1119 ok(!sii->hIcon, "got %p (expected NULL)\n", sii->hIcon); 1120 ok(sii->iSysImageIndex == -1, "got %d (expected -1)\n", sii->iSysImageIndex); 1121 1122 /* the exact size is required of the struct */ 1123 memset(buffer, '#', sizeof(buffer)); 1124 sii->cbSize = sizeof(SHSTOCKICONINFO) + 2; 1125 hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, sii); 1126 ok(hr == E_INVALIDARG, "+2: got 0x%x, iSysImageIndex: 0x%x, iIcon: 0x%x\n", hr, sii->iSysImageIndex, sii->iIcon); 1127 1128 memset(buffer, '#', sizeof(buffer)); 1129 sii->cbSize = sizeof(SHSTOCKICONINFO) + 1; 1130 hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, sii); 1131 ok(hr == E_INVALIDARG, "+1: got 0x%x, iSysImageIndex: 0x%x, iIcon: 0x%x\n", hr, sii->iSysImageIndex, sii->iIcon); 1132 1133 memset(buffer, '#', sizeof(buffer)); 1134 sii->cbSize = sizeof(SHSTOCKICONINFO) - 1; 1135 hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, sii); 1136 ok(hr == E_INVALIDARG, "-1: got 0x%x, iSysImageIndex: 0x%x, iIcon: 0x%x\n", hr, sii->iSysImageIndex, sii->iIcon); 1137 1138 memset(buffer, '#', sizeof(buffer)); 1139 sii->cbSize = sizeof(SHSTOCKICONINFO) - 2; 1140 hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, sii); 1141 ok(hr == E_INVALIDARG, "-2: got 0x%x, iSysImageIndex: 0x%x, iIcon: 0x%x\n", hr, sii->iSysImageIndex, sii->iIcon); 1142 1143 /* there is a NULL check for the struct */ 1144 hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, NULL); 1145 ok(hr == E_INVALIDARG, "NULL: got 0x%x\n", hr); 1146 1147 for(i = 0; i < 140; i++) /* highest on wvista, i > 140 gives E_INVALIDARG, win7 can go higher */ 1148 { 1149 memset(buffer, 0, sizeof(buffer)); 1150 sii->cbSize = sizeof(SHSTOCKICONINFO); 1151 hr = pSHGetStockIconInfo(i, SHGSI_ICON | SHGSI_SMALLICON, sii); 1152 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr); 1153 ok(sii->hIcon != NULL, "got NULL, expected an icon handle\n"); 1154 ok(sii->iIcon != 0, "got unexpected 0 for SIID %d\n", i); /* howto find out exact sii->iIcon value??? */ 1155 ok(sii->iSysImageIndex == -1, "got %d (expected -1)\n", sii->iSysImageIndex); 1156 ok(DestroyIcon(sii->hIcon), "DestroyIcon failed\n"); 1157 if (winetest_debug > 1) 1158 trace("%3d: got iSysImageIndex %3d, iIcon %3d and %s\n", i, sii->iSysImageIndex, 1159 sii->iIcon, wine_dbgstr_w(sii->szPath)); 1160 } 1161 } 1162 1163 static void test_SHExtractIcons(void) 1164 { 1165 static const WCHAR notepadW[] = {'n','o','t','e','p','a','d','.','e','x','e',0}; 1166 static const WCHAR shell32W[] = {'s','h','e','l','l','3','2','.','d','l','l',0}; 1167 static const WCHAR emptyW[] = {0}; 1168 UINT ret, ret2; 1169 HICON icons[256]; 1170 UINT ids[256], i; 1171 1172 if (!pSHExtractIconsW) 1173 { 1174 win_skip("SHExtractIconsW not available\n"); 1175 return; 1176 } 1177 1178 ret = pSHExtractIconsW(emptyW, 0, 16, 16, icons, ids, 1, 0); 1179 ok(ret == ~0u, "got %u\n", ret); 1180 1181 ret = pSHExtractIconsW(notepadW, 0, 16, 16, NULL, NULL, 1, 0); 1182 ok(ret == 1 || broken(ret == 2) /* win2k */, "got %u\n", ret); 1183 1184 icons[0] = (HICON)0xdeadbeef; 1185 ret = pSHExtractIconsW(notepadW, 0, 16, 16, icons, NULL, 1, 0); 1186 ok(ret == 1, "got %u\n", ret); 1187 ok(icons[0] != (HICON)0xdeadbeef, "icon not set\n"); 1188 DestroyIcon(icons[0]); 1189 1190 icons[0] = (HICON)0xdeadbeef; 1191 ids[0] = 0xdeadbeef; 1192 ret = pSHExtractIconsW(notepadW, 0, 16, 16, icons, ids, 1, 0); 1193 ok(ret == 1, "got %u\n", ret); 1194 ok(icons[0] != (HICON)0xdeadbeef, "icon not set\n"); 1195 ok(ids[0] != 0xdeadbeef, "id not set\n"); 1196 DestroyIcon(icons[0]); 1197 1198 ret = pSHExtractIconsW(shell32W, 0, 16, 16, NULL, NULL, 0, 0); 1199 ret2 = pSHExtractIconsW(shell32W, 4, MAKELONG(32,16), MAKELONG(32,16), NULL, NULL, 256, 0); 1200 ok(ret && ret == ret2, 1201 "icon count should be independent of requested icon sizes and base icon index\n"); 1202 1203 ret = pSHExtractIconsW(shell32W, 0, 16, 16, icons, ids, 0, 0); 1204 ok(ret == ~0u || !ret /* < vista */, "got %u\n", ret); 1205 1206 ret = pSHExtractIconsW(shell32W, 0, 16, 16, icons, ids, 3, 0); 1207 ok(ret == 3, "got %u\n", ret); 1208 for (i = 0; i < ret; i++) DestroyIcon(icons[i]); 1209 1210 /* count must be a multiple of two when getting two sizes */ 1211 ret = pSHExtractIconsW(shell32W, 0, MAKELONG(16,32), MAKELONG(16,32), icons, ids, 3, 0); 1212 ok(!ret /* vista */ || ret == 4, "got %u\n", ret); 1213 for (i = 0; i < ret; i++) DestroyIcon(icons[i]); 1214 1215 ret = pSHExtractIconsW(shell32W, 0, MAKELONG(16,32), MAKELONG(16,32), icons, ids, 4, 0); 1216 ok(ret == 4, "got %u\n", ret); 1217 for (i = 0; i < ret; i++) DestroyIcon(icons[i]); 1218 } 1219 1220 static void test_propertystore(void) 1221 { 1222 IShellLinkA *linkA; 1223 IShellLinkW *linkW; 1224 IPropertyStore *ps; 1225 HRESULT hr; 1226 1227 hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 1228 &IID_IShellLinkA, (void**)&linkA); 1229 ok(hr == S_OK, "got 0x%08x\n", hr); 1230 1231 hr = IShellLinkA_QueryInterface(linkA, &IID_IShellLinkW, (void**)&linkW); 1232 ok(hr == S_OK, "got 0x%08x\n", hr); 1233 1234 hr = IShellLinkA_QueryInterface(linkA, &IID_IPropertyStore, (void**)&ps); 1235 if (hr == S_OK) { 1236 IPropertyStoreCache *pscache; 1237 1238 IPropertyStore_Release(ps); 1239 1240 hr = IShellLinkW_QueryInterface(linkW, &IID_IPropertyStore, (void**)&ps); 1241 ok(hr == S_OK, "got 0x%08x\n", hr); 1242 1243 hr = IPropertyStore_QueryInterface(ps, &IID_IPropertyStoreCache, (void**)&pscache); 1244 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); 1245 1246 IPropertyStore_Release(ps); 1247 } 1248 else 1249 win_skip("IShellLink doesn't support IPropertyStore.\n"); 1250 1251 IShellLinkA_Release(linkA); 1252 IShellLinkW_Release(linkW); 1253 } 1254 1255 static void test_ExtractIcon(void) 1256 { 1257 static const WCHAR nameW[] = {'\\','e','x','t','r','a','c','t','i','c','o','n','_','t','e','s','t','.','t','x','t',0}; 1258 static const WCHAR shell32W[] = {'s','h','e','l','l','3','2','.','d','l','l',0}; 1259 WCHAR pathW[MAX_PATH]; 1260 HICON hicon, hicon2; 1261 char path[MAX_PATH]; 1262 HANDLE file; 1263 int r; 1264 ICONINFO info; 1265 BITMAP bm; 1266 1267 /* specified instance handle */ 1268 hicon = ExtractIconA(GetModuleHandleA("shell32.dll"), NULL, 0); 1269 todo_wine 1270 ok(hicon == NULL, "Got icon %p\n", hicon); 1271 hicon2 = ExtractIconA(GetModuleHandleA("shell32.dll"), "shell32.dll", -1); 1272 ok(hicon2 != NULL, "Got icon %p\n", hicon2); 1273 1274 /* existing index */ 1275 hicon = ExtractIconA(NULL, "shell32.dll", 0); 1276 ok(hicon != NULL && HandleToLong(hicon) != -1, "Got icon %p\n", hicon); 1277 DestroyIcon(hicon); 1278 1279 /* returns number of resources */ 1280 hicon = ExtractIconA(NULL, "shell32.dll", -1); 1281 ok(HandleToLong(hicon) > 1 && hicon == hicon2, "Got icon %p\n", hicon); 1282 1283 /* invalid index, valid dll name */ 1284 hicon = ExtractIconA(NULL, "shell32.dll", 3000); 1285 ok(hicon == NULL, "Got icon %p\n", hicon); 1286 1287 /* Create a temporary non-executable file */ 1288 GetTempPathA(sizeof(path), path); 1289 strcat(path, "\\extracticon_test.txt"); 1290 file = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 1291 ok(file != INVALID_HANDLE_VALUE, "Failed to create a test file\n"); 1292 CloseHandle(file); 1293 1294 hicon = ExtractIconA(NULL, path, 0); 1295 todo_wine 1296 ok(hicon == NULL, "Got icon %p\n", hicon); 1297 1298 hicon = ExtractIconA(NULL, path, -1); 1299 ok(hicon == NULL, "Got icon %p\n", hicon); 1300 1301 hicon = ExtractIconA(NULL, path, 1); 1302 todo_wine 1303 ok(hicon == NULL, "Got icon %p\n", hicon); 1304 1305 r = DeleteFileA(path); 1306 ok(r, "failed to delete file %s (%d)\n", path, GetLastError()); 1307 1308 /* same for W variant */ 1309 if (0) 1310 { 1311 /* specified instance handle, crashes on XP, 2k3 */ 1312 hicon = ExtractIconW(GetModuleHandleA("shell32.dll"), NULL, 0); 1313 ok(hicon == NULL, "Got icon %p\n", hicon); 1314 } 1315 hicon2 = ExtractIconW(GetModuleHandleA("shell32.dll"), shell32W, -1); 1316 ok(hicon2 != NULL, "Got icon %p\n", hicon2); 1317 1318 /* existing index */ 1319 hicon = ExtractIconW(NULL, shell32W, 0); 1320 ok(hicon != NULL && HandleToLong(hicon) != -1, "Got icon %p\n", hicon); 1321 GetIconInfo(hicon, &info); 1322 GetObjectW(info.hbmColor, sizeof(bm), &bm); 1323 ok(bm.bmWidth == GetSystemMetrics(SM_CXICON), "got %d\n", bm.bmWidth); 1324 ok(bm.bmHeight == GetSystemMetrics(SM_CYICON), "got %d\n", bm.bmHeight); 1325 DestroyIcon(hicon); 1326 1327 /* returns number of resources */ 1328 hicon = ExtractIconW(NULL, shell32W, -1); 1329 ok(HandleToLong(hicon) > 1 && hicon == hicon2, "Got icon %p\n", hicon); 1330 1331 /* invalid index, valid dll name */ 1332 hicon = ExtractIconW(NULL, shell32W, 3000); 1333 ok(hicon == NULL, "Got icon %p\n", hicon); 1334 1335 /* Create a temporary non-executable file */ 1336 GetTempPathW(ARRAY_SIZE(pathW), pathW); 1337 lstrcatW(pathW, nameW); 1338 file = CreateFileW(pathW, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 1339 ok(file != INVALID_HANDLE_VALUE, "Failed to create a test file\n"); 1340 CloseHandle(file); 1341 1342 hicon = ExtractIconW(NULL, pathW, 0); 1343 todo_wine 1344 ok(hicon == NULL, "Got icon %p\n", hicon); 1345 1346 hicon = ExtractIconW(NULL, pathW, -1); 1347 ok(hicon == NULL, "Got icon %p\n", hicon); 1348 1349 hicon = ExtractIconW(NULL, pathW, 1); 1350 todo_wine 1351 ok(hicon == NULL, "Got icon %p\n", hicon); 1352 1353 r = DeleteFileW(pathW); 1354 ok(r, "failed to delete file %s (%d)\n", path, GetLastError()); 1355 } 1356 1357 static void test_ExtractAssociatedIcon(void) 1358 { 1359 char pathA[MAX_PATH]; 1360 HICON hicon; 1361 WORD index; 1362 1363 /* empty path */ 1364 index = 0; 1365 *pathA = 0; 1366 hicon = ExtractAssociatedIconA(NULL, pathA, &index); 1367 todo_wine { 1368 ok(hicon != NULL, "Got icon %p\n", hicon); 1369 ok(!*pathA, "Unexpected path %s\n", pathA); 1370 ok(index == 0, "Unexpected index %u\n", index); 1371 } 1372 DestroyIcon(hicon); 1373 1374 /* by index */ 1375 index = 0; 1376 strcpy(pathA, "shell32.dll"); 1377 hicon = ExtractAssociatedIconA(NULL, pathA, &index); 1378 ok(hicon != NULL, "Got icon %p\n", hicon); 1379 ok(!strcmp(pathA, "shell32.dll"), "Unexpected path %s\n", pathA); 1380 ok(index == 0, "Unexpected index %u\n", index); 1381 DestroyIcon(hicon); 1382 1383 /* valid dll name, invalid index */ 1384 index = 5000; 1385 strcpy(pathA, "user32.dll"); 1386 hicon = ExtractAssociatedIconA(NULL, pathA, &index); 1387 CharLowerBuffA(pathA, strlen(pathA)); 1388 todo_wine { 1389 ok(hicon != NULL, "Got icon %p\n", hicon); 1390 ok(!!strstr(pathA, "shell32.dll"), "Unexpected path %s\n", pathA); 1391 } 1392 ok(index != 5000, "Unexpected index %u\n", index); 1393 DestroyIcon(hicon); 1394 1395 /* associated icon */ 1396 index = 0xcaca; 1397 strcpy(pathA, "dummy.exe"); 1398 hicon = ExtractAssociatedIconA(NULL, pathA, &index); 1399 CharLowerBuffA(pathA, strlen(pathA)); 1400 todo_wine { 1401 ok(hicon != NULL, "Got icon %p\n", hicon); 1402 ok(!!strstr(pathA, "shell32.dll"), "Unexpected path %s\n", pathA); 1403 } 1404 ok(index != 0xcaca, "Unexpected index %u\n", index); 1405 DestroyIcon(hicon); 1406 } 1407 1408 static int get_shell_icon_size(void) 1409 { 1410 char buf[10]; 1411 DWORD value = 32, size = sizeof(buf), type; 1412 HKEY key; 1413 1414 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Control Panel\\Desktop\\WindowMetrics", &key )) 1415 { 1416 if (!RegQueryValueExA( key, "Shell Icon Size", NULL, &type, (BYTE *)buf, &size ) && type == REG_SZ) 1417 value = atoi( buf ); 1418 RegCloseKey( key ); 1419 } 1420 return value; 1421 } 1422 1423 static void test_SHGetImageList(void) 1424 { 1425 HRESULT hr; 1426 IImageList *list, *list2; 1427 BOOL ret; 1428 HIMAGELIST lg, sm; 1429 ULONG start_refs, refs; 1430 int i, width, height, expect; 1431 BOOL dpi_aware = pIsProcessDPIAware && pIsProcessDPIAware(); 1432 1433 hr = SHGetImageList( SHIL_LARGE, &IID_IImageList, (void **)&list ); 1434 ok( hr == S_OK, "got %08x\n", hr ); 1435 start_refs = IImageList_AddRef( list ); 1436 IImageList_Release( list ); 1437 1438 hr = SHGetImageList( SHIL_LARGE, &IID_IImageList, (void **)&list2 ); 1439 ok( hr == S_OK, "got %08x\n", hr ); 1440 ok( list == list2, "lists differ\n" ); 1441 refs = IImageList_AddRef( list ); 1442 IImageList_Release( list ); 1443 ok( refs == start_refs + 1, "got %d, start_refs %d\n", refs, start_refs ); 1444 IImageList_Release( list2 ); 1445 1446 hr = SHGetImageList( SHIL_SMALL, &IID_IImageList, (void **)&list2 ); 1447 ok( hr == S_OK, "got %08x\n", hr ); 1448 1449 ret = Shell_GetImageLists( &lg, &sm ); 1450 ok( ret, "got %d\n", ret ); 1451 ok( lg == (HIMAGELIST)list, "mismatch\n" ); 1452 ok( sm == (HIMAGELIST)list2, "mismatch\n" ); 1453 1454 /* Shell_GetImageLists doesn't take a reference */ 1455 refs = IImageList_AddRef( list ); 1456 IImageList_Release( list ); 1457 ok( refs == start_refs, "got %d, start_refs %d\n", refs, start_refs ); 1458 1459 IImageList_Release( list2 ); 1460 IImageList_Release( list ); 1461 1462 /* Test the icon sizes */ 1463 for (i = 0; i <= SHIL_LAST; i++) 1464 { 1465 hr = SHGetImageList( i, &IID_IImageList, (void **)&list ); 1466 ok( hr == S_OK || broken( i == SHIL_JUMBO && hr == E_INVALIDARG ), /* XP and 2003 */ 1467 "%d: got %08x\n", i, hr ); 1468 if (FAILED(hr)) continue; 1469 IImageList_GetIconSize( list, &width, &height ); 1470 switch (i) 1471 { 1472 case SHIL_LARGE: 1473 if (dpi_aware) expect = GetSystemMetrics( SM_CXICON ); 1474 else expect = get_shell_icon_size(); 1475 break; 1476 case SHIL_SMALL: 1477 if (dpi_aware) expect = GetSystemMetrics( SM_CXICON ) / 2; 1478 else expect = GetSystemMetrics( SM_CXSMICON ); 1479 break; 1480 case SHIL_EXTRALARGE: 1481 expect = (GetSystemMetrics( SM_CXICON ) * 3) / 2; 1482 break; 1483 case SHIL_SYSSMALL: 1484 expect = GetSystemMetrics( SM_CXSMICON ); 1485 break; 1486 case SHIL_JUMBO: 1487 expect = 256; 1488 break; 1489 } 1490 todo_wine_if(i == SHIL_SYSSMALL && dpi_aware && expect != GetSystemMetrics( SM_CXICON ) / 2) 1491 { 1492 ok( width == expect, "%d: got %d expect %d\n", i, width, expect ); 1493 ok( height == expect, "%d: got %d expect %d\n", i, height, expect ); 1494 } 1495 IImageList_Release( list ); 1496 } 1497 } 1498 1499 START_TEST(shelllink) 1500 { 1501 HRESULT r; 1502 HMODULE hmod = GetModuleHandleA("shell32.dll"); 1503 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); 1504 HMODULE huser32 = GetModuleHandleA("user32.dll"); 1505 1506 pILFree = (void *)GetProcAddress(hmod, (LPSTR)155); 1507 pILIsEqual = (void *)GetProcAddress(hmod, (LPSTR)21); 1508 pSHILCreateFromPath = (void *)GetProcAddress(hmod, (LPSTR)28); 1509 pSHGetFolderLocation = (void *)GetProcAddress(hmod, "SHGetFolderLocation"); 1510 pSHDefExtractIconA = (void *)GetProcAddress(hmod, "SHDefExtractIconA"); 1511 pSHGetStockIconInfo = (void *)GetProcAddress(hmod, "SHGetStockIconInfo"); 1512 pGetLongPathNameA = (void *)GetProcAddress(hkernel32, "GetLongPathNameA"); 1513 pGetShortPathNameA = (void *)GetProcAddress(hkernel32, "GetShortPathNameA"); 1514 pSHExtractIconsW = (void *)GetProcAddress(hmod, "SHExtractIconsW"); 1515 pIsProcessDPIAware = (void *)GetProcAddress(huser32, "IsProcessDPIAware"); 1516 1517 r = CoInitialize(NULL); 1518 ok(r == S_OK, "CoInitialize failed (0x%08x)\n", r); 1519 if (r != S_OK) 1520 return; 1521 1522 test_get_set(); 1523 test_load_save(); 1524 test_datalink(); 1525 test_shdefextracticon(); 1526 test_GetIconLocation(); 1527 test_SHGetStockIconInfo(); 1528 test_SHExtractIcons(); 1529 test_propertystore(); 1530 test_ExtractIcon(); 1531 test_ExtractAssociatedIcon(); 1532 test_SHGetImageList(); 1533 1534 CoUninitialize(); 1535 } 1536