1 /* 2 * IQueryAssociations helper functions 3 * 4 * Copyright 2002 Jon Griffiths 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 #ifdef __REACTOS__ 21 #undef _WIN32_WINNT 22 #define _WIN32_WINNT _WIN32_WINNT_VISTA /* for RegGetValueW */ 23 #endif 24 #include <stdarg.h> 25 #include <assert.h> 26 27 #include "windef.h" 28 #include "winbase.h" 29 #include "winnls.h" 30 #include "winreg.h" 31 #include "objbase.h" 32 #include "shlguid.h" 33 #include "shlobj.h" 34 #include "shlwapi.h" 35 #include "wine/unicode.h" 36 #include "wine/debug.h" 37 38 WINE_DEFAULT_DEBUG_CHANNEL(shell); 39 40 /* Default IQueryAssociations::Init() flags */ 41 #define SHLWAPI_DEF_ASSOCF (ASSOCF_INIT_BYEXENAME|ASSOCF_INIT_DEFAULTTOSTAR| \ 42 ASSOCF_INIT_DEFAULTTOFOLDER) 43 44 /************************************************************************* 45 * SHLWAPI_ParamAToW 46 * 47 * Internal helper function: Convert ASCII parameter to Unicode. 48 */ 49 static BOOL SHLWAPI_ParamAToW(LPCSTR lpszParam, LPWSTR lpszBuff, DWORD dwLen, 50 LPWSTR* lpszOut) 51 { 52 if (lpszParam) 53 { 54 DWORD dwStrLen = MultiByteToWideChar(CP_ACP, 0, lpszParam, -1, NULL, 0); 55 56 if (dwStrLen < dwLen) 57 { 58 *lpszOut = lpszBuff; /* Use Buffer, it is big enough */ 59 } 60 else 61 { 62 /* Create a new buffer big enough for the string */ 63 *lpszOut = HeapAlloc(GetProcessHeap(), 0, 64 dwStrLen * sizeof(WCHAR)); 65 if (!*lpszOut) 66 return FALSE; 67 } 68 MultiByteToWideChar(CP_ACP, 0, lpszParam, -1, *lpszOut, dwStrLen); 69 } 70 else 71 *lpszOut = NULL; 72 return TRUE; 73 } 74 75 /************************************************************************* 76 * AssocCreate [SHLWAPI.@] 77 * 78 * Create a new IQueryAssociations object. 79 * 80 * PARAMS 81 * clsid [I] CLSID of object 82 * refiid [I] REFIID of interface 83 * lpInterface [O] Destination for the created IQueryAssociations object 84 * 85 * RETURNS 86 * Success: S_OK. lpInterface contains the new object. 87 * Failure: An HRESULT error code indicating the error. 88 * 89 * NOTES 90 * clsid must be equal to CLSID_QueryAssociations and 91 * refiid must be equal to IID_IQueryAssociations, IID_IUnknown or this function will fail 92 */ 93 HRESULT WINAPI AssocCreate(CLSID clsid, REFIID refiid, void **lpInterface) 94 { 95 TRACE("(%s,%s,%p)\n", debugstr_guid(&clsid), debugstr_guid(refiid), 96 lpInterface); 97 98 if (!lpInterface) 99 return E_INVALIDARG; 100 101 *(DWORD*)lpInterface = 0; 102 103 if (!IsEqualGUID(&clsid, &CLSID_QueryAssociations)) 104 return CLASS_E_CLASSNOTAVAILABLE; 105 106 return SHCoCreateInstance( NULL, &clsid, NULL, refiid, lpInterface ); 107 } 108 109 110 struct AssocPerceivedInfo 111 { 112 PCWSTR Type; 113 PERCEIVED Perceived; 114 INT FlagHardcoded; 115 INT FlagSoftcoded; 116 PCWSTR Extensions; 117 }; 118 119 static const WCHAR unspecified_exts[] = { 120 '.','l','n','k',0, 121 '.','s','e','a','r','c','h','-','m','s',0, 122 0 123 }; 124 125 static const WCHAR image_exts[] = { 126 '.','b','m','p',0, 127 '.','d','i','b',0, 128 '.','e','m','f',0, 129 '.','g','i','f',0, 130 '.','i','c','o',0, 131 '.','j','f','i','f',0, 132 '.','j','p','e',0, 133 '.','j','p','e','g',0, 134 '.','j','p','g',0, 135 '.','p','n','g',0, 136 '.','r','l','e',0, 137 '.','t','i','f',0, 138 '.','t','i','f','f',0, 139 '.','w','m','f',0, 140 0 141 }; 142 143 static const WCHAR audio_exts[] = { 144 '.','a','i','f',0, 145 '.','a','i','f','c',0, 146 '.','a','i','f','f',0, 147 '.','a','u',0, 148 '.','m','3','u',0, 149 '.','m','i','d',0, 150 '.','m','i','d','i',0, 151 #if _WIN32_WINNT > 0x602 152 '.','m','p','2',0, 153 #endif 154 '.','m','p','3',0, 155 '.','r','m','i',0, 156 '.','s','n','d',0, 157 '.','w','a','v',0, 158 '.','w','a','x',0, 159 '.','w','m','a',0, 160 0 161 }; 162 163 static const WCHAR video_exts[] = { 164 '.','a','s','f',0, 165 '.','a','s','x',0, 166 '.','a','v','i',0, 167 '.','d','v','r','-','m','s',0, 168 '.','I','V','F',0, 169 '.','m','1','v',0, 170 #if _WIN32_WINNT <= 0x602 171 '.','m','p','2',0, 172 #endif 173 '.','m','p','2','v',0, 174 '.','m','p','a',0, 175 '.','m','p','e',0, 176 '.','m','p','e','g',0, 177 '.','m','p','g',0, 178 '.','m','p','v','2',0, 179 '.','w','m',0, 180 '.','w','m','v',0, 181 '.','w','m','x',0, 182 '.','w','v','x',0, 183 0 184 }; 185 186 static const WCHAR compressed_exts[] = { 187 '.','z','i','p',0, 188 0 189 }; 190 191 static const WCHAR document_exts[] = { 192 #if _WIN32_WINNT >= 0x600 193 '.','h','t','m',0, 194 '.','h','t','m','l',0, 195 #endif 196 '.','m','h','t',0, 197 0 198 }; 199 200 static const WCHAR system_exts[] = { 201 '.','c','p','l',0, 202 0 203 }; 204 205 static const WCHAR application_exts[] = { 206 '.','b','a','s',0, 207 '.','b','a','t',0, 208 '.','c','m','d',0, 209 '.','c','o','m',0, 210 '.','e','x','e',0, 211 '.','h','t','a',0, 212 '.','m','s','i',0, 213 '.','p','i','f',0, 214 '.','r','e','g',0, 215 '.','s','c','r',0, 216 '.','v','b',0, 217 0 218 }; 219 220 const WCHAR type_text[] = {'t','e','x','t',0}; 221 const WCHAR type_image[] = {'i','m','a','g','e',0}; 222 const WCHAR type_audio[] = {'a','u','d','i','o',0}; 223 const WCHAR type_video[] = {'v','i','d','e','o',0}; 224 const WCHAR type_compressed[] = {'c','o','m','p','r','e','s','s','e','d',0}; 225 const WCHAR type_document[] = {'d','o','c','u','m','e','n','t',0}; 226 const WCHAR type_system[] = {'s','y','s','t','e','m',0}; 227 const WCHAR type_application[] = {'a','p','p','l','i','c','a','t','i','o','n',0}; 228 229 #define HARDCODED_NATIVE_WMSDK (PERCEIVEDFLAG_HARDCODED | PERCEIVEDFLAG_NATIVESUPPORT | PERCEIVEDFLAG_WMSDK) 230 #define HARDCODED_NATIVE_GDIPLUS (PERCEIVEDFLAG_HARDCODED | PERCEIVEDFLAG_NATIVESUPPORT | PERCEIVEDFLAG_GDIPLUS) 231 #define HARDCODED_NATIVE_ZIPFLDR (PERCEIVEDFLAG_HARDCODED | PERCEIVEDFLAG_NATIVESUPPORT | PERCEIVEDFLAG_ZIPFOLDER) 232 #define SOFTCODED_NATIVESUPPORT (PERCEIVEDFLAG_SOFTCODED | PERCEIVEDFLAG_NATIVESUPPORT) 233 234 static const struct AssocPerceivedInfo known_types[] = { 235 { NULL, PERCEIVED_TYPE_UNSPECIFIED, PERCEIVEDFLAG_HARDCODED, PERCEIVEDFLAG_SOFTCODED, unspecified_exts }, 236 { type_text, PERCEIVED_TYPE_TEXT, PERCEIVEDFLAG_HARDCODED, SOFTCODED_NATIVESUPPORT, NULL }, 237 { type_image, PERCEIVED_TYPE_IMAGE, HARDCODED_NATIVE_GDIPLUS, PERCEIVEDFLAG_SOFTCODED, image_exts }, 238 { type_audio, PERCEIVED_TYPE_AUDIO, HARDCODED_NATIVE_WMSDK, PERCEIVEDFLAG_SOFTCODED, audio_exts }, 239 { type_video, PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, PERCEIVEDFLAG_SOFTCODED, video_exts }, 240 { type_compressed, PERCEIVED_TYPE_COMPRESSED, HARDCODED_NATIVE_ZIPFLDR, PERCEIVEDFLAG_SOFTCODED, compressed_exts }, 241 { type_document, PERCEIVED_TYPE_DOCUMENT, PERCEIVEDFLAG_HARDCODED, PERCEIVEDFLAG_SOFTCODED, document_exts }, 242 { type_system, PERCEIVED_TYPE_SYSTEM, PERCEIVEDFLAG_HARDCODED, PERCEIVEDFLAG_SOFTCODED, system_exts }, 243 { type_application, PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED, PERCEIVEDFLAG_SOFTCODED, application_exts }, 244 }; 245 246 static const struct AssocPerceivedInfo* AssocFindByBuiltinExtension(LPCWSTR pszExt) 247 { 248 UINT n; 249 for (n = 0; n < sizeof(known_types) / sizeof(known_types[0]); ++n) 250 { 251 PCWSTR Ext = known_types[n].Extensions; 252 while (Ext && *Ext) 253 { 254 if (!StrCmpIW(Ext, pszExt)) 255 return &known_types[n]; 256 Ext += (strlenW(Ext) + 1); 257 } 258 } 259 return NULL; 260 } 261 262 static const struct AssocPerceivedInfo* AssocFindByType(LPCWSTR pszType) 263 { 264 UINT n; 265 for (n = 0; n < sizeof(known_types) / sizeof(known_types[0]); ++n) 266 { 267 if (known_types[n].Type) 268 { 269 if (!StrCmpIW(known_types[n].Type, pszType)) 270 return &known_types[n]; 271 } 272 } 273 return NULL; 274 } 275 276 277 /************************************************************************* 278 * AssocGetPerceivedType [SHLWAPI.@] 279 * 280 * Detect the type of a file by inspecting its extension 281 * 282 * PARAMS 283 * lpszExt [I] File extension to evaluate. 284 * lpType [O] Pointer to perceived type 285 * lpFlag [O] Pointer to perceived type flag 286 * lppszType [O] Address to pointer for perceived type text 287 * 288 * RETURNS 289 * Success: S_OK. lpType and lpFlag contain the perceived type and 290 * its information. If lppszType is not NULL, it will point 291 * to a string with perceived type text. 292 * Failure: An HRESULT error code indicating the error. 293 * 294 * NOTES 295 * lppszType is optional and it can be NULL. 296 * if lpType or lpFlag are NULL, the function will crash. 297 * if lpszExt is NULL, an error is returned. 298 */ 299 HRESULT WINAPI AssocGetPerceivedType(LPCWSTR lpszExt, PERCEIVED *lpType, 300 INT *lpFlag, LPWSTR *lppszType) 301 { 302 static const WCHAR PerceivedTypeKey[] = {'P','e','r','c','e','i','v','e','d','T','y','p','e',0}; 303 static const WCHAR SystemFileAssociationsKey[] = {'S','y','s','t','e','m','F','i','l','e', 304 'A','s','s','o','c','i','a','t','i','o','n','s','\\','%','s',0}; 305 const struct AssocPerceivedInfo *Info; 306 307 TRACE("(%s,%p,%p,%p)\n", debugstr_w(lpszExt), lpType, lpFlag, lppszType); 308 309 Info = AssocFindByBuiltinExtension(lpszExt); 310 if (Info) 311 { 312 *lpType = Info->Perceived; 313 *lpFlag = Info->FlagHardcoded; 314 } 315 else 316 { 317 WCHAR Buffer[100] = { 0 }; 318 DWORD Size = sizeof(Buffer); 319 if (RegGetValueW(HKEY_CLASSES_ROOT, lpszExt, PerceivedTypeKey, 320 RRF_RT_REG_SZ, NULL, Buffer, &Size) == ERROR_SUCCESS) 321 { 322 Info = AssocFindByType(Buffer); 323 } 324 if (!Info) 325 { 326 WCHAR KeyName[MAX_PATH] = { 0 }; 327 snprintfW(KeyName, MAX_PATH, SystemFileAssociationsKey, lpszExt); 328 Size = sizeof(Buffer); 329 if (RegGetValueW(HKEY_CLASSES_ROOT, KeyName, PerceivedTypeKey, 330 RRF_RT_REG_SZ, NULL, Buffer, &Size) == ERROR_SUCCESS) 331 { 332 Info = AssocFindByType(Buffer); 333 } 334 } 335 if (Info) 336 { 337 *lpType = Info->Perceived; 338 *lpFlag = Info->FlagSoftcoded; 339 } 340 } 341 342 if (Info) 343 { 344 if (lppszType && Info->Type) 345 { 346 return SHStrDupW(Info->Type, lppszType); 347 } 348 return Info->Type ? S_OK : E_FAIL; 349 } 350 else 351 { 352 *lpType = PERCEIVED_TYPE_UNSPECIFIED; 353 *lpFlag = 0; 354 } 355 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 356 } 357 358 /************************************************************************* 359 * AssocQueryKeyW [SHLWAPI.@] 360 * 361 * See AssocQueryKeyA. 362 */ 363 HRESULT WINAPI AssocQueryKeyW(ASSOCF cfFlags, ASSOCKEY assockey, LPCWSTR pszAssoc, 364 LPCWSTR pszExtra, HKEY *phkeyOut) 365 { 366 HRESULT hRet; 367 IQueryAssociations* lpAssoc; 368 369 TRACE("(0x%x,%d,%s,%s,%p)\n", cfFlags, assockey, debugstr_w(pszAssoc), 370 debugstr_w(pszExtra), phkeyOut); 371 372 hRet = AssocCreate( CLSID_QueryAssociations, &IID_IQueryAssociations, (void **)&lpAssoc ); 373 if (FAILED(hRet)) return hRet; 374 375 cfFlags &= SHLWAPI_DEF_ASSOCF; 376 hRet = IQueryAssociations_Init(lpAssoc, cfFlags, pszAssoc, NULL, NULL); 377 378 if (SUCCEEDED(hRet)) 379 hRet = IQueryAssociations_GetKey(lpAssoc, cfFlags, assockey, pszExtra, phkeyOut); 380 381 IQueryAssociations_Release(lpAssoc); 382 return hRet; 383 } 384 385 /************************************************************************* 386 * AssocQueryKeyA [SHLWAPI.@] 387 * 388 * Get a file association key from the registry. 389 * 390 * PARAMS 391 * cfFlags [I] ASSOCF_ flags from "shlwapi.h" 392 * assockey [I] Type of key to get 393 * pszAssoc [I] Key name to search below 394 * pszExtra [I] Extra information about the key location 395 * phkeyOut [O] Destination for the association key 396 * 397 * RETURNS 398 * Success: S_OK. phkeyOut contains the key. 399 * Failure: An HRESULT error code indicating the error. 400 */ 401 HRESULT WINAPI AssocQueryKeyA(ASSOCF cfFlags, ASSOCKEY assockey, LPCSTR pszAssoc, 402 LPCSTR pszExtra, HKEY *phkeyOut) 403 { 404 WCHAR szAssocW[MAX_PATH], *lpszAssocW = NULL; 405 WCHAR szExtraW[MAX_PATH], *lpszExtraW = NULL; 406 HRESULT hRet = E_OUTOFMEMORY; 407 408 TRACE("(0x%x,%d,%s,%s,%p)\n", cfFlags, assockey, debugstr_a(pszAssoc), 409 debugstr_a(pszExtra), phkeyOut); 410 411 if (SHLWAPI_ParamAToW(pszAssoc, szAssocW, MAX_PATH, &lpszAssocW) && 412 SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW)) 413 { 414 hRet = AssocQueryKeyW(cfFlags, assockey, lpszAssocW, lpszExtraW, phkeyOut); 415 } 416 417 if (lpszAssocW != szAssocW) 418 HeapFree(GetProcessHeap(), 0, lpszAssocW); 419 420 if (lpszExtraW != szExtraW) 421 HeapFree(GetProcessHeap(), 0, lpszExtraW); 422 423 return hRet; 424 } 425 426 /************************************************************************* 427 * AssocQueryStringW [SHLWAPI.@] 428 * 429 * See AssocQueryStringA. 430 */ 431 HRESULT WINAPI AssocQueryStringW(ASSOCF cfFlags, ASSOCSTR str, LPCWSTR pszAssoc, 432 LPCWSTR pszExtra, LPWSTR pszOut, DWORD *pcchOut) 433 { 434 HRESULT hRet; 435 IQueryAssociations* lpAssoc; 436 437 TRACE("(0x%x,%d,%s,%s,%p,%p)\n", cfFlags, str, debugstr_w(pszAssoc), 438 debugstr_w(pszExtra), pszOut, pcchOut); 439 440 if (!pcchOut) 441 return E_UNEXPECTED; 442 443 hRet = AssocCreate( CLSID_QueryAssociations, &IID_IQueryAssociations, (void **)&lpAssoc ); 444 if (FAILED(hRet)) return hRet; 445 446 hRet = IQueryAssociations_Init(lpAssoc, cfFlags & SHLWAPI_DEF_ASSOCF, 447 pszAssoc, NULL, NULL); 448 449 if (SUCCEEDED(hRet)) 450 hRet = IQueryAssociations_GetString(lpAssoc, cfFlags, str, pszExtra, 451 pszOut, pcchOut); 452 453 IQueryAssociations_Release(lpAssoc); 454 return hRet; 455 } 456 457 /************************************************************************* 458 * AssocQueryStringA [SHLWAPI.@] 459 * 460 * Get a file association string from the registry. 461 * 462 * PARAMS 463 * cfFlags [I] ASSOCF_ flags from "shlwapi.h" 464 * str [I] Type of string to get (ASSOCSTR enum from "shlwapi.h") 465 * pszAssoc [I] Key name to search below 466 * pszExtra [I] Extra information about the string location 467 * pszOut [O] Destination for the association string 468 * pcchOut [O] Length of pszOut 469 * 470 * RETURNS 471 * Success: S_OK. pszOut contains the string, pcchOut contains its length. 472 * Failure: An HRESULT error code indicating the error. 473 */ 474 HRESULT WINAPI AssocQueryStringA(ASSOCF cfFlags, ASSOCSTR str, LPCSTR pszAssoc, 475 LPCSTR pszExtra, LPSTR pszOut, DWORD *pcchOut) 476 { 477 WCHAR szAssocW[MAX_PATH], *lpszAssocW = NULL; 478 WCHAR szExtraW[MAX_PATH], *lpszExtraW = NULL; 479 HRESULT hRet = E_OUTOFMEMORY; 480 481 TRACE("(0x%x,0x%d,%s,%s,%p,%p)\n", cfFlags, str, debugstr_a(pszAssoc), 482 debugstr_a(pszExtra), pszOut, pcchOut); 483 484 if (!pcchOut) 485 hRet = E_UNEXPECTED; 486 else if (SHLWAPI_ParamAToW(pszAssoc, szAssocW, MAX_PATH, &lpszAssocW) && 487 SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW)) 488 { 489 WCHAR szReturnW[MAX_PATH], *lpszReturnW = szReturnW; 490 DWORD dwLenOut = *pcchOut; 491 492 if (dwLenOut >= MAX_PATH) 493 lpszReturnW = HeapAlloc(GetProcessHeap(), 0, 494 (dwLenOut + 1) * sizeof(WCHAR)); 495 else 496 dwLenOut = sizeof(szReturnW) / sizeof(szReturnW[0]); 497 498 if (!lpszReturnW) 499 hRet = E_OUTOFMEMORY; 500 else 501 { 502 hRet = AssocQueryStringW(cfFlags, str, lpszAssocW, lpszExtraW, 503 lpszReturnW, &dwLenOut); 504 505 if (SUCCEEDED(hRet)) 506 dwLenOut = WideCharToMultiByte(CP_ACP, 0, lpszReturnW, -1, 507 pszOut, *pcchOut, NULL, NULL); 508 509 *pcchOut = dwLenOut; 510 if (lpszReturnW != szReturnW) 511 HeapFree(GetProcessHeap(), 0, lpszReturnW); 512 } 513 } 514 515 if (lpszAssocW != szAssocW) 516 HeapFree(GetProcessHeap(), 0, lpszAssocW); 517 if (lpszExtraW != szExtraW) 518 HeapFree(GetProcessHeap(), 0, lpszExtraW); 519 return hRet; 520 } 521 522 /************************************************************************* 523 * AssocQueryStringByKeyW [SHLWAPI.@] 524 * 525 * See AssocQueryStringByKeyA. 526 */ 527 HRESULT WINAPI AssocQueryStringByKeyW(ASSOCF cfFlags, ASSOCSTR str, HKEY hkAssoc, 528 LPCWSTR pszExtra, LPWSTR pszOut, 529 DWORD *pcchOut) 530 { 531 HRESULT hRet; 532 IQueryAssociations* lpAssoc; 533 534 TRACE("(0x%x,0x%d,%p,%s,%p,%p)\n", cfFlags, str, hkAssoc, 535 debugstr_w(pszExtra), pszOut, pcchOut); 536 537 hRet = AssocCreate( CLSID_QueryAssociations, &IID_IQueryAssociations, (void **)&lpAssoc ); 538 if (FAILED(hRet)) return hRet; 539 540 cfFlags &= SHLWAPI_DEF_ASSOCF; 541 hRet = IQueryAssociations_Init(lpAssoc, cfFlags, 0, hkAssoc, NULL); 542 543 if (SUCCEEDED(hRet)) 544 hRet = IQueryAssociations_GetString(lpAssoc, cfFlags, str, pszExtra, 545 pszOut, pcchOut); 546 547 IQueryAssociations_Release(lpAssoc); 548 return hRet; 549 } 550 551 /************************************************************************* 552 * AssocQueryStringByKeyA [SHLWAPI.@] 553 * 554 * Get a file association string from the registry, given a starting key. 555 * 556 * PARAMS 557 * cfFlags [I] ASSOCF_ flags from "shlwapi.h" 558 * str [I] Type of string to get 559 * hkAssoc [I] Key to search below 560 * pszExtra [I] Extra information about the string location 561 * pszOut [O] Destination for the association string 562 * pcchOut [O] Length of pszOut 563 * 564 * RETURNS 565 * Success: S_OK. pszOut contains the string, pcchOut contains its length. 566 * Failure: An HRESULT error code indicating the error. 567 */ 568 HRESULT WINAPI AssocQueryStringByKeyA(ASSOCF cfFlags, ASSOCSTR str, HKEY hkAssoc, 569 LPCSTR pszExtra, LPSTR pszOut, 570 DWORD *pcchOut) 571 { 572 WCHAR szExtraW[MAX_PATH], *lpszExtraW = szExtraW; 573 WCHAR szReturnW[MAX_PATH], *lpszReturnW = szReturnW; 574 HRESULT hRet = E_OUTOFMEMORY; 575 576 TRACE("(0x%x,0x%d,%p,%s,%p,%p)\n", cfFlags, str, hkAssoc, 577 debugstr_a(pszExtra), pszOut, pcchOut); 578 579 if (!pcchOut) 580 hRet = E_INVALIDARG; 581 else if (SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW)) 582 { 583 DWORD dwLenOut = *pcchOut; 584 if (dwLenOut >= MAX_PATH) 585 lpszReturnW = HeapAlloc(GetProcessHeap(), 0, 586 (dwLenOut + 1) * sizeof(WCHAR)); 587 588 if (lpszReturnW) 589 { 590 hRet = AssocQueryStringByKeyW(cfFlags, str, hkAssoc, lpszExtraW, 591 lpszReturnW, &dwLenOut); 592 593 if (SUCCEEDED(hRet)) 594 WideCharToMultiByte(CP_ACP,0,szReturnW,-1,pszOut,dwLenOut,0,0); 595 *pcchOut = dwLenOut; 596 597 if (lpszReturnW != szReturnW) 598 HeapFree(GetProcessHeap(), 0, lpszReturnW); 599 } 600 } 601 602 if (lpszExtraW != szExtraW) 603 HeapFree(GetProcessHeap(), 0, lpszExtraW); 604 return hRet; 605 } 606 607 608 /************************************************************************** 609 * AssocIsDangerous (SHLWAPI.@) 610 * 611 * Determine if a file association is dangerous (potentially malware). 612 * 613 * PARAMS 614 * lpszAssoc [I] Name of file or file extension to check. 615 * 616 * RETURNS 617 * TRUE, if lpszAssoc may potentially be malware (executable), 618 * FALSE, Otherwise. 619 */ 620 BOOL WINAPI AssocIsDangerous(LPCWSTR lpszAssoc) 621 { 622 FIXME("%s\n", debugstr_w(lpszAssoc)); 623 return FALSE; 624 } 625