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 */
SHLWAPI_ParamAToW(LPCSTR lpszParam,LPWSTR lpszBuff,DWORD dwLen,LPWSTR * lpszOut)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 */
AssocCreate(CLSID clsid,REFIID refiid,void ** lpInterface)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
AssocFindByBuiltinExtension(LPCWSTR pszExt)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
AssocFindByType(LPCWSTR pszType)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 */
AssocGetPerceivedType(LPCWSTR lpszExt,PERCEIVED * lpType,INT * lpFlag,LPWSTR * lppszType)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 */
AssocQueryKeyW(ASSOCF cfFlags,ASSOCKEY assockey,LPCWSTR pszAssoc,LPCWSTR pszExtra,HKEY * phkeyOut)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 */
AssocQueryKeyA(ASSOCF cfFlags,ASSOCKEY assockey,LPCSTR pszAssoc,LPCSTR pszExtra,HKEY * phkeyOut)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 */
AssocQueryStringW(ASSOCF cfFlags,ASSOCSTR str,LPCWSTR pszAssoc,LPCWSTR pszExtra,LPWSTR pszOut,DWORD * pcchOut)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 */
AssocQueryStringA(ASSOCF cfFlags,ASSOCSTR str,LPCSTR pszAssoc,LPCSTR pszExtra,LPSTR pszOut,DWORD * pcchOut)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 */
AssocQueryStringByKeyW(ASSOCF cfFlags,ASSOCSTR str,HKEY hkAssoc,LPCWSTR pszExtra,LPWSTR pszOut,DWORD * pcchOut)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 */
AssocQueryStringByKeyA(ASSOCF cfFlags,ASSOCSTR str,HKEY hkAssoc,LPCSTR pszExtra,LPSTR pszOut,DWORD * pcchOut)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 */
AssocIsDangerous(LPCWSTR lpszAssoc)625 BOOL WINAPI AssocIsDangerous(LPCWSTR lpszAssoc)
626 {
627 FIXME("%s\n", debugstr_w(lpszAssoc));
628 return FALSE;
629 }
630