Removed uses of the non standard ICOM_VTBL macro.
[wine] / dlls / shlwapi / assoc.c
1 /*
2  * SHLWAPI 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * NOTES
21  *  These function simplify the process of using the IQueryAssociations
22  *  interface, primarily by providing the means to get an interface pointer.
23  *  For those not interested in the object, the AssocQuery* functions hide
24  *  the object completely and simply provide the functionality.
25  *
26  *  We require the implementation from shell32 because there is no interface
27  *  for exporting an IQueryAssociations object available from that dll -
28  *  as it is, we need the constructor.
29  */
30 #include "windef.h"
31 #include "winnls.h"
32 #include "winreg.h"
33 #include "shlguid.h"
34 #include "shlwapi.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(shell);
38
39 /* Default IQueryAssociations::Init() flags */
40 #define SHLWAPI_DEF_ASSOCF (ASSOCF_INIT_BYEXENAME|ASSOCF_INIT_DEFAULTTOSTAR| \
41                             ASSOCF_INIT_DEFAULTTOFOLDER)
42
43 /* FIXME:
44  * This is a temporary placeholder. We need the whole IQueryAssociations object.
45  */
46 static IQueryAssociations* IQueryAssociations_Constructor()
47 {
48   FIXME("() stub!\n");
49   return NULL;
50 }
51
52 /*************************************************************************
53  * SHLWAPI_ParamAToW
54  *
55  * Internal helper function: Convert ASCII parameter to Unicode.
56  */
57 static BOOL SHLWAPI_ParamAToW(LPCSTR lpszParam, LPWSTR lpszBuff, DWORD dwLen,
58                               LPWSTR* lpszOut)
59 {
60   if (lpszParam)
61   {
62     DWORD dwStrLen = lstrlenA(lpszParam);
63
64     if (dwStrLen < dwLen)
65     {
66       *lpszOut = lpszBuff; /* Use Buffer, it is big enough */
67     }
68     else
69     {
70       /* Create a new buffer big enough for the string */
71       *lpszOut = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
72                                    (dwStrLen + 1) * sizeof(WCHAR));
73       if (!*lpszOut)
74         return FALSE;
75     }
76     MultiByteToWideChar(0, 0, lpszParam, -1, *lpszOut, -1);
77   }
78   else
79     *lpszOut = NULL;
80   return TRUE;
81 }
82
83 /*************************************************************************
84  * AssocCreate  [SHLWAPI.253]
85  *
86  * Create a new IQueryAssociations object.
87  *
88  * PARAMS
89  *  clsid       [I] CLSID of object
90  *  refiid      [I] REFIID of interface
91  *  lpInterface [O] Destination for the created IQueryAssociations object
92  *
93  * RETURNS
94  *  Success: S_OK. lpInterface contains the new object
95  *  Failure: An HRESULT error value
96  */
97 HRESULT WINAPI AssocCreate(CLSID clsid, REFIID refiid, void **lpInterface)
98 {
99   HRESULT hRet;
100   IQueryAssociations* lpAssoc;
101
102   TRACE("(%s,%s,%p)\n", debugstr_guid(&clsid), debugstr_guid(refiid),
103         lpInterface);
104
105   if (!lpInterface)
106     return E_INVALIDARG;
107
108   *(DWORD*)lpInterface = 0;
109
110   if (!IsEqualGUID(&clsid, &IID_IQueryAssociations))
111     return E_NOTIMPL;
112
113   lpAssoc = IQueryAssociations_Constructor();
114
115   if (!lpAssoc)
116     return E_OUTOFMEMORY;
117
118   hRet = IQueryAssociations_QueryInterface(lpAssoc, refiid, lpInterface);
119   IQueryAssociations_Release(lpAssoc);
120   return hRet;
121 }
122
123 /*************************************************************************
124  * AssocQueryKeyW       [SHLWAPI.255]
125  *
126  * See AssocQueryKeyA.
127  */
128 HRESULT WINAPI AssocQueryKeyW(ASSOCF flags, ASSOCKEY key, LPCWSTR pszAssoc,
129                               LPCWSTR pszExtra, HKEY *phkeyOut)
130 {
131   HRESULT hRet;
132   IQueryAssociations* lpAssoc;
133
134   lpAssoc = IQueryAssociations_Constructor();
135
136   if (!lpAssoc)
137     return E_OUTOFMEMORY;
138
139   flags &= SHLWAPI_DEF_ASSOCF;
140   hRet = IQueryAssociations_Init(lpAssoc, flags, pszAssoc, NULL, NULL);
141
142   if (SUCCEEDED(hRet))
143     hRet = IQueryAssociations_GetKey(lpAssoc, flags, key, pszExtra, phkeyOut);
144
145   IQueryAssociations_Release(lpAssoc);
146   return hRet;
147 }
148
149 /*************************************************************************
150  * AssocQueryKeyA       [SHLWAPI.254]
151  *
152  * Get a file association key from the registry.
153  *
154  * PARAMS
155  *  flags    [I] Flags for the search
156  *  key      [I] Type of key to get
157  *  pszAssoc [I] Key name to search below
158  *  pszExtra [I] Extra information about the key location
159  *  phkeyOut [O] Destination for the association key
160  *
161  * RETURNS
162  *  Success: S_OK. phkeyOut contains the key
163  *  Failure: An HRESULT error code
164  */
165 HRESULT WINAPI AssocQueryKeyA(ASSOCF flags, ASSOCKEY key, LPCSTR pszAssoc,
166                               LPCSTR pszExtra, HKEY *phkeyOut)
167 {
168   WCHAR szAssocW[MAX_PATH], *lpszAssocW = NULL;
169   WCHAR szExtraW[MAX_PATH], *lpszExtraW = NULL;
170   HRESULT hRet = E_OUTOFMEMORY;
171
172   if (SHLWAPI_ParamAToW(pszAssoc, szAssocW, MAX_PATH, &lpszAssocW) &&
173       SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW))
174   {
175     hRet = AssocQueryKeyW(flags, key, lpszAssocW, lpszExtraW, phkeyOut);
176   }
177
178   if (lpszAssocW && lpszAssocW != szAssocW)
179     HeapFree(GetProcessHeap(), 0, lpszAssocW);
180
181   if (lpszExtraW && lpszExtraW != szExtraW)
182     HeapFree(GetProcessHeap(), 0, lpszExtraW);
183
184   return hRet;
185 }
186
187 /*************************************************************************
188  * AssocQueryStringW    [SHLWAPI.384]
189  *
190  * See AssocQueryStringA.
191  */
192 HRESULT WINAPI AssocQueryStringW(ASSOCF flags, ASSOCSTR str, LPCWSTR pszAssoc,
193                                  LPCWSTR pszExtra, LPWSTR pszOut, DWORD *pcchOut)
194 {
195   HRESULT hRet;
196   IQueryAssociations* lpAssoc;
197
198   if (!pcchOut)
199     return E_INVALIDARG;
200
201   lpAssoc = IQueryAssociations_Constructor();
202
203   if (!lpAssoc)
204     return E_OUTOFMEMORY;
205
206   hRet = IQueryAssociations_Init(lpAssoc, flags & SHLWAPI_DEF_ASSOCF,
207                                  pszAssoc, NULL, NULL);
208
209   if (SUCCEEDED(hRet))
210     hRet = IQueryAssociations_GetString(lpAssoc, flags, str, pszExtra,
211                                         pszOut, pcchOut);
212
213   IQueryAssociations_Release(lpAssoc);
214   return hRet;
215 }
216
217 /*************************************************************************
218  * AssocQueryStringA    [SHLWAPI.381]
219  *
220  * Get a file association string from the registry.
221  *
222  * PARAMS
223  *  flags    [I] Flags for the search
224  *  str      [I] Type of string to get
225  *  pszAssoc [I] Key name to search below
226  *  pszExtra [I] Extra information about the string location
227  *  pszOut   [O] Destination for the association string
228  *  pcchOut  [O] Length of pszOut
229  *
230  * RETURNS
231  *  Success: S_OK. pszOut contains the string.
232  *  Failure: An HRESULT error code.
233  */
234 HRESULT WINAPI AssocQueryStringA(ASSOCF flags, ASSOCSTR str, LPCSTR pszAssoc,
235                                  LPCSTR pszExtra, LPSTR pszOut, DWORD *pcchOut)
236 {
237   WCHAR szAssocW[MAX_PATH], *lpszAssocW = NULL;
238   WCHAR szExtraW[MAX_PATH], *lpszExtraW = NULL;
239   HRESULT hRet = E_OUTOFMEMORY;
240
241   if (!pcchOut)
242     hRet = E_INVALIDARG;
243   else if (SHLWAPI_ParamAToW(pszAssoc, szAssocW, MAX_PATH, &lpszAssocW) &&
244            SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW))
245   {
246     WCHAR szReturnW[MAX_PATH], *lpszReturnW = szReturnW;
247     DWORD dwLenOut = *pcchOut;
248
249     if (dwLenOut >= MAX_PATH)
250       lpszReturnW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
251                                       (dwLenOut + 1) * sizeof(WCHAR));
252
253     if (!lpszReturnW)
254       hRet = E_OUTOFMEMORY;
255     else
256     {
257       hRet = AssocQueryStringW(flags, str, lpszAssocW, lpszExtraW,
258                                lpszReturnW, &dwLenOut);
259
260       if (SUCCEEDED(hRet))
261         WideCharToMultiByte(CP_ACP,0,szReturnW,-1,pszOut,dwLenOut,0,0);
262       *pcchOut = dwLenOut;
263
264       if (lpszReturnW && lpszReturnW != szReturnW)
265         HeapFree(GetProcessHeap(), 0, lpszReturnW);
266     }
267   }
268
269   if (lpszAssocW && lpszAssocW != szAssocW)
270     HeapFree(GetProcessHeap(), 0, lpszAssocW);
271   if (lpszExtraW && lpszExtraW != szExtraW)
272     HeapFree(GetProcessHeap(), 0, lpszExtraW);
273   return hRet;
274 }
275
276 /*************************************************************************
277  * AssocQueryStringByKeyW       [SHLWAPI.383]
278  *
279  * See AssocQueryStringByKeyA.
280  */
281 HRESULT WINAPI AssocQueryStringByKeyW(ASSOCF flags, ASSOCSTR str, HKEY hkAssoc,
282                                       LPCWSTR pszExtra, LPWSTR pszOut,
283                                       DWORD *pcchOut)
284 {
285   HRESULT hRet;
286   IQueryAssociations* lpAssoc;
287
288   lpAssoc = IQueryAssociations_Constructor();
289
290   if (!lpAssoc)
291     return E_OUTOFMEMORY;
292
293   flags &= SHLWAPI_DEF_ASSOCF;
294   hRet = IQueryAssociations_Init(lpAssoc, flags, 0, hkAssoc, NULL);
295
296   if (SUCCEEDED(hRet))
297     hRet = IQueryAssociations_GetString(lpAssoc, flags, str, pszExtra,
298                                         pszOut, pcchOut);
299
300   IQueryAssociations_Release(lpAssoc);
301   return hRet;
302 }
303
304 /*************************************************************************
305  * AssocQueryStringByKeyA       [SHLWAPI.382]
306  *
307  * Get a file association string from the registry, given a starting key.
308  *
309  * PARAMS
310  *  flags    [I] Flags for the search
311  *  str      [I] Type of string to get
312  *  hkAssoc  [I] Key to search below
313  *  pszExtra [I] Extra information about the string location
314  *  pszOut   [O] Destination for the association string
315  *  pcchOut  [O] Length of pszOut
316  *
317  * RETURNS
318  *  Success: S_OK. pszOut contains the string.
319  *  Failure: An HRESULT error code.
320  */
321 HRESULT WINAPI AssocQueryStringByKeyA(ASSOCF flags, ASSOCSTR str, HKEY hkAssoc,
322                                       LPCSTR pszExtra, LPSTR pszOut,
323                                       DWORD *pcchOut)
324 {
325   WCHAR szExtraW[MAX_PATH], *lpszExtraW;
326   WCHAR szReturnW[MAX_PATH], *lpszReturnW = szReturnW;
327   HRESULT hRet = E_OUTOFMEMORY;
328
329   if (!pcchOut)
330     hRet = E_INVALIDARG;
331   else if (SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW))
332   {
333     DWORD dwLenOut = *pcchOut;
334     if (dwLenOut >= MAX_PATH)
335       lpszReturnW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
336                                       (dwLenOut + 1) * sizeof(WCHAR));
337
338     if (lpszReturnW)
339     {
340       hRet = AssocQueryStringByKeyW(flags, str, hkAssoc, lpszExtraW,
341                                     lpszReturnW, &dwLenOut);
342
343       if (SUCCEEDED(hRet))
344         WideCharToMultiByte(CP_ACP,0,szReturnW,-1,pszOut,dwLenOut,0,0);
345       *pcchOut = dwLenOut;
346
347       if (lpszReturnW != szReturnW)
348         HeapFree(GetProcessHeap(), 0, lpszReturnW);
349     }
350   }
351
352   if (lpszExtraW && lpszExtraW != szExtraW)
353     HeapFree(GetProcessHeap(), 0, lpszExtraW);
354   return hRet;
355 }