[QUARTZ] Add implementation for IFilterMapper interface

Christian Costa titan.costa at wanadoo.fr
Fri Feb 27 17:04:56 CST 2004


Hi,

This patch adds implementation for the IFilterMapper interface.
However filters registered with this interface require some work in 
devenum to
be seen from application. This will be done when time permits.

Bye.

Changelog :
Implemented IFilterMapper and IEnumRegFilters interfaces.
Fixed IFilterMapper2_EnumMatchingFilters.

Christian Costa   titan.costa at wanadoo.fr

-------------- next part --------------
Index: Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/quartz/Makefile.in,v
retrieving revision 1.34
diff -u -r1.34 Makefile.in
--- Makefile.in	27 Jan 2004 00:11:16 -0000	1.34
+++ Makefile.in	27 Feb 2004 21:46:19 -0000
@@ -12,6 +12,7 @@
 	enummedia.c \
 	enummoniker.c \
 	enumpins.c \
+	enumregfilters.c \
 	filesource.c \
 	filtergraph.c \
 	filtermapper.c \
Index: filtermapper.c
===================================================================
RCS file: /home/wine/wine/dlls/quartz/filtermapper.c,v
retrieving revision 1.7
diff -u -r1.7 filtermapper.c
--- filtermapper.c	30 Dec 2003 21:52:45 -0000	1.7
+++ filtermapper.c	27 Feb 2004 21:46:22 -0000
@@ -2,6 +2,7 @@
  * IFilterMapper & IFilterMapper2 Implementations
  *
  * Copyright 2003 Robert Shearman
+ * Copyright 2004 Christian Costa
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -56,6 +57,7 @@
 
 static const WCHAR wszClsidSlash[] = {'C','L','S','I','D','\\',0};
 static const WCHAR wszSlashInstance[] = {'\\','I','n','s','t','a','n','c','e','\\',0};
+static const WCHAR wszSlash[] = {'\\',0};
 
 /* CLSID property in media category Moniker */
 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
@@ -65,6 +67,18 @@
 static const WCHAR wszMeritName[] = {'M','e','r','i','t',0};
 /* FilterData property in media category Moniker (not CLSID_ActiveMovieCategories) */
 static const WCHAR wszFilterDataName[] = {'F','i','l','t','e','r','D','a','t','a',0};
+/* For filters registered with IFilterMapper */
+static const WCHAR wszFilterSlash[] = {'F','i','l','t','e','r','\\',0};
+static const WCHAR wszFilter[] = {'F','i','l','t','e','r',0};
+/* For pins registered with IFilterMapper */
+static const WCHAR wszPins[] = {'P','i','n','s',0};
+static const WCHAR wszAllowedMany[] = {'A','l','l','o','w','e','d','M','a','n','y',0};
+static const WCHAR wszAllowedZero[] = {'A','l','l','o','w','e','d','Z','e','r','o',0};
+static const WCHAR wszDirection[] = {'D','i','r','e','c','t','i','o','n',0};
+static const WCHAR wszIsRendered[] = {'I','s','R','e','n','d','e','r','e','d',0};
+/* For types registered with IFilterMapper */
+static const WCHAR wszTypes[] = {'T','y','p','e','s',0};
+
 
 /* registry format for REGFILTER2 */
 struct REG_RF
@@ -197,7 +211,7 @@
 {
     ICOM_THIS(FilterMapper2Impl, iface);
 
-    TRACE("()\n");
+    TRACE("(%p)->()\n", iface);
 
     return InterlockedIncrement(&This->refCount);
 }
