Fix the case of product and company names.
[wine] / dlls / shlwapi / assoc.c
1 /*
2  * IQueryAssociations object and 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include <stdarg.h>
21
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winnls.h"
25 #include "winreg.h"
26 #include "objbase.h"
27 #include "shlguid.h"
28 #include "shlwapi.h"
29 #include "wine/debug.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(shell);
32
33 /**************************************************************************
34  *  IQueryAssociations {SHLWAPI}
35  *
36  * DESCRIPTION
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).
44  *
45  * HELPERS
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:
51  *
52  * METHODS
53  */
54
55 /* Default IQueryAssociations::Init() flags */
56 #define SHLWAPI_DEF_ASSOCF (ASSOCF_INIT_BYEXENAME|ASSOCF_INIT_DEFAULTTOSTAR| \
57                             ASSOCF_INIT_DEFAULTTOFOLDER)
58
59 typedef struct
60 {
61   ICOM_VFIELD(IQueryAssociations);
62   LONG ref;
63 } IQueryAssociationsImpl;
64
65 static struct ICOM_VTABLE(IQueryAssociations) IQueryAssociations_vtbl;
66
67 /**************************************************************************
68  *  IQueryAssociations_Constructor [internal]
69  *
70  * Construct a new IQueryAssociations object.
71  */
72 static IQueryAssociations* IQueryAssociations_Constructor(void)
73 {
74   IQueryAssociationsImpl* iface;
75
76   iface =(IQueryAssociationsImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IQueryAssociationsImpl));
77   iface->lpVtbl = &IQueryAssociations_vtbl;
78   iface->ref = 1;
79
80   TRACE("Returning IQueryAssociations* %p\n", iface);
81   return (IQueryAssociations*)iface;
82 }
83
84 /*************************************************************************
85  * SHLWAPI_ParamAToW
86  *
87  * Internal helper function: Convert ASCII parameter to Unicode.
88  */
89 static BOOL SHLWAPI_ParamAToW(LPCSTR lpszParam, LPWSTR lpszBuff, DWORD dwLen,
90                               LPWSTR* lpszOut)
91 {
92   if (lpszParam)
93   {
94     DWORD dwStrLen = lstrlenA(lpszParam);
95
96     if (dwStrLen < dwLen)
97     {
98       *lpszOut = lpszBuff; /* Use Buffer, it is big enough */
99     }
100     else
101     {
102       /* Create a new buffer big enough for the string */
103       *lpszOut = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
104                                    (dwStrLen + 1) * sizeof(WCHAR));
105       if (!*lpszOut)
106         return FALSE;
107     }
108     MultiByteToWideChar(0, 0, lpszParam, -1, *lpszOut, -1);
109   }
110   else
111     *lpszOut = NULL;
112   return TRUE;
113 }
114
115 /*************************************************************************
116  * AssocCreate  [SHLWAPI.253]
117  *
118  * Create a new IQueryAssociations object.
119  *
120  * PARAMS
121  *  clsid       [I] CLSID of object
122  *  refiid      [I] REFIID of interface
123  *  lpInterface [O] Destination for the created IQueryAssociations object
124  *
125  * RETURNS
126  *  Success: S_OK. lpInterface contains the new object.
127  *  Failure: An HRESULT error code indicating the error.
128  *
129  * NOTES
130  *  refiid must be equal to IID_IQueryAssociations, or this function will fail.
131  */
132 HRESULT WINAPI AssocCreate(CLSID clsid, REFIID refiid, void **lpInterface)
133 {
134   HRESULT hRet;
135   IQueryAssociations* lpAssoc;
136
137   TRACE("(%s,%s,%p)\n", debugstr_guid(&clsid), debugstr_guid(refiid),
138         lpInterface);
139
140   if (!lpInterface)
141     return E_INVALIDARG;
142
143   *(DWORD*)lpInterface = 0;
144
145   if (!IsEqualGUID(&clsid, &IID_IQueryAssociations))
146     return E_NOTIMPL;
147
148   lpAssoc = IQueryAssociations_Constructor();
149
150   if (!lpAssoc)
151     return E_OUTOFMEMORY;
152
153   hRet = IQueryAssociations_QueryInterface(lpAssoc, refiid, lpInterface);
154   IQueryAssociations_Release(lpAssoc);
155   return hRet;
156 }
157
158 /*************************************************************************
159  * AssocQueryKeyW  [SHLWAPI.255]
160  *
161  * See AssocQueryKeyA.
162  */
163 HRESULT WINAPI AssocQueryKeyW(ASSOCF cfFlags, ASSOCKEY assockey, LPCWSTR pszAssoc,
164                               LPCWSTR pszExtra, HKEY *phkeyOut)
165 {
166   HRESULT hRet;
167   IQueryAssociations* lpAssoc;
168
169   TRACE("(0x%8lx,0x%8x,%s,%s,%p)\n", cfFlags, assockey, debugstr_w(pszAssoc),
170         debugstr_w(pszExtra), phkeyOut);
171
172   lpAssoc = IQueryAssociations_Constructor();
173
174   if (!lpAssoc)
175     return E_OUTOFMEMORY;
176
177   cfFlags &= SHLWAPI_DEF_ASSOCF;
178   hRet = IQueryAssociations_Init(lpAssoc, cfFlags, pszAssoc, NULL, NULL);
179
180   if (SUCCEEDED(hRet))
181     hRet = IQueryAssociations_GetKey(lpAssoc, cfFlags, assockey, pszExtra, phkeyOut);
182
183   IQueryAssociations_Release(lpAssoc);
184   return hRet;
185 }
186
187 /*************************************************************************
188  * AssocQueryKeyA  [SHLWAPI.254]
189  *
190  * Get a file association key from the registry.
191  *
192  * PARAMS
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
198  *
199  * RETURNS
200  *  Success: S_OK. phkeyOut contains the key.
201  *  Failure: An HRESULT error code indicating the error.
202  */
203 HRESULT WINAPI AssocQueryKeyA(ASSOCF cfFlags, ASSOCKEY assockey, LPCSTR pszAssoc,
204                               LPCSTR pszExtra, HKEY *phkeyOut)
205 {
206   WCHAR szAssocW[MAX_PATH], *lpszAssocW = NULL;
207   WCHAR szExtraW[MAX_PATH], *lpszExtraW = NULL;
208   HRESULT hRet = E_OUTOFMEMORY;
209
210   TRACE("(0x%8lx,0x%8x,%s,%s,%p)\n", cfFlags, assockey, debugstr_a(pszAssoc),
211         debugstr_a(pszExtra), phkeyOut);
212
213   if (SHLWAPI_ParamAToW(pszAssoc, szAssocW, MAX_PATH, &lpszAssocW) &&
214       SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW))
215   {
216     hRet = AssocQueryKeyW(cfFlags, assockey, lpszAssocW, lpszExtraW, phkeyOut);
217   }
218
219   if (lpszAssocW && lpszAssocW != szAssocW)
220     HeapFree(GetProcessHeap(), 0, lpszAssocW);
221
222   if (lpszExtraW && lpszExtraW != szExtraW)
223     HeapFree(GetProcessHeap(), 0, lpszExtraW);
224
225   return hRet;
226 }
227
228 /*************************************************************************
229  * AssocQueryStringW  [SHLWAPI.384]
230  *
231  * See AssocQueryStringA.
232  */
233 HRESULT WINAPI AssocQueryStringW(ASSOCF cfFlags, ASSOCSTR str, LPCWSTR pszAssoc,
234                                  LPCWSTR pszExtra, LPWSTR pszOut, DWORD *pcchOut)
235 {
236   HRESULT hRet;
237   IQueryAssociations* lpAssoc;
238
239   TRACE("(0x%8lx,0x%8x,%s,%s,%p,%p)\n", cfFlags, str, debugstr_w(pszAssoc),
240         debugstr_w(pszExtra), pszOut, pcchOut);
241
242   if (!pcchOut)
243     return E_INVALIDARG;
244
245   lpAssoc = IQueryAssociations_Constructor();
246
247   if (!lpAssoc)
248     return E_OUTOFMEMORY;
249
250   hRet = IQueryAssociations_Init(lpAssoc, cfFlags & SHLWAPI_DEF_ASSOCF,
251                                  pszAssoc, NULL, NULL);
252
253   if (SUCCEEDED(hRet))
254     hRet = IQueryAssociations_GetString(lpAssoc, cfFlags, str, pszExtra,
255                                         pszOut, pcchOut);
256
257   IQueryAssociations_Release(lpAssoc);
258   return hRet;
259 }
260
261 /*************************************************************************
262  * AssocQueryStringA  [SHLWAPI.381]
263  *
264  * Get a file association string from the registry.
265  *
266  * PARAMS
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
273  *
274  * RETURNS
275  *  Success: S_OK. pszOut contains the string, pcchOut contains its length.
276  *  Failure: An HRESULT error code indicating the error.
277  */
278 HRESULT WINAPI AssocQueryStringA(ASSOCF cfFlags, ASSOCSTR str, LPCSTR pszAssoc,
279                                  LPCSTR pszExtra, LPSTR pszOut, DWORD *pcchOut)
280 {
281   WCHAR szAssocW[MAX_PATH], *lpszAssocW = NULL;
282   WCHAR szExtraW[MAX_PATH], *lpszExtraW = NULL;
283   HRESULT hRet = E_OUTOFMEMORY;
284
285   TRACE("(0x%8lx,0x%8x,%s,%s,%p,%p)\n", cfFlags, str, debugstr_a(pszAssoc),
286         debugstr_a(pszExtra), pszOut, pcchOut);
287
288   if (!pcchOut)
289     hRet = E_INVALIDARG;
290   else if (SHLWAPI_ParamAToW(pszAssoc, szAssocW, MAX_PATH, &lpszAssocW) &&
291            SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW))
292   {
293     WCHAR szReturnW[MAX_PATH], *lpszReturnW = szReturnW;
294     DWORD dwLenOut = *pcchOut;
295
296     if (dwLenOut >= MAX_PATH)
297       lpszReturnW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
298                                       (dwLenOut + 1) * sizeof(WCHAR));
299
300     if (!lpszReturnW)
301       hRet = E_OUTOFMEMORY;
302     else
303     {
304       hRet = AssocQueryStringW(cfFlags, str, lpszAssocW, lpszExtraW,
305                                lpszReturnW, &dwLenOut);
306
307       if (SUCCEEDED(hRet))
308         WideCharToMultiByte(CP_ACP,0,szReturnW,-1,pszOut,dwLenOut,0,0);
309       *pcchOut = dwLenOut;
310
311       if (lpszReturnW && lpszReturnW != szReturnW)
312         HeapFree(GetProcessHeap(), 0, lpszReturnW);
313     }
314   }
315
316   if (lpszAssocW && lpszAssocW != szAssocW)
317     HeapFree(GetProcessHeap(), 0, lpszAssocW);
318   if (lpszExtraW && lpszExtraW != szExtraW)
319     HeapFree(GetProcessHeap(), 0, lpszExtraW);
320   return hRet;
321 }
322
323 /*************************************************************************
324  * AssocQueryStringByKeyW  [SHLWAPI.383]
325  *
326  * See AssocQueryStringByKeyA.
327  */
328 HRESULT WINAPI AssocQueryStringByKeyW(ASSOCF cfFlags, ASSOCSTR str, HKEY hkAssoc,
329                                       LPCWSTR pszExtra, LPWSTR pszOut,
330                                       DWORD *pcchOut)
331 {
332   HRESULT hRet;
333   IQueryAssociations* lpAssoc;
334
335   TRACE("(0x%8lx,0x%8x,%p,%s,%p,%p)\n", cfFlags, str, hkAssoc,
336         debugstr_w(pszExtra), pszOut, pcchOut);
337
338   lpAssoc = IQueryAssociations_Constructor();
339
340   if (!lpAssoc)
341     return E_OUTOFMEMORY;
342
343   cfFlags &= SHLWAPI_DEF_ASSOCF;
344   hRet = IQueryAssociations_Init(lpAssoc, cfFlags, 0, hkAssoc, NULL);
345
346   if (SUCCEEDED(hRet))
347     hRet = IQueryAssociations_GetString(lpAssoc, cfFlags, str, pszExtra,
348                                         pszOut, pcchOut);
349
350   IQueryAssociations_Release(lpAssoc);
351   return hRet;
352 }
353
354 /*************************************************************************
355  * AssocQueryStringByKeyA  [SHLWAPI.382]
356  *
357  * Get a file association string from the registry, given a starting key.
358  *
359  * PARAMS
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
366  *
367  * RETURNS
368  *  Success: S_OK. pszOut contains the string, pcchOut contains its length.
369  *  Failure: An HRESULT error code indicating the error.
370  */
371 HRESULT WINAPI AssocQueryStringByKeyA(ASSOCF cfFlags, ASSOCSTR str, HKEY hkAssoc,
372                                       LPCSTR pszExtra, LPSTR pszOut,
373                                       DWORD *pcchOut)
374 {
375   WCHAR szExtraW[MAX_PATH], *lpszExtraW;
376   WCHAR szReturnW[MAX_PATH], *lpszReturnW = szReturnW;
377   HRESULT hRet = E_OUTOFMEMORY;
378
379   TRACE("(0x%8lx,0x%8x,%p,%s,%p,%p)\n", cfFlags, str, hkAssoc,
380         debugstr_a(pszExtra), pszOut, pcchOut);
381
382   if (!pcchOut)
383     hRet = E_INVALIDARG;
384   else if (SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW))
385   {
386     DWORD dwLenOut = *pcchOut;
387     if (dwLenOut >= MAX_PATH)
388       lpszReturnW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
389                                       (dwLenOut + 1) * sizeof(WCHAR));
390
391     if (lpszReturnW)
392     {
393       hRet = AssocQueryStringByKeyW(cfFlags, str, hkAssoc, lpszExtraW,
394                                     lpszReturnW, &dwLenOut);
395
396       if (SUCCEEDED(hRet))
397         WideCharToMultiByte(CP_ACP,0,szReturnW,-1,pszOut,dwLenOut,0,0);
398       *pcchOut = dwLenOut;
399
400       if (lpszReturnW != szReturnW)
401         HeapFree(GetProcessHeap(), 0, lpszReturnW);
402     }
403   }
404
405   if (lpszExtraW && lpszExtraW != szExtraW)
406     HeapFree(GetProcessHeap(), 0, lpszExtraW);
407   return hRet;
408 }
409
410
411 /**************************************************************************
412  *  AssocIsDangerous  (SHLWAPI.@)
413  */
414 HRESULT WINAPI AssocIsDangerous( ASSOCSTR str )
415 {
416     FIXME("%08x\n", str);
417     return S_FALSE;
418 }
419
420 /**************************************************************************
421  *  IQueryAssociations_QueryInterface {SHLWAPI}
422  *
423  * See IUnknown_QueryInterface.
424  */
425 static HRESULT WINAPI IQueryAssociations_fnQueryInterface(
426   IQueryAssociations* iface,
427   REFIID riid,
428   LPVOID *ppvObj)
429 {
430   ICOM_THIS(IQueryAssociationsImpl, iface);
431
432   TRACE("(%p,%s,%p)\n",This, debugstr_guid(riid), ppvObj);
433
434   *ppvObj = NULL;
435
436   if (IsEqualIID(riid, &IID_IUnknown) ||
437       IsEqualIID(riid, &IID_IQueryAssociations))
438   {
439     *ppvObj = (IQueryAssociations*)This;
440
441     IQueryAssociations_AddRef((IQueryAssociations*)*ppvObj);
442     TRACE("Returning IQueryAssociations (%p)\n", *ppvObj);
443     return S_OK;
444   }
445   TRACE("Returning E_NOINTERFACE\n");
446   return E_NOINTERFACE;
447 }
448
449 /**************************************************************************
450  *  IQueryAssociations_AddRef {SHLWAPI}
451  *
452  * See IUnknown_AddRef.
453  */
454 static ULONG WINAPI IQueryAssociations_fnAddRef(IQueryAssociations *iface)
455 {
456   ICOM_THIS(IQueryAssociationsImpl,iface);
457
458   TRACE("(%p)->(ref before=%lu)\n",This, This->ref);
459
460   return InterlockedIncrement(&This->ref);
461 }
462
463 /**************************************************************************
464  *  IQueryAssociations_Release {SHLWAPI}
465  *
466  * See IUnknown_Release.
467  */
468 static ULONG WINAPI IQueryAssociations_fnRelease(IQueryAssociations *iface)
469 {
470   ICOM_THIS(IQueryAssociationsImpl,iface);
471   ULONG ulRet;
472
473   TRACE("(%p)->(ref before=%lu)\n",This, This->ref);
474
475   if (!(ulRet = InterlockedDecrement(&This->ref)))
476   {
477     TRACE("Destroying IQueryAssociations (%p)\n", This);
478     HeapFree(GetProcessHeap(), 0, This);
479   }
480   return ulRet;
481 }
482
483 /**************************************************************************
484  *  IQueryAssociations_Init {SHLWAPI}
485  *
486  * Initialise an IQueryAssociations object.
487  *
488  * PARAMS
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.
494  *
495  * RETURNS
496  *  Success: S_OK. iface is initialised with the parameters given.
497  *  Failure: An HRESULT error code indicating the error.
498  */
499 static HRESULT WINAPI IQueryAssociations_fnInit(
500   IQueryAssociations *iface,
501   ASSOCF cfFlags,
502   LPCWSTR pszAssoc,
503   HKEY hkProgid,
504   HWND hWnd)
505 {
506   ICOM_THIS(IQueryAssociationsImpl, iface);
507
508   FIXME("(%p,0x%8lx,%s,%p,%p)-stub!\n", This, cfFlags,
509         debugstr_w(pszAssoc), hkProgid, hWnd);
510   return E_NOTIMPL;
511 }
512
513 /**************************************************************************
514  *  IQueryAssociations_GetString {SHLWAPI}
515  *
516  * Get a file association string from the registry.
517  *
518  * PARAMS
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
525  *
526  * RETURNS
527  *  Success: S_OK. pszOut contains the string, pcchOut contains its length.
528  *  Failure: An HRESULT error code indicating the error.
529  */
530 static HRESULT WINAPI IQueryAssociations_fnGetString(
531   IQueryAssociations *iface,
532   ASSOCF cfFlags,
533   ASSOCSTR str,
534   LPCWSTR pszExtra,
535   LPWSTR pszOut,
536   DWORD *pcchOut)
537 {
538   ICOM_THIS(IQueryAssociationsImpl, iface);
539
540   FIXME("(%p,0x%8lx,0x%8x,%s,%p,%p)-stub!\n", This, cfFlags, str,
541         debugstr_w(pszExtra), pszOut, pcchOut);
542   return E_NOTIMPL;
543 }
544
545 /**************************************************************************
546  *  IQueryAssociations_GetKey {SHLWAPI}
547  *
548  * Get a file association key from the registry.
549  *
550  * PARAMS
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
556  *
557  * RETURNS
558  *  Success: S_OK. phkeyOut contains a handle to the key.
559  *  Failure: An HRESULT error code indicating the error.
560  */
561 static HRESULT WINAPI IQueryAssociations_fnGetKey(
562   IQueryAssociations *iface,
563   ASSOCF cfFlags,
564   ASSOCKEY assockey,
565   LPCWSTR pszExtra,
566   HKEY *phkeyOut)
567 {
568   ICOM_THIS(IQueryAssociationsImpl, iface);
569
570   FIXME("(%p,0x%8lx,0x%8x,%s,%p)-stub!\n", This, cfFlags, assockey,
571         debugstr_w(pszExtra), phkeyOut);
572   return E_NOTIMPL;
573 }
574
575 /**************************************************************************
576  *  IQueryAssociations_GetData {SHLWAPI}
577  *
578  * Get the data for a file association key from the registry.
579  *
580  * PARAMS
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
587  *
588  * RETURNS
589  *  Success: S_OK. pszOut contains the data, pcbOut contains its length.
590  *  Failure: An HRESULT error code indicating the error.
591  */
592 static HRESULT WINAPI IQueryAssociations_fnGetData(
593   IQueryAssociations *iface,
594   ASSOCF cfFlags,
595   ASSOCDATA assocdata,
596   LPCWSTR pszExtra,
597   LPVOID pvOut,
598   DWORD *pcbOut)
599 {
600   ICOM_THIS(IQueryAssociationsImpl, iface);
601
602   FIXME("(%p,0x%8lx,0x%8x,%s,%p,%p)-stub!\n", This, cfFlags, assocdata,
603         debugstr_w(pszExtra), pvOut, pcbOut);
604   return E_NOTIMPL;
605 }
606
607 /**************************************************************************
608  *  IQueryAssociations_GetEnum {SHLWAPI}
609  *
610  * Not yet implemented in native Win32.
611  *
612  * PARAMS
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.
619  *
620  * RETURNS
621  *  Success: S_OK.
622  *  Failure: An HRESULT error code indicating the error.
623  *
624  * NOTES
625  *  Presumably this function returns an enumerator object.
626  */
627 static HRESULT WINAPI IQueryAssociations_fnGetEnum(
628   IQueryAssociations *iface,
629   ASSOCF cfFlags,
630   ASSOCENUM assocenum,
631   LPCWSTR pszExtra,
632   REFIID riid,
633   LPVOID *ppvOut)
634 {
635   ICOM_THIS(IQueryAssociationsImpl, iface);
636
637   FIXME("(%p,0x%8lx,0x%8x,%s,%s,%p)-stub!\n", This, cfFlags, assocenum,
638         debugstr_w(pszExtra), debugstr_guid(riid), ppvOut);
639   return E_NOTIMPL;
640 }
641
642 static struct ICOM_VTABLE(IQueryAssociations) IQueryAssociations_vtbl =
643 {
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
653 };