Spelling stuff.
[wine] / dlls / comcat / information.c
1 /*
2  *      ComCatMgr ICatInformation implementation for comcat.dll
3  *
4  * Copyright (C) 2002 John K. Hohm
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
21 #include <string.h>
22 #include "comcat.h"
23
24 #include "wine/debug.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(ole);
27
28 static LPENUMCATEGORYINFO COMCAT_IEnumCATEGORYINFO_Construct(LCID lcid);
29 static HRESULT COMCAT_GetCategoryDesc(HKEY key, LCID lcid, PWCHAR pszDesc,
30                                       ULONG buf_wchars);
31
32 /**********************************************************************
33  * COMCAT_ICatInformation_QueryInterface
34  */
35 static HRESULT WINAPI COMCAT_ICatInformation_QueryInterface(
36     LPCATINFORMATION iface,
37     REFIID riid,
38     LPVOID *ppvObj)
39 {
40     ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface);
41     TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
42
43     if (This == NULL || ppvObj == NULL) return E_POINTER;
44
45     return IUnknown_QueryInterface((LPUNKNOWN)&This->unkVtbl, riid, ppvObj);
46 }
47
48 /**********************************************************************
49  * COMCAT_ICatInformation_AddRef
50  */
51 static ULONG WINAPI COMCAT_ICatInformation_AddRef(LPCATINFORMATION iface)
52 {
53     ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface);
54     TRACE("\n");
55
56     if (This == NULL) return E_POINTER;
57
58     return IUnknown_AddRef((LPUNKNOWN)&This->unkVtbl);
59 }
60
61 /**********************************************************************
62  * COMCAT_ICatInformation_Release
63  */
64 static ULONG WINAPI COMCAT_ICatInformation_Release(LPCATINFORMATION iface)
65 {
66     ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface);
67     TRACE("\n");
68
69     if (This == NULL) return E_POINTER;
70
71     return IUnknown_Release((LPUNKNOWN)&This->unkVtbl);
72 }
73
74 /**********************************************************************
75  * COMCAT_ICatInformation_EnumCategories
76  */
77 static HRESULT WINAPI COMCAT_ICatInformation_EnumCategories(
78     LPCATINFORMATION iface,
79     LCID lcid,
80     LPENUMCATEGORYINFO *ppenumCatInfo)
81 {
82 /*     ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface); */
83     TRACE("\n");
84
85     if (iface == NULL || ppenumCatInfo == NULL) return E_POINTER;
86
87     *ppenumCatInfo = COMCAT_IEnumCATEGORYINFO_Construct(lcid);
88     if (*ppenumCatInfo == NULL) return E_OUTOFMEMORY;
89     IEnumCATEGORYINFO_AddRef(*ppenumCatInfo);
90     return S_OK;
91 }
92
93 /**********************************************************************
94  * COMCAT_ICatInformation_GetCategoryDesc
95  */
96 static HRESULT WINAPI COMCAT_ICatInformation_GetCategoryDesc(
97     LPCATINFORMATION iface,
98     REFCATID rcatid,
99     LCID lcid,
100     PWCHAR *ppszDesc)
101 {
102 /*     ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface); */
103     WCHAR keyname[60] = { 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n',
104                           't', ' ', 'C', 'a', 't', 'e', 'g', 'o',
105                           'r', 'i', 'e', 's', '\\', 0 };
106     HKEY key;
107     HRESULT res;
108
109     TRACE("\n\tCATID:\t%s\n\tLCID:\t%lX\n",debugstr_guid(rcatid), lcid);
110
111     if (rcatid == NULL || ppszDesc == NULL) return E_INVALIDARG;
112
113     /* Open the key for this category. */
114     if (!StringFromGUID2(rcatid, keyname + 21, 39)) return E_FAIL;
115     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &key);
116     if (res != ERROR_SUCCESS) return CAT_E_CATIDNOEXIST;
117
118     /* Allocate a sensible amount of memory for the description. */
119     *ppszDesc = (PWCHAR) CoTaskMemAlloc(128 * sizeof(WCHAR));
120     if (*ppszDesc == NULL) {
121         RegCloseKey(key);
122         return E_OUTOFMEMORY;
123     }
124
125     /* Get the description, and make sure it's null terminated. */
126     res = COMCAT_GetCategoryDesc(key, lcid, *ppszDesc, 128);
127     RegCloseKey(key);
128     if (FAILED(res)) {
129         CoTaskMemFree(*ppszDesc);
130         return res;
131     }
132
133     return S_OK;
134 }
135
136 /**********************************************************************
137  * COMCAT_ICatInformation_EnumClassesOfCategories
138  */
139 static HRESULT WINAPI COMCAT_ICatInformation_EnumClassesOfCategories(
140     LPCATINFORMATION iface,
141     ULONG cImplemented,
142     CATID *rgcatidImpl,
143     ULONG cRequired,
144     CATID *rgcatidReq,
145     LPENUMCLSID *ppenumCLSID)
146 {
147 /*     ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface); */
148     FIXME("(): stub\n");
149
150     return E_NOTIMPL;
151 }
152
153 /**********************************************************************
154  * COMCAT_ICatInformation_IsClassOfCategories
155  */
156 static HRESULT WINAPI COMCAT_ICatInformation_IsClassOfCategories(
157     LPCATINFORMATION iface,
158     REFCLSID rclsid,
159     ULONG cImplemented,
160     CATID *rgcatidImpl,
161     ULONG cRequired,
162     CATID *rgcatidReq)
163 {
164 /*     ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface); */
165     FIXME("(): stub\n");
166
167     return E_NOTIMPL;
168 }
169
170 /**********************************************************************
171  * COMCAT_ICatInformation_EnumImplCategoriesOfClass
172  */
173 static HRESULT WINAPI COMCAT_ICatInformation_EnumImplCategoriesOfClass(
174     LPCATINFORMATION iface,
175     REFCLSID rclsid,
176     LPENUMCATID *ppenumCATID)
177 {
178 /*     ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface); */
179     FIXME("(): stub\n");
180
181     return E_NOTIMPL;
182 }
183
184 /**********************************************************************
185  * COMCAT_ICatInformation_EnumReqCategoriesOfClass
186  */
187 static HRESULT WINAPI COMCAT_ICatInformation_EnumReqCategoriesOfClass(
188     LPCATINFORMATION iface,
189     REFCLSID rclsid,
190     LPENUMCATID *ppenumCATID)
191 {
192 /*     ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface); */
193     FIXME("(): stub\n");
194
195     return E_NOTIMPL;
196 }
197
198 /**********************************************************************
199  * COMCAT_ICatInformation_Vtbl
200  */
201 ICOM_VTABLE(ICatInformation) COMCAT_ICatInformation_Vtbl =
202 {
203     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
204     COMCAT_ICatInformation_QueryInterface,
205     COMCAT_ICatInformation_AddRef,
206     COMCAT_ICatInformation_Release,
207     COMCAT_ICatInformation_EnumCategories,
208     COMCAT_ICatInformation_GetCategoryDesc,
209     COMCAT_ICatInformation_EnumClassesOfCategories,
210     COMCAT_ICatInformation_IsClassOfCategories,
211     COMCAT_ICatInformation_EnumImplCategoriesOfClass,
212     COMCAT_ICatInformation_EnumReqCategoriesOfClass
213 };
214
215 /**********************************************************************
216  * IEnumCATEGORYINFO implementation
217  *
218  * This implementation is not thread-safe.  The manager itself is, but
219  * I can't imagine a valid use of an enumerator in several threads.
220  */
221 typedef struct
222 {
223     ICOM_VFIELD(IEnumCATEGORYINFO);
224     DWORD ref;
225     LCID  lcid;
226     HKEY  key;
227     DWORD next_index;
228 } IEnumCATEGORYINFOImpl;
229
230 static ULONG WINAPI COMCAT_IEnumCATEGORYINFO_AddRef(LPENUMCATEGORYINFO iface)
231 {
232     ICOM_THIS(IEnumCATEGORYINFOImpl, iface);
233     TRACE("\n");
234
235     if (This == NULL) return E_POINTER;
236
237     return ++(This->ref);
238 }
239
240 static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_QueryInterface(
241     LPENUMCATEGORYINFO iface,
242     REFIID riid,
243     LPVOID *ppvObj)
244 {
245     ICOM_THIS(IEnumCATEGORYINFOImpl, iface);
246     TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
247
248     if (This == NULL || ppvObj == NULL) return E_POINTER;
249
250     if (IsEqualGUID(riid, &IID_IUnknown) ||
251         IsEqualGUID(riid, &IID_IEnumCATEGORYINFO))
252     {
253         *ppvObj = (LPVOID)iface;
254         COMCAT_IEnumCATEGORYINFO_AddRef(iface);
255         return S_OK;
256     }
257
258     return E_NOINTERFACE;
259 }
260
261 static ULONG WINAPI COMCAT_IEnumCATEGORYINFO_Release(LPENUMCATEGORYINFO iface)
262 {
263     ICOM_THIS(IEnumCATEGORYINFOImpl, iface);
264     TRACE("\n");
265
266     if (This == NULL) return E_POINTER;
267
268     if (--(This->ref) == 0) {
269         if (This->key) RegCloseKey(This->key);
270         HeapFree(GetProcessHeap(), 0, This);
271         return 0;
272     }
273     return This->ref;
274 }
275
276 static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Next(
277     LPENUMCATEGORYINFO iface,
278     ULONG celt,
279     CATEGORYINFO *rgelt,
280     ULONG *pceltFetched)
281 {
282     ICOM_THIS(IEnumCATEGORYINFOImpl, iface);
283     ULONG fetched = 0;
284
285     TRACE("\n");
286
287     if (This == NULL || rgelt == NULL) return E_POINTER;
288
289     if (This->key) while (fetched < celt) {
290         HRESULT res;
291         WCHAR catid[39];
292         DWORD cName = 39;
293         HKEY subkey;
294
295         res = RegEnumKeyExW(This->key, This->next_index, catid, &cName,
296                             NULL, NULL, NULL, NULL);
297         if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
298         ++(This->next_index);
299
300         res = CLSIDFromString(catid, &rgelt->catid);
301         if (FAILED(res)) continue;
302
303         res = RegOpenKeyExW(This->key, catid, 0, KEY_READ, &subkey);
304         if (res != ERROR_SUCCESS) continue;
305
306         res = COMCAT_GetCategoryDesc(subkey, This->lcid,
307                                      rgelt->szDescription, 128);
308         RegCloseKey(subkey);
309         if (FAILED(res)) continue;
310
311         rgelt->lcid = This->lcid;
312         ++fetched;
313         ++rgelt;
314     }
315
316     if (pceltFetched) *pceltFetched = fetched;
317     return fetched == celt ? S_OK : S_FALSE;
318 }
319
320 static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Skip(
321     LPENUMCATEGORYINFO iface,
322     ULONG celt)
323 {
324 /*     ICOM_THIS(IEnumCATEGORYINFOImpl, iface); */
325     FIXME("(): stub\n");
326
327     return E_NOTIMPL;
328 }
329
330 static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Reset(LPENUMCATEGORYINFO iface)
331 {
332 /*     ICOM_THIS(IEnumCATEGORYINFOImpl, iface); */
333     FIXME("(): stub\n");
334
335     return E_NOTIMPL;
336 }
337
338 static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Clone(
339     LPENUMCATEGORYINFO iface,
340     IEnumCATEGORYINFO **ppenum)
341 {
342 /*     ICOM_THIS(IEnumCATEGORYINFOImpl, iface); */
343     FIXME("(): stub\n");
344
345     return E_NOTIMPL;
346 }
347
348 ICOM_VTABLE(IEnumCATEGORYINFO) COMCAT_IEnumCATEGORYINFO_Vtbl =
349 {
350     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
351     COMCAT_IEnumCATEGORYINFO_QueryInterface,
352     COMCAT_IEnumCATEGORYINFO_AddRef,
353     COMCAT_IEnumCATEGORYINFO_Release,
354     COMCAT_IEnumCATEGORYINFO_Next,
355     COMCAT_IEnumCATEGORYINFO_Skip,
356     COMCAT_IEnumCATEGORYINFO_Reset,
357     COMCAT_IEnumCATEGORYINFO_Clone
358 };
359
360 static LPENUMCATEGORYINFO COMCAT_IEnumCATEGORYINFO_Construct(LCID lcid)
361 {
362     IEnumCATEGORYINFOImpl *This;
363
364     This = (IEnumCATEGORYINFOImpl *) HeapAlloc(
365         GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumCATEGORYINFOImpl));
366     if (This) {
367         WCHAR keyname[21] = { 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n',
368                               't', ' ', 'C', 'a', 't', 'e', 'g', 'o',
369                               'r', 'i', 'e', 's', 0 };
370
371         ICOM_VTBL(This) = &COMCAT_IEnumCATEGORYINFO_Vtbl;
372         This->lcid = lcid;
373         RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &This->key);
374     }
375     return (LPENUMCATEGORYINFO)This;
376 }
377
378 /**********************************************************************
379  * COMCAT_GetCategoryDesc
380  */
381 static HRESULT COMCAT_GetCategoryDesc(HKEY key, LCID lcid, PWCHAR pszDesc,
382                                       ULONG buf_wchars)
383 {
384     WCHAR fmt[4] = { '%', 'l', 'X', 0 };
385     WCHAR valname[5];
386     HRESULT res;
387     DWORD type, size = (buf_wchars - 1) * sizeof(WCHAR);
388
389     if (pszDesc == NULL) return E_INVALIDARG;
390
391     /* FIXME: lcid comparisons are more complex than this! */
392     swprintf(valname, fmt, lcid);
393     res = RegQueryValueExW(key, valname, 0, &type, (LPBYTE)pszDesc, &size);
394     if (res != ERROR_SUCCESS || type != REG_SZ) return CAT_E_NODESCRIPTION;
395     pszDesc[size / sizeof(WCHAR)] = (WCHAR)0;
396
397     return S_OK;
398 }