@@ -206,7 +220,7 @@
 {
     ICOM_THIS(FilterMapper2Impl, iface);
 
-    TRACE("()\n");
+    TRACE("(%p)->()\n", iface);
 
     if (InterlockedDecrement(&This->refCount) == 0)
     {
@@ -879,7 +893,7 @@
             if (SUCCEEDED(hrSub))
                 hrSub = ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum, &clsidCat, &pEnum, 0);
 
-            if (SUCCEEDED(hrSub))
+            if (SUCCEEDED(hrSub) && (hrSub == S_OK))
             {
                 while (IEnumMoniker_Next(pEnum, 1, &pMoniker, NULL) == S_OK)
                 {
@@ -941,7 +955,6 @@
         IMoniker_Release(pMonikerCat);
     }
 
-
     if (SUCCEEDED(hr))
     {
         IMoniker ** ppMoniker;
@@ -1024,20 +1037,179 @@
     CLSID clsOutMaj,
     CLSID clsOutSub)
 {
-    FIXME("stub\n");
-    return E_NOTIMPL;
+    ICOM_THIS_From_IFilterMapper(FilterMapper2Impl, iface);
+    GUID InputType[2];
+    GUID OutputType[2];
+    IEnumMoniker* ppEnumMoniker;
+    IMoniker* IMon;
+    ULONG nb;
+    ULONG idx = 0, nb_mon = 0;
+    REGFILTER* regfilters;
+    HRESULT hr;
+
+    TRACE("(%p/%p)->(%p, %lx, %s, %s, %s, %s, %s, %s, %s) stub!\n",
+        iface,This,
+        ppEnum,
+        dwMerit,
+        bInputNeeded ? "true" : "false",
+        debugstr_guid(&clsInMaj),
+        debugstr_guid(&clsInSub),
+        bRender ? "true" : "false",
+        bOutputNeeded ? "true" : "false",
+        debugstr_guid(&clsOutMaj),
+        debugstr_guid(&clsOutSub));
+
+    InputType[0] = clsInMaj;
+    InputType[1] = clsInSub;
+    OutputType[0] = clsOutMaj;
+    OutputType[1] = clsOutSub;
+
+    hr = IFilterMapper2_EnumMatchingFilters((IFilterMapper2*)This,
+                                       &ppEnumMoniker,
+                                       0,
+                                       TRUE,
+                                       dwMerit,
+                                       bInputNeeded,
+                                       1,
+                                       InputType,
+                                       NULL,
+                                       &GUID_NULL,
+                                       bRender,
+                                       bOutputNeeded,
+                                       1,
+                                       OutputType,
+                                       NULL,
+                                       &GUID_NULL);
+
+    if (!SUCCEEDED(hr))
+	return hr;
+    
+    while(IEnumMoniker_Next(ppEnumMoniker, 1, &IMon, &nb) == S_OK) {
+	IMoniker_Release(IMon);
+	nb_mon++;
+    }
+
+    *ppEnum = NULL;
+    if (!nb_mon) {
+	IEnumMoniker_Release(ppEnumMoniker);
+	return IEnumRegFiltersImpl_Create(NULL, 0, ppEnum);
+    }
+
+    regfilters = CoTaskMemAlloc(nb_mon * sizeof(REGFILTER));
+    if (!regfilters) {
+	IEnumMoniker_Release(ppEnumMoniker);
+	return E_OUTOFMEMORY;
+    }
+    
+    IEnumMoniker_Reset(ppEnumMoniker);
+    while(IEnumMoniker_Next(ppEnumMoniker, 1, &IMon, &nb) == S_OK)
+    {
+        IPropertyBag * pPropBagCat = NULL;
+        VARIANT var;
+        HRESULT hrSub;
+	GUID clsid;
+	int len;
+
+        VariantInit(&var);
+	V_VT(&var) = VT_BSTR;
+
+        hrSub = IMoniker_BindToStorage(IMon, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
+
+	if (SUCCEEDED(hrSub))
+            hrSub = IPropertyBag_Read(pPropBagCat, wszClsidName, &var, NULL);
+
+        if (SUCCEEDED(hrSub))
+	{
+	    CLSIDFromString(V_UNION(&var, bstrVal), &clsid);
+	}
+
+        if (SUCCEEDED(hrSub))
+            hrSub = IPropertyBag_Read(pPropBagCat, wszFriendlyName, &var, NULL);
+
+        if (SUCCEEDED(hrSub))
+	{
+	    len = (strlenW((WCHAR*)&V_UNION(&var, bstrVal))+1) * sizeof(WCHAR);
+	    if (!(regfilters[idx].Name = CoTaskMemAlloc(len*2)))
+		hr = E_OUTOFMEMORY;
+	}
+
+        if (SUCCEEDED(hrSub))
+	{
+	    memcpy(regfilters[idx].Name, &V_UNION(&var, bstrVal), len);
+	    regfilters[idx].Clsid = clsid;
+	    idx++;
+	}
+	
+	if (pPropBagCat)
+	    IPropertyBag_Release(pPropBagCat);
+	IMoniker_Release(IMon);
+    }
+
+    /* In case of release all resources */
+    if (!SUCCEEDED(hr)) {
+	for (idx = 0; idx < nb_mon; idx++)
+	    CoTaskMemFree(regfilters[idx].Name);
+    	CoTaskMemFree(regfilters);
+	IEnumMoniker_Release(ppEnumMoniker);
+	return hr;
+    }
+		
+    hr = IEnumRegFiltersImpl_Create(regfilters, nb_mon, ppEnum);
+    CoTaskMemFree(regfilters);
+    IEnumMoniker_Release(ppEnumMoniker);
+    
+    return hr;
 }
 
 
 static HRESULT WINAPI FilterMapper_RegisterFilter(IFilterMapper * iface, CLSID clsid, LPCWSTR szName, DWORD dwMerit)
 {
-    FIXME("stub\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    LPWSTR wszClsid = NULL;
+    HKEY hKey;
+    WCHAR wszKeyName[strlenW(wszFilterSlash) + (CHARS_IN_GUID-1) + 1];
+	
+    TRACE("(%p)->(%s, %s, %lx)\n", iface, debugstr_guid(&clsid), debugstr_w(szName), dwMerit);
+
+    hr = StringFromCLSID(&clsid, &wszClsid);
+
+    if (SUCCEEDED(hr))
+    {
+	strcpyW(wszKeyName, wszFilterSlash);
+    	strcatW(wszKeyName, wszClsid);
+    
+	hr = HRESULT_FROM_WIN32(RegCreateKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL));
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        hr = HRESULT_FROM_WIN32(RegSetValueExW(hKey, NULL, 0, REG_SZ, (LPBYTE)szName, strlenW(szName) + 1));
+	CloseHandle(hKey);
+    }
+
+    if (SUCCEEDED(hr))
+    {
+	strcpyW(wszKeyName, wszClsidSlash);
+    	strcatW(wszKeyName, wszClsid);
+    
+	hr = HRESULT_FROM_WIN32(RegCreateKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL));
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        hr = HRESULT_FROM_WIN32(RegSetValueExW(hKey, wszMeritName, 0, REG_DWORD, (LPBYTE)&dwMerit, sizeof(dwMerit)));
+	CloseHandle(hKey);
+    }
+    
+    return hr;
 }
 
 static HRESULT WINAPI FilterMapper_RegisterFilterInstance(IFilterMapper * iface, CLSID clsid, LPCWSTR szName, CLSID *MRId)
 {
-    FIXME("stub\n");
+    TRACE("(%p)->(%s, %s, %p)\n", iface, debugstr_guid(&clsid), debugstr_w(szName), MRId);
+
+    /* Not implemented in Windows (tested on Win2k) */
+
     return E_NOTIMPL;
 }
 
@@ -1052,8 +1224,76 @@
     CLSID ConnectsToFilter,
     LPCWSTR ConnectsToPin)
 {
-    FIXME("stub\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    LPWSTR wszClsid = NULL;
+    HKEY hKey = NULL;
+    HKEY hPinsKey = NULL;
+    WCHAR * wszPinsKeyName;
+    WCHAR wszKeyName[strlenW(wszClsidSlash) + (CHARS_IN_GUID-1) + 1];
+
+    TRACE("(%p)->(%s, %s, %d, %d, %d, %d, %s, %s)\n", iface, debugstr_guid(&Filter), debugstr_w(szName), bRendered,
+		bOutput, bZero, bMany, debugstr_guid(&ConnectsToFilter), debugstr_w(ConnectsToPin));
+
+    hr = StringFromCLSID(&Filter, &wszClsid);
+
+    if (SUCCEEDED(hr))
+    {
+	strcpyW(wszKeyName, wszClsidSlash);
+    	strcatW(wszKeyName, wszClsid);
+
+	hr = HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, KEY_WRITE, &hKey));
+    }
+
+    if (SUCCEEDED(hr))
+    {
+	wszPinsKeyName = CoTaskMemAlloc((strlenW(wszPins) + 1 + strlenW(szName) + 1) * 2);
+	if (!wszPinsKeyName)
+	    hr = E_OUTOFMEMORY;
+    }
+
+    if (SUCCEEDED(hr))
+    {
+	strcpyW(wszPinsKeyName, wszPins);
+    	strcatW(wszPinsKeyName, wszSlash);
+    	strcatW(wszPinsKeyName, szName);
+    
+	hr = HRESULT_FROM_WIN32(RegCreateKeyExW(hKey, wszPinsKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hPinsKey, NULL));
+	CoTaskMemFree(wszPinsKeyName);
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        hr = HRESULT_FROM_WIN32(RegSetValueExW(hPinsKey, wszAllowedMany, 0, REG_DWORD, (LPBYTE)&bMany, sizeof(bMany)));
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        hr = HRESULT_FROM_WIN32(RegSetValueExW(hPinsKey, wszAllowedZero, 0, REG_DWORD, (LPBYTE)&bZero, sizeof(bZero)));
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        hr = HRESULT_FROM_WIN32(RegSetValueExW(hPinsKey, wszDirection, 0, REG_DWORD, (LPBYTE)&bOutput, sizeof(bOutput)));
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        hr = HRESULT_FROM_WIN32(RegSetValueExW(hPinsKey, wszIsRendered, 0, REG_DWORD, (LPBYTE)&bRendered, sizeof(bRendered)));
+    }
+
+    if (SUCCEEDED(hr))
+    {
+	hr = HRESULT_FROM_WIN32(RegCreateKeyExW(hPinsKey, wszTypes, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, NULL, NULL));
+    }
+
+    if (wszClsid)
+	CoTaskMemFree(wszClsid);
+    if (hKey)
+	CloseHandle(hKey);
+    if (hPinsKey)
+	CloseHandle(hPinsKey);
+
+    return hr;
 }
 
 
