Vincent Povirk : windowscodecs: Implement IWICImagingFactory:: CreateComponentEnumerator.
Alexandre Julliard
julliard at winehq.org
Wed Aug 5 09:48:17 CDT 2009
Module: wine
Branch: master
Commit: cd4fdb95875a835fdc2868f7bb943cbdcd048d0c
URL: http://source.winehq.org/git/wine.git/?a=commit;h=cd4fdb95875a835fdc2868f7bb943cbdcd048d0c
Author: Vincent Povirk <vincent at codeweavers.com>
Date: Tue Jul 28 19:08:42 2009 -0500
windowscodecs: Implement IWICImagingFactory::CreateComponentEnumerator.
---
dlls/windowscodecs/imgfactory.c | 4 +-
dlls/windowscodecs/info.c | 261 ++++++++++++++++++++++++++++++++
dlls/windowscodecs/wincodecs_private.h | 1 +
3 files changed, 264 insertions(+), 2 deletions(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c
index bdc2c45..e7bca4c 100644
--- a/dlls/windowscodecs/imgfactory.c
+++ b/dlls/windowscodecs/imgfactory.c
@@ -246,8 +246,8 @@ static HRESULT WINAPI ImagingFactory_CreateBitmapFromHICON(IWICImagingFactory *i
static HRESULT WINAPI ImagingFactory_CreateComponentEnumerator(IWICImagingFactory *iface,
DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
{
- FIXME("(%p,%u,%u,%p): stub\n", iface, componentTypes, options, ppIEnumUnknown);
- return E_NOTIMPL;
+ TRACE("(%p,%u,%u,%p)\n", iface, componentTypes, options, ppIEnumUnknown);
+ return CreateComponentEnumerator(componentTypes, options, ppIEnumUnknown);
}
static HRESULT WINAPI ImagingFactory_CreateFastMetadataEncoderFromDecoder(
diff --git a/dlls/windowscodecs/info.c b/dlls/windowscodecs/info.c
index 12eb4f0..e8a70c3 100644
--- a/dlls/windowscodecs/info.c
+++ b/dlls/windowscodecs/info.c
@@ -32,6 +32,7 @@
#include "wine/debug.h"
#include "wine/unicode.h"
+#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
@@ -531,3 +532,263 @@ HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
return hr;
}
+
+typedef struct {
+ const IEnumUnknownVtbl *IEnumUnknown_Vtbl;
+ LONG ref;
+ struct list objects;
+ struct list *cursor;
+} ComponentEnum;
+
+typedef struct {
+ struct list entry;
+ IUnknown *unk;
+} ComponentEnumItem;
+
+static const IEnumUnknownVtbl ComponentEnumVtbl;
+
+static HRESULT WINAPI ComponentEnum_QueryInterface(IEnumUnknown *iface, REFIID iid,
+ void **ppv)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IEnumUnknown, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI ComponentEnum_AddRef(IEnumUnknown *iface)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI ComponentEnum_Release(IEnumUnknown *iface)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+ ComponentEnumItem *cursor, *cursor2;
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->objects, ComponentEnumItem, entry)
+ {
+ IUnknown_Release(cursor->unk);
+ list_remove(&cursor->entry);
+ HeapFree(GetProcessHeap(), 0, cursor);
+ }
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt,
+ IUnknown **rgelt, ULONG *pceltFetched)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+ int num_fetched=0;
+ ComponentEnumItem *item;
+
+ TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
+
+ while (num_fetched<celt)
+ {
+ if (!This->cursor)
+ {
+ *pceltFetched = num_fetched;
+ return S_FALSE;
+ }
+ item = LIST_ENTRY(This->cursor, ComponentEnumItem, entry);
+ IUnknown_AddRef(item->unk);
+ rgelt[num_fetched] = item->unk;
+ num_fetched++;
+ This->cursor = list_next(&This->objects, This->cursor);
+ }
+ *pceltFetched = num_fetched;
+ return S_OK;
+}
+
+static HRESULT WINAPI ComponentEnum_Skip(IEnumUnknown *iface, ULONG celt)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+ int i;
+
+ TRACE("(%p,%u)\n", iface, celt);
+
+ for (i=0; i<celt; i++)
+ {
+ if (!This->cursor)
+ return S_FALSE;
+ This->cursor = list_next(&This->objects, This->cursor);
+ }
+ return S_OK;
+}
+
+static HRESULT WINAPI ComponentEnum_Reset(IEnumUnknown *iface)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+
+ TRACE("(%p)\n", iface);
+
+ This->cursor = list_head(&This->objects);
+ return S_OK;
+}
+
+static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+ ComponentEnum *new_enum;
+ ComponentEnumItem *old_item, *new_item;
+ HRESULT ret=S_OK;
+
+ new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
+ if (!new_enum)
+ {
+ *ppenum = NULL;
+ return E_OUTOFMEMORY;
+ }
+
+ new_enum->IEnumUnknown_Vtbl = &ComponentEnumVtbl;
+ new_enum->ref = 1;
+ new_enum->cursor = NULL;
+
+ list_init(&new_enum->objects);
+ LIST_FOR_EACH_ENTRY(old_item, &This->objects, ComponentEnumItem, entry)
+ {
+ new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
+ if (!new_item)
+ {
+ ret = E_OUTOFMEMORY;
+ break;
+ }
+ new_item->unk = old_item->unk;
+ list_add_tail(&new_enum->objects, &new_item->entry);
+ IUnknown_AddRef(new_item->unk);
+ if (&old_item->entry == This->cursor) new_enum->cursor = &new_item->entry;
+ }
+
+ if (FAILED(ret))
+ {
+ IUnknown_Release((IUnknown*)new_enum);
+ *ppenum = NULL;
+ }
+ else
+ *ppenum = (IEnumUnknown*)new_enum;
+
+ return ret;
+}
+
+static const IEnumUnknownVtbl ComponentEnumVtbl = {
+ ComponentEnum_QueryInterface,
+ ComponentEnum_AddRef,
+ ComponentEnum_Release,
+ ComponentEnum_Next,
+ ComponentEnum_Skip,
+ ComponentEnum_Reset,
+ ComponentEnum_Clone
+};
+
+HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
+{
+ ComponentEnum *This;
+ ComponentEnumItem *item;
+ const struct category *category;
+ HKEY clsidkey, catidkey, instancekey;
+ WCHAR guidstring[39];
+ LONG res;
+ int i;
+ HRESULT hr=S_OK;
+ CLSID clsid;
+
+ if (options) FIXME("ignoring flags %x\n", options);
+
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
+ if (res != ERROR_SUCCESS)
+ return HRESULT_FROM_WIN32(res);
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
+ if (!This)
+ {
+ RegCloseKey(clsidkey);
+ return E_OUTOFMEMORY;
+ }
+
+ This->IEnumUnknown_Vtbl = &ComponentEnumVtbl;
+ This->ref = 1;
+ list_init(&This->objects);
+
+ for (category=categories; category->type && hr == S_OK; category++)
+ {
+ if ((category->type & componentTypes) == 0) continue;
+ StringFromGUID2(category->catid, guidstring, 39);
+ res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
+ if (res == ERROR_SUCCESS)
+ {
+ res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
+ if (res == ERROR_SUCCESS)
+ {
+ i=0;
+ for (;;i++)
+ {
+ DWORD guidstring_size = 39;
+ res = RegEnumKeyExW(instancekey, i, guidstring, &guidstring_size, NULL, NULL, NULL, NULL);
+ if (res != ERROR_SUCCESS) break;
+
+ item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
+ if (!item) { hr = E_OUTOFMEMORY; break; }
+
+ hr = CLSIDFromString(guidstring, &clsid);
+ if (SUCCEEDED(hr))
+ {
+ hr = CreateComponentInfo(&clsid, (IWICComponentInfo**)&item->unk);
+ if (SUCCEEDED(hr))
+ list_add_tail(&This->objects, &item->entry);
+ }
+
+ if (!SUCCEEDED(hr))
+ {
+ HeapFree(GetProcessHeap(), 0, item);
+ hr = S_OK;
+ }
+ }
+ RegCloseKey(instancekey);
+ }
+ RegCloseKey(catidkey);
+ }
+ if (res != ERROR_SUCCESS && res != ERROR_NO_MORE_ITEMS)
+ hr = HRESULT_FROM_WIN32(res);
+ }
+ RegCloseKey(clsidkey);
+
+ if (SUCCEEDED(hr))
+ {
+ IEnumUnknown_Reset((IEnumUnknown*)This);
+ *ppIEnumUnknown = (IEnumUnknown*)This;
+ }
+ else
+ {
+ *ppIEnumUnknown = NULL;
+ IUnknown_Release((IUnknown*)This);
+ }
+
+ return hr;
+}
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index 9e9e9e0..6e4e752 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -29,5 +29,6 @@ extern HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer);
extern HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo);
+extern HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown);
#endif /* WINCODECS_PRIVATE_H */
More information about the wine-cvs
mailing list