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