@@ -1064,26 +1304,169 @@
     CLSID clsMajorType,
     CLSID clsSubType)
 {
-    FIXME("stub\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    LPWSTR wszClsid = NULL;
+    LPWSTR wszClsidMajorType = NULL;
+    LPWSTR wszClsidSubType = NULL;
+    HKEY hKey = NULL;
+    WCHAR * wszTypesKey;
+    WCHAR wszKeyName[strlenW(wszClsidSlash) + (CHARS_IN_GUID-1) + 1];
+
+    TRACE("(%p)->(%s, %s, %s, %s)\n", iface, debugstr_guid(&clsFilter), debugstr_w(szName), debugstr_guid(&clsMajorType),
+		debugstr_guid(&clsSubType));
+
+    hr = StringFromCLSID(&clsFilter, &wszClsid);
+
+    if (SUCCEEDED(hr))
+    {
+	hr = StringFromCLSID(&clsMajorType, &wszClsidMajorType);
+    }
+
+    if (SUCCEEDED(hr))
+    {
+	hr = StringFromCLSID(&clsSubType, &wszClsidSubType);
+    }
+
+    if (SUCCEEDED(hr))
+    {
+	wszTypesKey = CoTaskMemAlloc((strlenW(wszClsidSlash) + strlenW(wszClsid) + strlenW(wszPins) +
+			strlenW(szName) + strlenW(wszTypes) + 3 + 1) * 2);
+	if (!wszTypesKey)
+	    hr = E_OUTOFMEMORY;
+    }
+
+    if (SUCCEEDED(hr))
+    {
+	strcpyW(wszTypesKey, wszClsidSlash);
+    	strcatW(wszTypesKey, wszClsid);
+    	strcatW(wszTypesKey, wszSlash);
+    	strcatW(wszTypesKey, wszPins);
+    	strcatW(wszTypesKey, wszSlash);
+    	strcatW(wszTypesKey, szName);
+    	strcatW(wszTypesKey, wszSlash);
+    	strcatW(wszTypesKey, wszTypes);
+
+	hr = HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_CLASSES_ROOT, wszTypesKey, 0, KEY_WRITE, &hKey));
+	CoTaskMemFree(wszTypesKey);
+    }
+
+    if (SUCCEEDED(hr))
+    {
+	strcpyW(wszKeyName, wszClsidMajorType);
+    	strcatW(wszKeyName, wszSlash);
+    	strcatW(wszKeyName, wszClsidSubType);
+    
+	hr = HRESULT_FROM_WIN32(RegCreateKeyExW(hKey, wszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, NULL, NULL));
+	CloseHandle(hKey);
+    }
+
+    if (wszClsid)
+	CoTaskMemFree(wszClsid);
+    if (wszClsidMajorType)
+	CoTaskMemFree(wszClsidMajorType);
+    if (wszClsidSubType)
+	CoTaskMemFree(wszClsidSubType);
+
+    return hr;
 }
 
 static HRESULT WINAPI FilterMapper_UnregisterFilter(IFilterMapper * iface, CLSID Filter)
 {
-    FIXME("stub\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    LPWSTR wszClsid = NULL;
+    HKEY hKey;
+    WCHAR wszKeyName[strlenW(wszClsidSlash) + (CHARS_IN_GUID-1) + 1];
+
+    TRACE("(%p)->(%s)\n", iface, debugstr_guid(&Filter));
+	
+    hr = StringFromCLSID(&Filter, &wszClsid);
+
+    if (SUCCEEDED(hr))
+    {
+	hr = HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_CLASSES_ROOT, wszFilter, 0, KEY_WRITE, &hKey));
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        hr = HRESULT_FROM_WIN32(RegDeleteKeyW(hKey, wszClsid));
+	CloseHandle(hKey);
+    }
+
+    if (SUCCEEDED(hr))
+    {
+	strcpyW(wszKeyName, wszClsidSlash);
+    	strcatW(wszKeyName, wszClsid);
+    
+	hr = HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, KEY_WRITE, &hKey));
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        hr = HRESULT_FROM_WIN32(RegDeleteKeyW(hKey, wszMeritName));
+	CloseHandle(hKey);
+    }
+
+    if (wszClsid)
+	CoTaskMemFree(wszClsid);
+
+    return hr;
 }
 
 static HRESULT WINAPI FilterMapper_UnregisterFilterInstance(IFilterMapper * iface, CLSID MRId)
 {
-    FIXME("stub\n");
+    TRACE("(%p)->(%s)\n", iface, debugstr_guid(&MRId));
+
+    /* Not implemented in Windows (tested on Win2k) */
+
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI FilterMapper_UnregisterPin(IFilterMapper * iface, CLSID Filter, LPCWSTR Name)
 {
-    FIXME("stub\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    LPWSTR wszClsid = NULL;
+    HKEY hKey = NULL;
+    WCHAR * wszPinNameKey;
+    WCHAR wszKeyName[strlenW(wszClsidSlash) + (CHARS_IN_GUID-1) + 1];
+
+    TRACE("(%p)->(%s, %s)\n", iface, debugstr_guid(&Filter), debugstr_w(Name));
+
+    if (!Name)
+	return E_INVALIDARG;
+    
+    hr = StringFromCLSID(&Filter, &wszClsid);
+
+    if (SUCCEEDED(hr))
+    {
+	strcpyW(wszKeyName, wszClsidSlash);
+    	strcatW(wszKeyName, wszClsid);
+
+	hr = HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, KEY_WRITE, &hKey));
+    }
+
+    if (SUCCEEDED(hr))
+    {
+	wszPinNameKey = CoTaskMemAlloc((strlenW(wszPins) + 1 + strlenW(Name) + 1) * 2);
+	if (!wszPinNameKey)
+	    hr = E_OUTOFMEMORY;
+    }
+
+    if (SUCCEEDED(hr))
+    {
+	strcpyW(wszPinNameKey, wszPins);
+	strcatW(wszPinNameKey, wszSlash);
+	strcatW(wszPinNameKey, Name);
+	
+	hr = HRESULT_FROM_WIN32(RegDeleteKeyW(hKey, wszPinNameKey));
+	CoTaskMemFree(wszPinNameKey);
+    }
+
+    if (wszClsid)
+        CoTaskMemFree(wszClsid);
+    if (hKey)
+	CloseHandle(hKey);
+    
+    return hr;
 }
 
 static ICOM_VTABLE(IFilterMapper) fmvtbl =
