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