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