@@ -1103,3 +1486,4 @@
     FilterMapper_UnregisterPin,
     FilterMapper_EnumMatchingFilters
 };
+
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ enumregfilters.c	2004-02-27 22:33:59.000000000 +0000
@@ -0,0 +1,202 @@
+/*
+ * Implementation of IEnumRegFilters Interface
+ *
+ * Copyright 2004 Christian Costa
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "quartz_private.h"
+
+#include "wine/unicode.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(quartz);
+
+typedef struct IEnumRegFiltersImpl
+{
+    const IEnumRegFiltersVtbl * lpVtbl;
+    ULONG refCount;
+    ULONG size;
+    REGFILTER* RegFilters;
+    ULONG uIndex;
+} IEnumRegFiltersImpl;
+
+static const struct IEnumRegFiltersVtbl IEnumRegFiltersImpl_Vtbl;
+
+HRESULT IEnumRegFiltersImpl_Create(REGFILTER* pInRegFilters, const ULONG size, IEnumRegFilters ** ppEnum)
+{
+    IEnumRegFiltersImpl* pEnumRegFilters;
+    REGFILTER* pRegFilters = NULL;
+    int i;
+
+    TRACE("(%p, %ld, %p)\n", pInRegFilters, size, ppEnum);
+    
+    pEnumRegFilters = CoTaskMemAlloc(sizeof(IEnumRegFiltersImpl));
+    if (!pEnumRegFilters) {
+        *ppEnum = NULL;
+        return E_OUTOFMEMORY;
+    }
+
+    /* Accept size of 0 */
+    if (size) {
+	pRegFilters = CoTaskMemAlloc(sizeof(REGFILTER)*size);
+	if (!pRegFilters) {
+	    CoTaskMemFree(pEnumRegFilters);
+	    *ppEnum = NULL;
+	    return E_OUTOFMEMORY;
+	}
+    }
+    
+    for(i = 0; i < size; i++) {
+	pRegFilters[i].Clsid = pInRegFilters[i].Clsid;
+	pRegFilters[i].Name = (WCHAR*)CoTaskMemAlloc((strlenW(pInRegFilters[i].Name)+1)*sizeof(WCHAR));
+	if (!pRegFilters[i].Name) {
+	    while(i)
+		CoTaskMemFree(pRegFilters[--i].Name);
+	    CoTaskMemFree(pRegFilters);
+	    CoTaskMemFree(pEnumRegFilters);
+	    return E_OUTOFMEMORY;
+	}
+	CopyMemory(pRegFilters[i].Name, pInRegFilters[i].Name, (strlenW(pInRegFilters[i].Name)+1)*sizeof(WCHAR));
+    }
+
+    pEnumRegFilters->lpVtbl = &IEnumRegFiltersImpl_Vtbl;
+    pEnumRegFilters->refCount = 1;
+    pEnumRegFilters->uIndex = 0;
+    pEnumRegFilters->RegFilters = pRegFilters;
+    pEnumRegFilters->size = size;
+
+    *ppEnum = (IEnumRegFilters *)(&pEnumRegFilters->lpVtbl);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI IEnumRegFiltersImpl_QueryInterface(IEnumRegFilters * iface, REFIID riid, LPVOID * ppv)
+{
+    TRACE("(%p)->(%s, %p)\n", iface, qzdebugstr_guid(riid), ppv);
+
+    *ppv = NULL;
+
+    if (IsEqualIID(riid, &IID_IUnknown))
+        *ppv = (LPVOID)iface;
+    else if (IsEqualIID(riid, &IID_IEnumRegFilters))
+        *ppv = (LPVOID)iface;
+
+    if (*ppv) {
+        IUnknown_AddRef((IUnknown *)(*ppv));
+        return S_OK;
+    }
+
+    FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI IEnumRegFiltersImpl_AddRef(IEnumRegFilters * iface)
+{
+    ICOM_THIS(IEnumRegFiltersImpl, iface);
+
+    TRACE("(%p)\n", iface);
+
+    return ++This->refCount;
+}
+
+static ULONG WINAPI IEnumRegFiltersImpl_Release(IEnumRegFilters * iface)
+{
+    ICOM_THIS(IEnumRegFiltersImpl, iface);
+
+    TRACE("(%p)\n", iface);
+    
+    if (!--This->refCount) {
+        CoTaskMemFree(This);
+        return 0;
+    } else
+        return This->refCount;
+}
+
+static HRESULT WINAPI IEnumRegFiltersImpl_Next(IEnumRegFilters * iface, ULONG cFilters, REGFILTER ** ppRegFilter, ULONG * pcFetched)
+{
+    ULONG cFetched; 
+    ICOM_THIS(IEnumRegFiltersImpl, iface);
+    int i;
+
+    cFetched = min(This->size, This->uIndex + cFilters) - This->uIndex;
+
+    TRACE("(%p)->(%lu, %p, %p)\n", iface, cFilters, ppRegFilter, pcFetched);
+
+    if (cFetched > 0)
+    {
+	for(i = 0; i < cFetched; i++) {
+	    /* The string in the REGFILTER structure must be allocated in the same block as the REGFILTER structure itself */
+            ppRegFilter[i] = (REGFILTER*)CoTaskMemAlloc(sizeof(REGFILTER)+(strlenW(This->RegFilters[i].Name)+1)*sizeof(WCHAR));
+	    if (!ppRegFilter[i]) {
+		while(i) {
+		    CoTaskMemFree(ppRegFilter[--i]);
+		    ppRegFilter[i] = NULL;
+		}
+		return E_OUTOFMEMORY;
+	    }
+	    ppRegFilter[i]->Clsid = This->RegFilters[i].Clsid;
+	    ppRegFilter[i]->Name = (WCHAR*)((char*)ppRegFilter[i]+sizeof(REGFILTER));
+	    CopyMemory(ppRegFilter[i]->Name, This->RegFilters[i].Name, (strlenW(This->RegFilters[i].Name)+1)*sizeof(WCHAR));
+	}
+
+	This->uIndex += cFetched;
+	if (pcFetched)
+	    *pcFetched = cFetched;
+	return S_OK;
+    }
+
+    return S_FALSE;
+}
+
+static HRESULT WINAPI IEnumRegFiltersImpl_Skip(IEnumRegFilters * iface, ULONG n)
+{
+    TRACE("(%p)->(%lu)\n", iface, n);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IEnumRegFiltersImpl_Reset(IEnumRegFilters * iface)
+{
+    ICOM_THIS(IEnumRegFiltersImpl, iface);
+
+    TRACE("(%p)\n", iface);
+
+    This->uIndex = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI IEnumRegFiltersImpl_Clone(IEnumRegFilters * iface, IEnumRegFilters ** ppEnum)
+{
+    TRACE("(%p)->(%p)\n", iface, ppEnum);
+
+    return E_NOTIMPL;
+}
+
+static const IEnumRegFiltersVtbl IEnumRegFiltersImpl_Vtbl =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IEnumRegFiltersImpl_QueryInterface,
+    IEnumRegFiltersImpl_AddRef,
+    IEnumRegFiltersImpl_Release,
+    IEnumRegFiltersImpl_Next,
+    IEnumRegFiltersImpl_Skip,
+    IEnumRegFiltersImpl_Reset,
+    IEnumRegFiltersImpl_Clone
+};
+


More information about the wine-patches mailing list