2 * IQueryAssociations object and helper functions
4 * Copyright 2002 Jon Griffiths
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(shell);
33 /**************************************************************************
34 * IQueryAssociations {SHLWAPI}
37 * This object provides a layer of abstraction over the system registry in
38 * order to simplify the process of parsing associations between files.
39 * Associations in this context means the registry entries that link (for
40 * example) the extension of a file with its description, list of
41 * applications to open the file with, and actions that can be performed on it
42 * (the shell displays such information in the context menu of explorer
43 * when you right-click on a file).
46 * You can use this object tranparently by calling the helper functions
47 * AssocQueryKeyA(), AssocQueryStringA() and AssocQueryStringByKeyA(). These
48 * create an IQueryAssociations object, perform the requested actions
49 * and then dispose of the object. Alternatively, you can create an instance
50 * of the object using AssocCreate() and call the following methods on it:
55 /* Default IQueryAssociations::Init() flags */
56 #define SHLWAPI_DEF_ASSOCF (ASSOCF_INIT_BYEXENAME|ASSOCF_INIT_DEFAULTTOSTAR| \
57 ASSOCF_INIT_DEFAULTTOFOLDER)
61 ICOM_VFIELD(IQueryAssociations);
63 } IQueryAssociationsImpl;
65 static struct ICOM_VTABLE(IQueryAssociations) IQueryAssociations_vtbl;
67 /**************************************************************************
68 * IQueryAssociations_Constructor [internal]
70 * Construct a new IQueryAssociations object.
72 static IQueryAssociations* IQueryAssociations_Constructor(void)
74 IQueryAssociationsImpl* iface;
76 iface =(IQueryAssociationsImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IQueryAssociationsImpl));
77 iface->lpVtbl = &IQueryAssociations_vtbl;
80 TRACE("Returning IQueryAssociations* %p\n", iface);
81 return (IQueryAssociations*)iface;
84 /*************************************************************************
87 * Internal helper function: Convert ASCII parameter to Unicode.
89 static BOOL SHLWAPI_ParamAToW(LPCSTR lpszParam, LPWSTR lpszBuff, DWORD dwLen,
94 DWORD dwStrLen = lstrlenA(lpszParam);
98 *lpszOut = lpszBuff; /* Use Buffer, it is big enough */
102 /* Create a new buffer big enough for the string */
103 *lpszOut = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
104 (dwStrLen + 1) * sizeof(WCHAR));
108 MultiByteToWideChar(0, 0, lpszParam, -1, *lpszOut, -1);
115 /*************************************************************************
116 * AssocCreate [SHLWAPI.253]
118 * Create a new IQueryAssociations object.
121 * clsid [I] CLSID of object
122 * refiid [I] REFIID of interface
123 * lpInterface [O] Destination for the created IQueryAssociations object
126 * Success: S_OK. lpInterface contains the new object.
127 * Failure: An HRESULT error code indicating the error.
130 * refiid must be equal to IID_IQueryAssociations, or this function will fail.
132 HRESULT WINAPI AssocCreate(CLSID clsid, REFIID refiid, void **lpInterface)
135 IQueryAssociations* lpAssoc;
137 TRACE("(%s,%s,%p)\n", debugstr_guid(&clsid), debugstr_guid(refiid),
143 *(DWORD*)lpInterface = 0;
145 if (!IsEqualGUID(&clsid, &IID_IQueryAssociations))
148 lpAssoc = IQueryAssociations_Constructor();
151 return E_OUTOFMEMORY;
153 hRet = IQueryAssociations_QueryInterface(lpAssoc, refiid, lpInterface);
154 IQueryAssociations_Release(lpAssoc);
158 /*************************************************************************
159 * AssocQueryKeyW [SHLWAPI.255]
161 * See AssocQueryKeyA.
163 HRESULT WINAPI AssocQueryKeyW(ASSOCF cfFlags, ASSOCKEY assockey, LPCWSTR pszAssoc,
164 LPCWSTR pszExtra, HKEY *phkeyOut)
167 IQueryAssociations* lpAssoc;
169 TRACE("(0x%8lx,0x%8x,%s,%s,%p)\n", cfFlags, assockey, debugstr_w(pszAssoc),
170 debugstr_w(pszExtra), phkeyOut);
172 lpAssoc = IQueryAssociations_Constructor();
175 return E_OUTOFMEMORY;
177 cfFlags &= SHLWAPI_DEF_ASSOCF;
178 hRet = IQueryAssociations_Init(lpAssoc, cfFlags, pszAssoc, NULL, NULL);
181 hRet = IQueryAssociations_GetKey(lpAssoc, cfFlags, assockey, pszExtra, phkeyOut);
183 IQueryAssociations_Release(lpAssoc);
187 /*************************************************************************
188 * AssocQueryKeyA [SHLWAPI.254]
190 * Get a file association key from the registry.
193 * cfFlags [I] ASSOCF_ flags from "shlwapi.h"
194 * assockey [I] Type of key to get
195 * pszAssoc [I] Key name to search below
196 * pszExtra [I] Extra information about the key location
197 * phkeyOut [O] Destination for the association key
200 * Success: S_OK. phkeyOut contains the key.
201 * Failure: An HRESULT error code indicating the error.
203 HRESULT WINAPI AssocQueryKeyA(ASSOCF cfFlags, ASSOCKEY assockey, LPCSTR pszAssoc,
204 LPCSTR pszExtra, HKEY *phkeyOut)
206 WCHAR szAssocW[MAX_PATH], *lpszAssocW = NULL;
207 WCHAR szExtraW[MAX_PATH], *lpszExtraW = NULL;
208 HRESULT hRet = E_OUTOFMEMORY;
210 TRACE("(0x%8lx,0x%8x,%s,%s,%p)\n", cfFlags, assockey, debugstr_a(pszAssoc),
211 debugstr_a(pszExtra), phkeyOut);
213 if (SHLWAPI_ParamAToW(pszAssoc, szAssocW, MAX_PATH, &lpszAssocW) &&
214 SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW))
216 hRet = AssocQueryKeyW(cfFlags, assockey, lpszAssocW, lpszExtraW, phkeyOut);
219 if (lpszAssocW && lpszAssocW != szAssocW)
220 HeapFree(GetProcessHeap(), 0, lpszAssocW);
222 if (lpszExtraW && lpszExtraW != szExtraW)
223 HeapFree(GetProcessHeap(), 0, lpszExtraW);
228 /*************************************************************************
229 * AssocQueryStringW [SHLWAPI.384]
231 * See AssocQueryStringA.
233 HRESULT WINAPI AssocQueryStringW(ASSOCF cfFlags, ASSOCSTR str, LPCWSTR pszAssoc,
234 LPCWSTR pszExtra, LPWSTR pszOut, DWORD *pcchOut)
237 IQueryAssociations* lpAssoc;
239 TRACE("(0x%8lx,0x%8x,%s,%s,%p,%p)\n", cfFlags, str, debugstr_w(pszAssoc),
240 debugstr_w(pszExtra), pszOut, pcchOut);
245 lpAssoc = IQueryAssociations_Constructor();
248 return E_OUTOFMEMORY;
250 hRet = IQueryAssociations_Init(lpAssoc, cfFlags & SHLWAPI_DEF_ASSOCF,
251 pszAssoc, NULL, NULL);
254 hRet = IQueryAssociations_GetString(lpAssoc, cfFlags, str, pszExtra,
257 IQueryAssociations_Release(lpAssoc);
261 /*************************************************************************
262 * AssocQueryStringA [SHLWAPI.381]
264 * Get a file association string from the registry.
267 * cfFlags [I] ASSOCF_ flags from "shlwapi.h"
268 * str [I] Type of string to get (ASSOCSTR enum from "shlwapi.h")
269 * pszAssoc [I] Key name to search below
270 * pszExtra [I] Extra information about the string location
271 * pszOut [O] Destination for the association string
272 * pcchOut [O] Length of pszOut
275 * Success: S_OK. pszOut contains the string, pcchOut contains its length.
276 * Failure: An HRESULT error code indicating the error.
278 HRESULT WINAPI AssocQueryStringA(ASSOCF cfFlags, ASSOCSTR str, LPCSTR pszAssoc,
279 LPCSTR pszExtra, LPSTR pszOut, DWORD *pcchOut)
281 WCHAR szAssocW[MAX_PATH], *lpszAssocW = NULL;
282 WCHAR szExtraW[MAX_PATH], *lpszExtraW = NULL;
283 HRESULT hRet = E_OUTOFMEMORY;
285 TRACE("(0x%8lx,0x%8x,%s,%s,%p,%p)\n", cfFlags, str, debugstr_a(pszAssoc),
286 debugstr_a(pszExtra), pszOut, pcchOut);
290 else if (SHLWAPI_ParamAToW(pszAssoc, szAssocW, MAX_PATH, &lpszAssocW) &&
291 SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW))
293 WCHAR szReturnW[MAX_PATH], *lpszReturnW = szReturnW;
294 DWORD dwLenOut = *pcchOut;
296 if (dwLenOut >= MAX_PATH)
297 lpszReturnW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
298 (dwLenOut + 1) * sizeof(WCHAR));
301 hRet = E_OUTOFMEMORY;
304 hRet = AssocQueryStringW(cfFlags, str, lpszAssocW, lpszExtraW,
305 lpszReturnW, &dwLenOut);
308 WideCharToMultiByte(CP_ACP,0,szReturnW,-1,pszOut,dwLenOut,0,0);
311 if (lpszReturnW && lpszReturnW != szReturnW)
312 HeapFree(GetProcessHeap(), 0, lpszReturnW);
316 if (lpszAssocW && lpszAssocW != szAssocW)
317 HeapFree(GetProcessHeap(), 0, lpszAssocW);
318 if (lpszExtraW && lpszExtraW != szExtraW)
319 HeapFree(GetProcessHeap(), 0, lpszExtraW);
323 /*************************************************************************
324 * AssocQueryStringByKeyW [SHLWAPI.383]
326 * See AssocQueryStringByKeyA.
328 HRESULT WINAPI AssocQueryStringByKeyW(ASSOCF cfFlags, ASSOCSTR str, HKEY hkAssoc,
329 LPCWSTR pszExtra, LPWSTR pszOut,
333 IQueryAssociations* lpAssoc;
335 TRACE("(0x%8lx,0x%8x,%p,%s,%p,%p)\n", cfFlags, str, hkAssoc,
336 debugstr_w(pszExtra), pszOut, pcchOut);
338 lpAssoc = IQueryAssociations_Constructor();
341 return E_OUTOFMEMORY;
343 cfFlags &= SHLWAPI_DEF_ASSOCF;
344 hRet = IQueryAssociations_Init(lpAssoc, cfFlags, 0, hkAssoc, NULL);
347 hRet = IQueryAssociations_GetString(lpAssoc, cfFlags, str, pszExtra,
350 IQueryAssociations_Release(lpAssoc);
354 /*************************************************************************
355 * AssocQueryStringByKeyA [SHLWAPI.382]
357 * Get a file association string from the registry, given a starting key.
360 * cfFlags [I] ASSOCF_ flags from "shlwapi.h"
361 * str [I] Type of string to get
362 * hkAssoc [I] Key to search below
363 * pszExtra [I] Extra information about the string location
364 * pszOut [O] Destination for the association string
365 * pcchOut [O] Length of pszOut
368 * Success: S_OK. pszOut contains the string, pcchOut contains its length.
369 * Failure: An HRESULT error code indicating the error.
371 HRESULT WINAPI AssocQueryStringByKeyA(ASSOCF cfFlags, ASSOCSTR str, HKEY hkAssoc,
372 LPCSTR pszExtra, LPSTR pszOut,
375 WCHAR szExtraW[MAX_PATH], *lpszExtraW;
376 WCHAR szReturnW[MAX_PATH], *lpszReturnW = szReturnW;
377 HRESULT hRet = E_OUTOFMEMORY;
379 TRACE("(0x%8lx,0x%8x,%p,%s,%p,%p)\n", cfFlags, str, hkAssoc,
380 debugstr_a(pszExtra), pszOut, pcchOut);
384 else if (SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW))
386 DWORD dwLenOut = *pcchOut;
387 if (dwLenOut >= MAX_PATH)
388 lpszReturnW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
389 (dwLenOut + 1) * sizeof(WCHAR));
393 hRet = AssocQueryStringByKeyW(cfFlags, str, hkAssoc, lpszExtraW,
394 lpszReturnW, &dwLenOut);
397 WideCharToMultiByte(CP_ACP,0,szReturnW,-1,pszOut,dwLenOut,0,0);
400 if (lpszReturnW != szReturnW)
401 HeapFree(GetProcessHeap(), 0, lpszReturnW);
405 if (lpszExtraW && lpszExtraW != szExtraW)
406 HeapFree(GetProcessHeap(), 0, lpszExtraW);
411 /**************************************************************************
412 * AssocIsDangerous (SHLWAPI.@)
414 HRESULT WINAPI AssocIsDangerous( ASSOCSTR str )
416 FIXME("%08x\n", str);
420 /**************************************************************************
421 * IQueryAssociations_QueryInterface {SHLWAPI}
423 * See IUnknown_QueryInterface.
425 static HRESULT WINAPI IQueryAssociations_fnQueryInterface(
426 IQueryAssociations* iface,
430 ICOM_THIS(IQueryAssociationsImpl, iface);
432 TRACE("(%p,%s,%p)\n",This, debugstr_guid(riid), ppvObj);
436 if (IsEqualIID(riid, &IID_IUnknown) ||
437 IsEqualIID(riid, &IID_IQueryAssociations))
439 *ppvObj = (IQueryAssociations*)This;
441 IQueryAssociations_AddRef((IQueryAssociations*)*ppvObj);
442 TRACE("Returning IQueryAssociations (%p)\n", *ppvObj);
445 TRACE("Returning E_NOINTERFACE\n");
446 return E_NOINTERFACE;
449 /**************************************************************************
450 * IQueryAssociations_AddRef {SHLWAPI}
452 * See IUnknown_AddRef.
454 static ULONG WINAPI IQueryAssociations_fnAddRef(IQueryAssociations *iface)
456 ICOM_THIS(IQueryAssociationsImpl,iface);
458 TRACE("(%p)->(ref before=%lu)\n",This, This->ref);
460 return InterlockedIncrement(&This->ref);
463 /**************************************************************************
464 * IQueryAssociations_Release {SHLWAPI}
466 * See IUnknown_Release.
468 static ULONG WINAPI IQueryAssociations_fnRelease(IQueryAssociations *iface)
470 ICOM_THIS(IQueryAssociationsImpl,iface);
473 TRACE("(%p)->(ref before=%lu)\n",This, This->ref);
475 if (!(ulRet = InterlockedDecrement(&This->ref)))
477 TRACE("Destroying IQueryAssociations (%p)\n", This);
478 HeapFree(GetProcessHeap(), 0, This);
483 /**************************************************************************
484 * IQueryAssociations_Init {SHLWAPI}
486 * Initialise an IQueryAssociations object.
489 * iface [I] IQueryAssociations interface to initialise
490 * cfFlags [I] ASSOCF_ flags from "shlwapi.h"
491 * pszAssoc [I] String for the root key name, or NULL if hkProgid is given
492 * hkProgid [I] Handle for the root key, or NULL if pszAssoc is given
493 * hWnd [I] Reserved, must be NULL.
496 * Success: S_OK. iface is initialised with the parameters given.
497 * Failure: An HRESULT error code indicating the error.
499 static HRESULT WINAPI IQueryAssociations_fnInit(
500 IQueryAssociations *iface,
506 ICOM_THIS(IQueryAssociationsImpl, iface);
508 FIXME("(%p,0x%8lx,%s,%p,%p)-stub!\n", This, cfFlags,
509 debugstr_w(pszAssoc), hkProgid, hWnd);
513 /**************************************************************************
514 * IQueryAssociations_GetString {SHLWAPI}
516 * Get a file association string from the registry.
519 * iface [I] IQueryAssociations interface to query
520 * cfFlags [I] ASSOCF_ flags from "shlwapi.h"
521 * str [I] Type of string to get (ASSOCSTR enum from "shlwapi.h")
522 * pszExtra [I] Extra information about the string location
523 * pszOut [O] Destination for the association string
524 * pcchOut [I/O] Length of pszOut
527 * Success: S_OK. pszOut contains the string, pcchOut contains its length.
528 * Failure: An HRESULT error code indicating the error.
530 static HRESULT WINAPI IQueryAssociations_fnGetString(
531 IQueryAssociations *iface,
538 ICOM_THIS(IQueryAssociationsImpl, iface);
540 FIXME("(%p,0x%8lx,0x%8x,%s,%p,%p)-stub!\n", This, cfFlags, str,
541 debugstr_w(pszExtra), pszOut, pcchOut);
545 /**************************************************************************
546 * IQueryAssociations_GetKey {SHLWAPI}
548 * Get a file association key from the registry.
551 * iface [I] IQueryAssociations interface to query
552 * cfFlags [I] ASSOCF_ flags from "shlwapi.h"
553 * assockey [I] Type of key to get (ASSOCKEY enum from "shlwapi.h")
554 * pszExtra [I] Extra information about the key location
555 * phkeyOut [O] Destination for the association key
558 * Success: S_OK. phkeyOut contains a handle to the key.
559 * Failure: An HRESULT error code indicating the error.
561 static HRESULT WINAPI IQueryAssociations_fnGetKey(
562 IQueryAssociations *iface,
568 ICOM_THIS(IQueryAssociationsImpl, iface);
570 FIXME("(%p,0x%8lx,0x%8x,%s,%p)-stub!\n", This, cfFlags, assockey,
571 debugstr_w(pszExtra), phkeyOut);
575 /**************************************************************************
576 * IQueryAssociations_GetData {SHLWAPI}
578 * Get the data for a file association key from the registry.
581 * iface [I] IQueryAssociations interface to query
582 * cfFlags [I] ASSOCF_ flags from "shlwapi.h"
583 * assocdata [I] Type of data to get (ASSOCDATA enum from "shlwapi.h")
584 * pszExtra [I] Extra information about the data location
585 * pvOut [O] Destination for the association key
586 * pcbOut [I/O] Size of pvOut
589 * Success: S_OK. pszOut contains the data, pcbOut contains its length.
590 * Failure: An HRESULT error code indicating the error.
592 static HRESULT WINAPI IQueryAssociations_fnGetData(
593 IQueryAssociations *iface,
600 ICOM_THIS(IQueryAssociationsImpl, iface);
602 FIXME("(%p,0x%8lx,0x%8x,%s,%p,%p)-stub!\n", This, cfFlags, assocdata,
603 debugstr_w(pszExtra), pvOut, pcbOut);
607 /**************************************************************************
608 * IQueryAssociations_GetEnum {SHLWAPI}
610 * Not yet implemented in native Win32.
613 * iface [I] IQueryAssociations interface to query
614 * cfFlags [I] ASSOCF_ flags from "shlwapi.h"
615 * assocenum [I] Type of enum to get (ASSOCENUM enum from "shlwapi.h")
616 * pszExtra [I] Extra information about the enum location
617 * riid [I] REFIID to look for
618 * ppvOut [O] Destination for the interface.
622 * Failure: An HRESULT error code indicating the error.
625 * Presumably this function returns an enumerator object.
627 static HRESULT WINAPI IQueryAssociations_fnGetEnum(
628 IQueryAssociations *iface,
635 ICOM_THIS(IQueryAssociationsImpl, iface);
637 FIXME("(%p,0x%8lx,0x%8x,%s,%s,%p)-stub!\n", This, cfFlags, assocenum,
638 debugstr_w(pszExtra), debugstr_guid(riid), ppvOut);
642 static struct ICOM_VTABLE(IQueryAssociations) IQueryAssociations_vtbl =
644 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
645 IQueryAssociations_fnQueryInterface,
646 IQueryAssociations_fnAddRef,
647 IQueryAssociations_fnRelease,
648 IQueryAssociations_fnInit,
649 IQueryAssociations_fnGetString,
650 IQueryAssociations_fnGetKey,
651 IQueryAssociations_fnGetData,
652 IQueryAssociations_fnGetEnum