complete ICatInformation implementation
John K. Hohm
jhohm at acm.org
Sat Jun 1 16:43:27 CDT 2002
Changelog:
John K. Hohm <jhohm at acm.org>
complete ICatInformation implementation
-------------- next part --------------
Index: dlls/comcat/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/comcat/Makefile.in,v
retrieving revision 1.3
diff -u -r1.3 Makefile.in
--- dlls/comcat/Makefile.in 29 May 2002 19:25:50 -0000 1.3
+++ dlls/comcat/Makefile.in 1 Jun 2002 21:38:20 -0000
@@ -4,7 +4,7 @@
VPATH = @srcdir@
MODULE = comcat.dll
IMPORTS = ole32 user32 advapi32 kernel32
-EXTRALIBS = $(LIBUUID)
+EXTRALIBS = $(LIBUNICODE) $(LIBUUID)
LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o
Index: dlls/comcat/comcat.h
===================================================================
RCS file: /home/wine/wine/dlls/comcat/comcat.h,v
retrieving revision 1.3
diff -u -r1.3 comcat.h
--- dlls/comcat/comcat.h 29 May 2002 19:25:50 -0000 1.3
+++ dlls/comcat/comcat.h 1 Jun 2002 21:38:20 -0000
@@ -27,6 +27,7 @@
#include "wine/obj_base.h"
#include "wine/obj_enumguid.h"
#include "wine/obj_comcat.h"
+#include "wine/unicode.h"
/**********************************************************************
* Dll lifetime tracking declaration for comcat.dll
Index: dlls/comcat/information.c
===================================================================
RCS file: /home/wine/wine/dlls/comcat/information.c,v
retrieving revision 1.3
diff -u -r1.3 information.c
--- dlls/comcat/information.c 29 May 2002 19:25:50 -0000 1.3
+++ dlls/comcat/information.c 1 Jun 2002 21:38:20 -0000
@@ -30,6 +30,20 @@
static HRESULT COMCAT_GetCategoryDesc(HKEY key, LCID lcid, PWCHAR pszDesc,
ULONG buf_wchars);
+struct class_categories {
+ LPCWSTR impl_strings;
+ LPCWSTR req_strings;
+};
+
+static struct class_categories *COMCAT_PrepareClassCategories(
+ ULONG impl_count, CATID *impl_catids, ULONG req_count, CATID *req_catids);
+static HRESULT COMCAT_IsClassOfCategories(
+ HKEY key, struct class_categories const* class_categories);
+static LPENUMGUID COMCAT_CLSID_IEnumGUID_Construct(
+ struct class_categories const* class_categories);
+static LPENUMGUID COMCAT_CATID_IEnumGUID_Construct(
+ REFCLSID rclsid, LPCWSTR impl_req);
+
/**********************************************************************
* COMCAT_ICatInformation_QueryInterface
*/
@@ -146,9 +160,24 @@
LPENUMCLSID *ppenumCLSID)
{
/* ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface); */
- FIXME("(): stub\n");
+ struct class_categories *categories;
+
+ TRACE("\n");
- return E_NOTIMPL;
+ if (iface == NULL || ppenumCLSID == NULL ||
+ (cImplemented && rgcatidImpl == NULL) ||
+ (cRequired && rgcatidReq == NULL)) return E_POINTER;
+
+ categories = COMCAT_PrepareClassCategories(cImplemented, rgcatidImpl,
+ cRequired, rgcatidReq);
+ if (categories == NULL) return E_OUTOFMEMORY;
+ *ppenumCLSID = COMCAT_CLSID_IEnumGUID_Construct(categories);
+ if (*ppenumCLSID == NULL) {
+ HeapFree(GetProcessHeap(), 0, categories);
+ return E_OUTOFMEMORY;
+ }
+ IEnumGUID_AddRef(*ppenumCLSID);
+ return S_OK;
}
/**********************************************************************
@@ -163,9 +192,40 @@
CATID *rgcatidReq)
{
/* ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface); */
- FIXME("(): stub\n");
+ WCHAR keyname[45] = { 'C', 'L', 'S', 'I', 'D', '\\', 0 };
+ HRESULT res;
+ struct class_categories *categories;
+ HKEY key;
+
+ if (WINE_TRACE_ON(ole)) {
+ ULONG count;
+ TRACE("\n\tCLSID:\t%s\n\tImplemented %lu\n",debugstr_guid(rclsid),cImplemented);
+ for (count = 0; count < cImplemented; ++count)
+ DPRINTF("\t\t%s\n",debugstr_guid(&rgcatidImpl[count]));
+ DPRINTF("\tRequired %lu\n",cRequired);
+ for (count = 0; count < cRequired; ++count)
+ DPRINTF("\t\t%s\n",debugstr_guid(&rgcatidReq[count]));
+ }
+
+ if ((cImplemented && rgcatidImpl == NULL) ||
+ (cRequired && rgcatidReq == NULL)) return E_POINTER;
+
+ res = StringFromGUID2(rclsid, keyname + 6, 39);
+ if (FAILED(res)) return res;
+
+ categories = COMCAT_PrepareClassCategories(cImplemented, rgcatidImpl,
+ cRequired, rgcatidReq);
+ if (categories == NULL) return E_OUTOFMEMORY;
+
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &key);
+ if (res == ERROR_SUCCESS) {
+ res = COMCAT_IsClassOfCategories(key, categories);
+ RegCloseKey(key);
+ } else res = S_FALSE;
+
+ HeapFree(GetProcessHeap(), 0, categories);
- return E_NOTIMPL;
+ return res;
}
/**********************************************************************
@@ -177,9 +237,18 @@
LPENUMCATID *ppenumCATID)
{
/* ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface); */
- FIXME("(): stub\n");
+ WCHAR postfix[24] = { '\\', 'I', 'm', 'p', 'l', 'e', 'm', 'e',
+ 'n', 't', 'e', 'd', ' ', 'C', 'a', 't',
+ 'e', 'g', 'o', 'r', 'i', 'e', 's', 0 };
- return E_NOTIMPL;
+ TRACE("\n\tCLSID:\t%s\n",debugstr_guid(rclsid));
+
+ if (iface == NULL || rclsid == NULL || ppenumCATID == NULL)
+ return E_POINTER;
+
+ *ppenumCATID = COMCAT_CATID_IEnumGUID_Construct(rclsid, postfix);
+ if (*ppenumCATID == NULL) return E_OUTOFMEMORY;
+ return S_OK;
}
/**********************************************************************
@@ -191,9 +260,18 @@
LPENUMCATID *ppenumCATID)
{
/* ICOM_THIS_MULTI(ComCatMgrImpl, infVtbl, iface); */
- FIXME("(): stub\n");
+ WCHAR postfix[21] = { '\\', 'R', 'e', 'q', 'u', 'i', 'r', 'e',
+ 'd', ' ', 'C', 'a', 't', 'e', 'g', 'o',
+ 'r', 'i', 'e', 's', 0 };
+
+ TRACE("\n\tCLSID:\t%s\n",debugstr_guid(rclsid));
+
+ if (iface == NULL || rclsid == NULL || ppenumCATID == NULL)
+ return E_POINTER;
- return E_NOTIMPL;
+ *ppenumCATID = COMCAT_CATID_IEnumGUID_Construct(rclsid, postfix);
+ if (*ppenumCATID == NULL) return E_OUTOFMEMORY;
+ return S_OK;
}
/**********************************************************************
@@ -322,28 +400,54 @@
LPENUMCATEGORYINFO iface,
ULONG celt)
{
-/* ICOM_THIS(IEnumCATEGORYINFOImpl, iface); */
- FIXME("(): stub\n");
+ ICOM_THIS(IEnumCATEGORYINFOImpl, iface);
- return E_NOTIMPL;
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+ This->next_index += celt;
+ /* This should return S_FALSE when there aren't celt elems to skip. */
+ return S_OK;
}
static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Reset(LPENUMCATEGORYINFO iface)
{
-/* ICOM_THIS(IEnumCATEGORYINFOImpl, iface); */
- FIXME("(): stub\n");
+ ICOM_THIS(IEnumCATEGORYINFOImpl, iface);
- return E_NOTIMPL;
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+ This->next_index = 0;
+ return S_OK;
}
static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Clone(
LPENUMCATEGORYINFO iface,
IEnumCATEGORYINFO **ppenum)
{
-/* ICOM_THIS(IEnumCATEGORYINFOImpl, iface); */
- FIXME("(): stub\n");
+ ICOM_THIS(IEnumCATEGORYINFOImpl, iface);
+ WCHAR keyname[21] = { 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n',
+ 't', ' ', 'C', 'a', 't', 'e', 'g', 'o',
+ 'r', 'i', 'e', 's', 0 };
+ IEnumCATEGORYINFOImpl *new_this;
+
+ TRACE("\n");
+
+ if (This == NULL || ppenum == NULL) return E_POINTER;
+
+ new_this = (IEnumCATEGORYINFOImpl *) HeapAlloc(
+ GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumCATEGORYINFOImpl));
+ if (new_this == NULL) return E_OUTOFMEMORY;
+
+ ICOM_VTBL(new_this) = ICOM_VTBL(This);
+ new_this->ref = 1;
+ new_this->lcid = This->lcid;
+ /* FIXME: could we more efficiently use DuplicateHandle? */
+ RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &new_this->key);
+ new_this->next_index = This->next_index;
- return E_NOTIMPL;
+ *ppenum = (LPENUMCATEGORYINFO)new_this;
+ return S_OK;
}
ICOM_VTABLE(IEnumCATEGORYINFO) COMCAT_IEnumCATEGORYINFO_Vtbl =
@@ -392,8 +496,470 @@
/* FIXME: lcid comparisons are more complex than this! */
wsprintfW(valname, fmt, lcid);
res = RegQueryValueExW(key, valname, 0, &type, (LPBYTE)pszDesc, &size);
- if (res != ERROR_SUCCESS || type != REG_SZ) return CAT_E_NODESCRIPTION;
+ if (res != ERROR_SUCCESS || type != REG_SZ) {
+ FIXME("Simplified lcid comparison\n");
+ return CAT_E_NODESCRIPTION;
+ }
pszDesc[size / sizeof(WCHAR)] = (WCHAR)0;
return S_OK;
+}
+
+/**********************************************************************
+ * COMCAT_PrepareClassCategories
+ */
+static struct class_categories *COMCAT_PrepareClassCategories(
+ ULONG impl_count, CATID *impl_catids, ULONG req_count, CATID *req_catids)
+{
+ struct class_categories *categories;
+ WCHAR *strings;
+
+ categories = (struct class_categories *)HeapAlloc(
+ GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(struct class_categories) +
+ ((impl_count + req_count) * 39 + 2) * sizeof(WCHAR));
+ if (categories == NULL) return categories;
+
+ strings = (WCHAR *)(categories + 1);
+ categories->impl_strings = strings;
+ while (impl_count--) {
+ StringFromGUID2(impl_catids++, strings, 39);
+ strings += 39;
+ }
+ *strings++ = 0;
+
+ categories->req_strings = strings;
+ while (req_count--) {
+ StringFromGUID2(req_catids++, strings, 39);
+ strings += 39;
+ }
+ *strings++ = 0;
+
+ return categories;
+}
+
+/**********************************************************************
+ * COMCAT_IsClassOfCategories
+ */
+static HRESULT COMCAT_IsClassOfCategories(
+ HKEY key,
+ struct class_categories const* categories)
+{
+ WCHAR impl_keyname[23] = { 'I', 'm', 'p', 'l', 'e', 'm', 'e', 'n',
+ 't', 'e', 'd', ' ', 'C', 'a', 't', 'e',
+ 'g', 'o', 'r', 'i', 'e', 's', 0 };
+ WCHAR req_keyname[20] = { 'R', 'e', 'q', 'u', 'i', 'r', 'e', 'd',
+ ' ', 'C', 'a', 't', 'e', 'g', 'o', 'r',
+ 'i', 'e', 's', 0 };
+ HKEY subkey;
+ HRESULT res;
+ DWORD index;
+ LPCWSTR string;
+
+ /* Check that every given category is implemented by class. */
+ res = RegOpenKeyExW(key, impl_keyname, 0, KEY_READ, &subkey);
+ if (res != ERROR_SUCCESS) return S_FALSE;
+ for (string = categories->impl_strings; *string; string += 39) {
+ HKEY catkey;
+ res = RegOpenKeyExW(subkey, string, 0, 0, &catkey);
+ if (res != ERROR_SUCCESS) {
+ RegCloseKey(subkey);
+ return S_FALSE;
+ }
+ RegCloseKey(catkey);
+ }
+ RegCloseKey(subkey);
+
+ /* Check that all categories required by class are given. */
+ res = RegOpenKeyExW(key, req_keyname, 0, KEY_READ, &subkey);
+ if (res == ERROR_SUCCESS) {
+ for (index = 0; ; ++index) {
+ WCHAR keyname[39];
+ DWORD size = 39;
+
+ res = RegEnumKeyExW(subkey, index, keyname, &size,
+ NULL, NULL, NULL, NULL);
+ if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
+ if (size != 38) continue; /* bogus catid in registry */
+ for (string = categories->req_strings; *string; string += 39)
+ if (!strcmpiW(string, keyname)) break;
+ if (!*string) {
+ RegCloseKey(subkey);
+ return S_FALSE;
+ }
+ }
+ RegCloseKey(subkey);
+ }
+
+ return S_OK;
+}
+
+/**********************************************************************
+ * ClassesOfCategories IEnumCLSID (IEnumGUID) implementation
+ *
+ * This implementation is not thread-safe. The manager itself is, but
+ * I can't imagine a valid use of an enumerator in several threads.
+ */
+typedef struct
+{
+ ICOM_VFIELD(IEnumGUID);
+ DWORD ref;
+ struct class_categories const *categories;
+ HKEY key;
+ DWORD next_index;
+} CLSID_IEnumGUIDImpl;
+
+static ULONG WINAPI COMCAT_CLSID_IEnumGUID_AddRef(LPENUMGUID iface)
+{
+ ICOM_THIS(CLSID_IEnumGUIDImpl, iface);
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ return ++(This->ref);
+}
+
+static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_QueryInterface(
+ LPENUMGUID iface,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ ICOM_THIS(CLSID_IEnumGUIDImpl, iface);
+ TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+ if (This == NULL || ppvObj == NULL) return E_POINTER;
+
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_IEnumGUID))
+ {
+ *ppvObj = (LPVOID)iface;
+ COMCAT_CLSID_IEnumGUID_AddRef(iface);
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI COMCAT_CLSID_IEnumGUID_Release(LPENUMGUID iface)
+{
+ ICOM_THIS(CLSID_IEnumGUIDImpl, iface);
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ if (--(This->ref) == 0) {
+ if (This->key) RegCloseKey(This->key);
+ HeapFree(GetProcessHeap(), 0, (LPVOID)This->categories);
+ HeapFree(GetProcessHeap(), 0, This);
+ return 0;
+ }
+ return This->ref;
+}
+
+static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Next(
+ LPENUMGUID iface,
+ ULONG celt,
+ GUID *rgelt,
+ ULONG *pceltFetched)
+{
+ ICOM_THIS(CLSID_IEnumGUIDImpl, iface);
+ ULONG fetched = 0;
+
+ TRACE("\n");
+
+ if (This == NULL || rgelt == NULL) return E_POINTER;
+
+ if (This->key) while (fetched < celt) {
+ HRESULT res;
+ WCHAR clsid[39];
+ DWORD cName = 39;
+ HKEY subkey;
+
+ res = RegEnumKeyExW(This->key, This->next_index, clsid, &cName,
+ NULL, NULL, NULL, NULL);
+ if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
+ ++(This->next_index);
+
+ res = CLSIDFromString(clsid, rgelt);
+ if (FAILED(res)) continue;
+
+ res = RegOpenKeyExW(This->key, clsid, 0, KEY_READ, &subkey);
+ if (res != ERROR_SUCCESS) continue;
+
+ res = COMCAT_IsClassOfCategories(subkey, This->categories);
+ RegCloseKey(subkey);
+ if (res != S_OK) continue;
+
+ ++fetched;
+ ++rgelt;
+ }
+
+ if (pceltFetched) *pceltFetched = fetched;
+ return fetched == celt ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Skip(
+ LPENUMGUID iface,
+ ULONG celt)
+{
+ ICOM_THIS(CLSID_IEnumGUIDImpl, iface);
+
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+ This->next_index += celt;
+ FIXME("Never returns S_FALSE\n");
+ return S_OK;
+}
+
+static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Reset(LPENUMGUID iface)
+{
+ ICOM_THIS(CLSID_IEnumGUIDImpl, iface);
+
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+ This->next_index = 0;
+ return S_OK;
+}
+
+static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Clone(
+ LPENUMGUID iface,
+ IEnumGUID **ppenum)
+{
+ ICOM_THIS(CLSID_IEnumGUIDImpl, iface);
+ WCHAR keyname[6] = { 'C', 'L', 'S', 'I', 'D', 0 };
+ CLSID_IEnumGUIDImpl *new_this;
+ DWORD size;
+
+ TRACE("\n");
+
+ if (This == NULL || ppenum == NULL) return E_POINTER;
+
+ new_this = (CLSID_IEnumGUIDImpl *) HeapAlloc(
+ GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLSID_IEnumGUIDImpl));
+ if (new_this == NULL) return E_OUTOFMEMORY;
+
+ ICOM_VTBL(new_this) = ICOM_VTBL(This);
+ new_this->ref = 1;
+ size = HeapSize(GetProcessHeap(), 0, (LPVOID)This->categories);
+ new_this->categories = (struct class_categories *)
+ HeapAlloc(GetProcessHeap(), 0, size);
+ if (new_this->categories == NULL) {
+ HeapFree(GetProcessHeap(), 0, new_this);
+ return E_OUTOFMEMORY;
+ }
+ memcpy((LPVOID)new_this->categories, This->categories, size);
+ /* FIXME: could we more efficiently use DuplicateHandle? */
+ RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &new_this->key);
+ new_this->next_index = This->next_index;
+
+ *ppenum = (LPENUMGUID)new_this;
+ return S_OK;
+}
+
+ICOM_VTABLE(IEnumGUID) COMCAT_CLSID_IEnumGUID_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ COMCAT_CLSID_IEnumGUID_QueryInterface,
+ COMCAT_CLSID_IEnumGUID_AddRef,
+ COMCAT_CLSID_IEnumGUID_Release,
+ COMCAT_CLSID_IEnumGUID_Next,
+ COMCAT_CLSID_IEnumGUID_Skip,
+ COMCAT_CLSID_IEnumGUID_Reset,
+ COMCAT_CLSID_IEnumGUID_Clone
+};
+
+static LPENUMGUID COMCAT_CLSID_IEnumGUID_Construct(
+ struct class_categories const* categories)
+{
+ CLSID_IEnumGUIDImpl *This;
+
+ This = (CLSID_IEnumGUIDImpl *) HeapAlloc(
+ GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLSID_IEnumGUIDImpl));
+ if (This) {
+ WCHAR keyname[6] = { 'C', 'L', 'S', 'I', 'D', 0 };
+
+ ICOM_VTBL(This) = &COMCAT_CLSID_IEnumGUID_Vtbl;
+ This->categories = categories;
+ RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &This->key);
+ }
+ return (LPENUMGUID)This;
+}
+
+/**********************************************************************
+ * CategoriesOfClass IEnumCATID (IEnumGUID) implementation
+ *
+ * This implementation is not thread-safe. The manager itself is, but
+ * I can't imagine a valid use of an enumerator in several threads.
+ */
+typedef struct
+{
+ ICOM_VFIELD(IEnumGUID);
+ DWORD ref;
+ WCHAR keyname[68];
+ HKEY key;
+ DWORD next_index;
+} CATID_IEnumGUIDImpl;
+
+static ULONG WINAPI COMCAT_CATID_IEnumGUID_AddRef(LPENUMGUID iface)
+{
+ ICOM_THIS(CATID_IEnumGUIDImpl, iface);
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ return ++(This->ref);
+}
+
+static HRESULT WINAPI COMCAT_CATID_IEnumGUID_QueryInterface(
+ LPENUMGUID iface,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ ICOM_THIS(CATID_IEnumGUIDImpl, iface);
+ TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+ if (This == NULL || ppvObj == NULL) return E_POINTER;
+
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_IEnumGUID))
+ {
+ *ppvObj = (LPVOID)iface;
+ COMCAT_CATID_IEnumGUID_AddRef(iface);
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI COMCAT_CATID_IEnumGUID_Release(LPENUMGUID iface)
+{
+ ICOM_THIS(CATID_IEnumGUIDImpl, iface);
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ if (--(This->ref) == 0) {
+ if (This->key) RegCloseKey(This->key);
+ HeapFree(GetProcessHeap(), 0, This);
+ return 0;
+ }
+ return This->ref;
+}
+
+static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Next(
+ LPENUMGUID iface,
+ ULONG celt,
+ GUID *rgelt,
+ ULONG *pceltFetched)
+{
+ ICOM_THIS(CATID_IEnumGUIDImpl, iface);
+ ULONG fetched = 0;
+
+ TRACE("\n");
+
+ if (This == NULL || rgelt == NULL) return E_POINTER;
+
+ if (This->key) while (fetched < celt) {
+ HRESULT res;
+ WCHAR catid[39];
+ DWORD cName = 39;
+
+ res = RegEnumKeyExW(This->key, This->next_index, catid, &cName,
+ NULL, NULL, NULL, NULL);
+ if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
+ ++(This->next_index);
+
+ res = CLSIDFromString(catid, rgelt);
+ if (FAILED(res)) continue;
+
+ ++fetched;
+ ++rgelt;
+ }
+
+ if (pceltFetched) *pceltFetched = fetched;
+ return fetched == celt ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Skip(
+ LPENUMGUID iface,
+ ULONG celt)
+{
+ ICOM_THIS(CATID_IEnumGUIDImpl, iface);
+
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+ This->next_index += celt;
+ FIXME("Never returns S_FALSE\n");
+ return S_OK;
+}
+
+static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Reset(LPENUMGUID iface)
+{
+ ICOM_THIS(CATID_IEnumGUIDImpl, iface);
+
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+ This->next_index = 0;
+ return S_OK;
+}
+
+static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Clone(
+ LPENUMGUID iface,
+ IEnumGUID **ppenum)
+{
+ ICOM_THIS(CATID_IEnumGUIDImpl, iface);
+ CATID_IEnumGUIDImpl *new_this;
+
+ TRACE("\n");
+
+ if (This == NULL || ppenum == NULL) return E_POINTER;
+
+ new_this = (CATID_IEnumGUIDImpl *) HeapAlloc(
+ GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CATID_IEnumGUIDImpl));
+ if (new_this == NULL) return E_OUTOFMEMORY;
+
+ ICOM_VTBL(new_this) = ICOM_VTBL(This);
+ new_this->ref = 1;
+ lstrcpyW(new_this->keyname, This->keyname);
+ /* FIXME: could we more efficiently use DuplicateHandle? */
+ RegOpenKeyExW(HKEY_CLASSES_ROOT, new_this->keyname, 0, KEY_READ, &new_this->key);
+ new_this->next_index = This->next_index;
+
+ *ppenum = (LPENUMGUID)new_this;
+ return S_OK;
+}
+
+ICOM_VTABLE(IEnumGUID) COMCAT_CATID_IEnumGUID_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ COMCAT_CATID_IEnumGUID_QueryInterface,
+ COMCAT_CATID_IEnumGUID_AddRef,
+ COMCAT_CATID_IEnumGUID_Release,
+ COMCAT_CATID_IEnumGUID_Next,
+ COMCAT_CATID_IEnumGUID_Skip,
+ COMCAT_CATID_IEnumGUID_Reset,
+ COMCAT_CATID_IEnumGUID_Clone
+};
+
+static LPENUMGUID COMCAT_CATID_IEnumGUID_Construct(
+ REFCLSID rclsid, LPCWSTR postfix)
+{
+ CATID_IEnumGUIDImpl *This;
+
+ This = (CATID_IEnumGUIDImpl *) HeapAlloc(
+ GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CATID_IEnumGUIDImpl));
+ if (This) {
+ WCHAR prefix[6] = { 'C', 'L', 'S', 'I', 'D', '\\' };
+
+ ICOM_VTBL(This) = &COMCAT_CATID_IEnumGUID_Vtbl;
+ memcpy(This->keyname, prefix, sizeof prefix);
+ StringFromGUID2(rclsid, This->keyname + 6, 39);
+ lstrcpyW(This->keyname + 44, postfix);
+ RegOpenKeyExW(HKEY_CLASSES_ROOT, This->keyname, 0, KEY_READ, &This->key);
+ }
+ return (LPENUMGUID)This;
}
More information about the wine-patches
mailing list