Hi, This patch is the implementation of IFilterMapper2 which will form the basis for the IGraphBuilder interface. Naturally, it depends on DSHOW-01, the big header patch. Changelog: - Implement IFilterMapper2 Rob
diff -u -N -r -x *~ -x .#* -x CVS wine/dlls/quartz01/Makefile.in wine/dlls/quartz/Makefile.in --- wine/dlls/quartz01/Makefile.in Tue Jun 24 14:26:20 2003 +++ wine/dlls/quartz/Makefile.in Sun Jun 29 16:25:44 2003 @@ -3,14 +3,16 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = quartz.dll -IMPORTS = kernel32 +IMPORTS = kernel32 ole32 oleaut32 advapi32 EXTRALIBS = $(LIBUUID) LDDLLFLAGS = @LDDLLFLAGS@ SYMBOLFILE = $(MODULE).tmp.o C_SRCS = \ + enummoniker.c \ filtergraph.c \ + filtermapper.c \ main.c @MAKE_DLL_RULES@ diff -u -N -r -x *~ -x .#* -x CVS wine/dlls/quartz01/enummoniker.c wine/dlls/quartz/enummoniker.c --- wine/dlls/quartz01/enummoniker.c Thu Jan 1 01:00:00 1970 +++ wine/dlls/quartz/enummoniker.c Sun Jun 29 18:07:27 2003 @@ -0,0 +1,195 @@ +/* + * IEnumMoniker implementation + * + * Copyright 2003 Robert Shearman + * + * This file contains the (internal) driver registration functions, + * driver enumeration APIs and DirectDraw creation functions. + * + * 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 + */ + +#define COM_NO_WINDOWS_H +#include "ole2.h" +#include "strmif.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(quartz); + +typedef struct EnumMonikerImpl +{ + ICOM_VFIELD(IEnumMoniker); + ULONG ref; + IMoniker ** ppMoniker; + ULONG nMonikerCount; + ULONG index; +} EnumMonikerImpl; + +static struct ICOM_VTABLE(IEnumMoniker) EnumMonikerImpl_Vtbl; + +static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface); + +HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum) +{ + /* NOTE: assumes that array of IMonikers has already been AddRef'd + * I.e. this function does not AddRef the array of incoming + * IMonikers */ + EnumMonikerImpl * pemi = CoTaskMemAlloc(sizeof(EnumMonikerImpl)); + + TRACE("(%p, %ld, %p)\n", ppMoniker, nMonikerCount, ppEnum); + + *ppEnum = NULL; + + if (!pemi) + return E_OUTOFMEMORY; + + pemi->lpVtbl = &EnumMonikerImpl_Vtbl; + pemi->ref = 1; + pemi->ppMoniker = CoTaskMemAlloc(nMonikerCount * sizeof(IMoniker*)); + memcpy(pemi->ppMoniker, ppMoniker, nMonikerCount*sizeof(IMoniker*)); + pemi->nMonikerCount = nMonikerCount; + pemi->index = 0; + + *ppEnum = (IEnumMoniker *)pemi; + + return S_OK; +} + +/********************************************************************** + * IEnumMoniker_QueryInterface (also IUnknown) + */ +static HRESULT WINAPI EnumMonikerImpl_QueryInterface( + LPENUMMONIKER iface, + REFIID riid, + LPVOID *ppvObj) +{ + ICOM_THIS(EnumMonikerImpl, 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_IEnumMoniker)) + { + *ppvObj = (LPVOID)iface; + EnumMonikerImpl_AddRef(iface); + return S_OK; + } + + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +/********************************************************************** + * IEnumMoniker_AddRef (also IUnknown) + */ +static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface) +{ + ICOM_THIS(EnumMonikerImpl, iface); + + TRACE("\n"); + + if (This == NULL) return E_POINTER; + + return InterlockedIncrement(&This->ref); +} + +/********************************************************************** + * IEnumMoniker_Release (also IUnknown) + */ +static ULONG WINAPI EnumMonikerImpl_Release(LPENUMMONIKER iface) +{ + ICOM_THIS(EnumMonikerImpl, iface); + + TRACE("\n"); + + if (!InterlockedDecrement(&This->ref)) + { + CoTaskMemFree(This->ppMoniker); + This->ppMoniker = NULL; + CoTaskMemFree(This); + return 0; + } + return This->ref; +} + +static HRESULT WINAPI EnumMonikerImpl_Next(LPENUMMONIKER iface, ULONG celt, IMoniker ** rgelt, ULONG * pceltFetched) +{ + ULONG fetched; + ICOM_THIS(EnumMonikerImpl, iface); + + TRACE("(%ld, %p, %p)\n", celt, rgelt, pceltFetched); + + for (fetched = 0; (This->index + fetched < This->nMonikerCount) && (fetched < celt); fetched++) + { + rgelt[fetched] = This->ppMoniker[This->index + fetched]; + IMoniker_AddRef(rgelt[fetched]); + } + + This->index += fetched; + + if (pceltFetched) + *pceltFetched = fetched; + + if (fetched != celt) + return S_FALSE; + else + return S_OK; +} + +static HRESULT WINAPI EnumMonikerImpl_Skip(LPENUMMONIKER iface, ULONG celt) +{ + ICOM_THIS(EnumMonikerImpl, iface); + + TRACE("(%ld)\n", celt); + + This->index += celt; + + return S_OK; +} + +static HRESULT WINAPI EnumMonikerImpl_Reset(LPENUMMONIKER iface) +{ + ICOM_THIS(EnumMonikerImpl, iface); + + TRACE("()\n"); + + This->index = 0; + + return S_OK; +} + +static HRESULT WINAPI EnumMonikerImpl_Clone(LPENUMMONIKER iface, IEnumMoniker ** ppenum) +{ + FIXME("(%p): stub\n", ppenum); + + return E_NOTIMPL; +} + +/********************************************************************** + * IEnumMoniker_Vtbl + */ +static ICOM_VTABLE(IEnumMoniker) EnumMonikerImpl_Vtbl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + EnumMonikerImpl_QueryInterface, + EnumMonikerImpl_AddRef, + EnumMonikerImpl_Release, + EnumMonikerImpl_Next, + EnumMonikerImpl_Skip, + EnumMonikerImpl_Reset, + EnumMonikerImpl_Clone +}; diff -u -N -r -x *~ -x .#* -x CVS wine/dlls/quartz01/filtergraph.c wine/dlls/quartz/filtergraph.c --- wine/dlls/quartz01/filtergraph.c Tue Jun 24 14:26:20 2003 +++ wine/dlls/quartz/filtergraph.c Fri Jun 27 00:02:42 2003 @@ -28,6 +28,18 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); +typedef struct _IFilterGraphImpl { + ICOM_VTABLE(IGraphBuilder) *IGraphBuilder_vtbl; + ICOM_VTABLE(IMediaControl) *IMediaControl_vtbl; + ICOM_VTABLE(IMediaSeeking) *IMediaSeeking_vtbl; + ICOM_VTABLE(IBasicAudio) *IBasicAudio_vtbl; + ICOM_VTABLE(IBasicVideo) *IBasicVideo_vtbl; + ICOM_VTABLE(IVideoWindow) *IVideoWindow_vtbl; + ICOM_VTABLE(IMediaEventEx) *IMediaEventEx_vtbl; + ULONG ref; +} IFilterGraphImpl; + + static HRESULT Filtergraph_QueryInterface(IFilterGraphImpl *This, REFIID riid, LPVOID *ppvObj) { diff -u -N -r -x *~ -x .#* -x CVS wine/dlls/quartz01/filtermapper.c wine/dlls/quartz/filtermapper.c --- wine/dlls/quartz01/filtermapper.c Thu Jan 1 01:00:00 1970 +++ wine/dlls/quartz/filtermapper.c Mon Jun 30 00:09:20 2003 @@ -0,0 +1,1105 @@ +/* + * IFilterMapper & IFilterMapper2 Implementations + * + * Copyright 2003 Robert Shearman + * + * This file contains the (internal) driver registration functions, + * driver enumeration APIs and DirectDraw creation functions. + * + * 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 "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "winerror.h" + +#include "quartz_private.h" + +#define COM_NO_WINDOWS_H +#include "ole2.h" +#include "strmif.h" +#include "wine/obj_property.h" +#include "wine/unicode.h" +#include "uuids.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(quartz); + +typedef struct FilterMapper2Impl +{ + ICOM_VFIELD(IFilterMapper2); + ICOM_VTABLE(IFilterMapper) * lpVtblFilterMapper; + ULONG refCount; +} FilterMapper2Impl; + +static struct ICOM_VTABLE(IFilterMapper2) fm2vtbl; +static struct ICOM_VTABLE(IFilterMapper) fmvtbl; + +#define _IFilterMapper_Offset ((int)(&(((FilterMapper2Impl*)0)->lpVtblFilterMapper))) +#define ICOM_THIS_From_IFilterMapper(impl, iface) impl* This = (impl*)(((char*)iface)-_IFilterMapper_Offset) + +static const WCHAR wszClsidSlash[] = {'C','L','S','I','D','\\',0}; +static const WCHAR wszSlashInstance[] = {'\\','I','n','s','t','a','n','c','e','\\',0}; + +/* CLSID property in media category Moniker */ +static const WCHAR wszClsidName[] = {'C','L','S','I','D',0}; +/* FriendlyName property in media category Moniker */ +static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; +/* Merit property in media category Moniker (CLSID_ActiveMovieCategories only) */ +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}; + +/* registry format for REGFILTER2 */ +struct REG_RF +{ + DWORD dwVersion; + DWORD dwMerit; + DWORD dwPins; + DWORD dwUnused; +}; + +struct REG_RFP +{ + BYTE signature[4]; /* e.g. "0pi3" */ + DWORD dwFlags; + DWORD dwInstances; + DWORD dwMediaTypes; + DWORD dwMediums; + DWORD bCategory; /* is there a category clsid? */ + /* optional: dwOffsetCategoryClsid */ +}; + +struct REG_TYPE +{ + BYTE signature[4]; /* e.g. "0ty3" */ + DWORD dwUnused; + DWORD dwOffsetMajor; + DWORD dwOffsetMinor; +}; + +struct MONIKER_MERIT +{ + IMoniker * pMoniker; + DWORD dwMerit; +}; + +struct Vector +{ + LPBYTE pData; + int capacity; /* in bytes */ + int current; /* pointer to next free byte */ +}; + +/* returns the position it was added at */ +static int add_data(struct Vector * v, const BYTE * pData, int size) +{ + int index = v->current; + if (v->current + size > v->capacity) + { + LPBYTE pOldData = v->pData; + v->capacity = (v->capacity + size) * 2; + v->pData = CoTaskMemAlloc(v->capacity); + memcpy(v->pData, pOldData, v->current); + CoTaskMemFree(pOldData); + } + memcpy(v->pData + v->current, pData, size); + v->current += size; + return index; +} + +static int find_data(struct Vector * v, const BYTE * pData, int size) +{ + int index; + for (index = 0; index < v->current; index++) + if (!memcmp(v->pData + index, pData, size)) + return index; + /* not found */ + return -1; +} + +static void delete_vector(struct Vector * v) +{ + if (v->pData) + CoTaskMemFree(v->pData); + v->current = 0; + v->capacity = 0; +} + +HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj) +{ + FilterMapper2Impl * pFM2impl; + + TRACE("(%p, %p)\n", pUnkOuter, ppObj); + + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + + pFM2impl = CoTaskMemAlloc(sizeof(*pFM2impl)); + if (!pFM2impl) + return E_OUTOFMEMORY; + + pFM2impl->lpVtbl = &fm2vtbl; + pFM2impl->lpVtblFilterMapper = &fmvtbl; + pFM2impl->refCount = 1; + + *ppObj = pFM2impl; + + TRACE("-- created at %p\n", pFM2impl); + + return S_OK; +} + +/*** IUnknown methods ***/ + +static HRESULT WINAPI FilterMapper2_QueryInterface(IFilterMapper2 * iface, REFIID riid, LPVOID *ppv) +{ + ICOM_THIS(FilterMapper2Impl, iface); + + TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv); + + *ppv = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) + *ppv = iface; + else if (IsEqualIID(riid, &IID_IFilterMapper2)) + *ppv = iface; + else if (IsEqualIID(riid, &IID_IFilterMapper)) + *ppv = &This->lpVtblFilterMapper; + + if (*ppv != NULL) + { + IUnknown_AddRef((IUnknown *)*ppv); + return S_OK; + } + + FIXME("No interface for %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI FilterMapper2_AddRef(IFilterMapper2 * iface) +{ + ICOM_THIS(FilterMapper2Impl, iface); + + TRACE("()\n"); + + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI FilterMapper2_Release(IFilterMapper2 * iface) +{ + ICOM_THIS(FilterMapper2Impl, iface); + + TRACE("()\n"); + + if (InterlockedDecrement(&This->refCount) == 0) + { + CoTaskMemFree(This); + return 0; + } + return This->refCount; +} + +/*** IFilterMapper2 methods ***/ + +static HRESULT WINAPI FilterMapper2_CreateCategory( + IFilterMapper2 * iface, + REFCLSID clsidCategory, + DWORD dwCategoryMerit, + LPCWSTR szDescription) +{ + LPWSTR wClsidAMCat = NULL; + LPWSTR wClsidCategory = NULL; + WCHAR wszKeyName[strlenW(wszClsidSlash) + strlenW(wszSlashInstance) + (CHARS_IN_GUID-1) * 2 + 1]; + HKEY hKey = NULL; + HRESULT hr; + + TRACE("(%s, %lx, %s)\n", debugstr_guid(clsidCategory), dwCategoryMerit, debugstr_w(szDescription)); + + hr = StringFromCLSID(&CLSID_ActiveMovieCategories, &wClsidAMCat); + + if (SUCCEEDED(hr)) + { + hr = StringFromCLSID(clsidCategory, &wClsidCategory); + } + + if (SUCCEEDED(hr)) + { + strcpyW(wszKeyName, wszClsidSlash); + strcatW(wszKeyName, wClsidAMCat); + strcatW(wszKeyName, wszSlashInstance); + strcatW(wszKeyName, wClsidCategory); + + 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, wszFriendlyName, 0, REG_SZ, (LPBYTE)szDescription, strlenW(szDescription) + 1)); + } + + if (SUCCEEDED(hr)) + { + hr = HRESULT_FROM_WIN32(RegSetValueExW(hKey, wszClsidName, 0, REG_SZ, (LPBYTE)wClsidCategory, strlenW(wClsidCategory) + 1)); + } + + if (SUCCEEDED(hr)) + { + hr = HRESULT_FROM_WIN32(RegSetValueExW(hKey, wszMeritName, 0, REG_DWORD, (LPBYTE)&dwCategoryMerit, sizeof(dwCategoryMerit))); + } + + CloseHandle(hKey); + + if (wClsidCategory) + CoTaskMemFree(wClsidCategory); + if (wClsidAMCat) + CoTaskMemFree(wClsidAMCat); + + return hr; +} + +static HRESULT WINAPI FilterMapper2_UnregisterFilter( + IFilterMapper2 * iface, + const CLSID *pclsidCategory, + const OLECHAR *szInstance, + REFCLSID Filter) +{ + WCHAR wszKeyName[MAX_PATH]; + LPWSTR wClsidCategory = NULL; + LPWSTR wFilter = NULL; + HRESULT hr; + + TRACE("(%p, %s, %s)\n", pclsidCategory, debugstr_w(szInstance), debugstr_guid(Filter)); + + if (!pclsidCategory) + pclsidCategory = &CLSID_LegacyAmFilterCategory; + + hr = StringFromCLSID(pclsidCategory, &wClsidCategory); + + if (SUCCEEDED(hr)) + { + strcpyW(wszKeyName, wszClsidSlash); + strcatW(wszKeyName, wClsidCategory); + strcatW(wszKeyName, wszSlashInstance); + if (szInstance) + strcatW(wszKeyName, szInstance); + else + { + hr = StringFromCLSID(Filter, &wFilter); + if (SUCCEEDED(hr)) + strcatW(wszKeyName, wFilter); + } + } + + if (SUCCEEDED(hr)) + { + hr = HRESULT_FROM_WIN32(RegDeleteKeyW(HKEY_CLASSES_ROOT, wszKeyName)); + } + + if (wClsidCategory) + CoTaskMemFree(wClsidCategory); + if (wFilter) + CoTaskMemFree(wFilter); + + return hr; +} + +static HRESULT FM2_WriteFriendlyName(IPropertyBag * pPropBag, LPCWSTR szName) +{ + VARIANT var; + + V_VT(&var) = VT_BSTR; + V_UNION(&var, bstrVal) = (BSTR)szName; + + return IPropertyBag_Write(pPropBag, wszFriendlyName, &var); +} + +static HRESULT FM2_WriteClsid(IPropertyBag * pPropBag, REFCLSID clsid) +{ + LPWSTR wszClsid = NULL; + VARIANT var; + HRESULT hr; + + hr = StringFromCLSID(clsid, &wszClsid); + + if (SUCCEEDED(hr)) + { + V_VT(&var) = VT_BSTR; + V_UNION(&var, bstrVal) = wszClsid; + hr = IPropertyBag_Write(pPropBag, wszClsidName, &var); + } + if (wszClsid) + CoTaskMemFree(wszClsid); + return hr; +} + +static HRESULT FM2_WriteFilterData(IPropertyBag * pPropBag, const REGFILTER2 * prf2) +{ + VARIANT var; + int size = sizeof(struct REG_RF); + int i; + struct Vector mainStore = {NULL, 0, 0}; + struct Vector clsidStore = {NULL, 0, 0}; + struct REG_RF rrf; + SAFEARRAY * psa; + SAFEARRAYBOUND saBound; + HRESULT hr = S_OK; + + rrf.dwVersion = prf2->dwVersion; + rrf.dwMerit = prf2->dwMerit; + rrf.dwPins = prf2->u.s1.cPins2; + rrf.dwUnused = 0; + + add_data(&mainStore, (LPBYTE)&rrf, sizeof(rrf)); + + for (i = 0; i < prf2->u.s1.cPins2; i++) + { + size += sizeof(struct REG_RFP); + if (prf2->u.s1.rgPins2[i].clsPinCategory) + size += sizeof(DWORD); + size += prf2->u.s1.rgPins2[i].nMediaTypes * sizeof(struct REG_TYPE); + size += prf2->u.s1.rgPins2[i].nMediums * sizeof(DWORD); + } + + for (i = 0; i < prf2->u.s1.cPins2; i++) + { + struct REG_RFP rrfp; + REGFILTERPINS2 rgPin2 = prf2->u.s1.rgPins2[i]; + int j; + + rrfp.signature[0] = '0'; + rrfp.signature[1] = 'p'; + rrfp.signature[2] = 'i'; + rrfp.signature[3] = '3'; + rrfp.signature[0] += i; + rrfp.dwFlags = rgPin2.dwFlags; + rrfp.dwInstances = rgPin2.cInstances; + rrfp.dwMediaTypes = rgPin2.nMediaTypes; + rrfp.dwMediums = rgPin2.nMediums; + rrfp.bCategory = rgPin2.clsPinCategory ? 1 : 0; + + add_data(&mainStore, (LPBYTE)&rrfp, sizeof(rrfp)); + if (rrfp.bCategory) + { + DWORD index = find_data(&clsidStore, (LPBYTE)rgPin2.clsPinCategory, sizeof(CLSID)); + if (index == -1) + index = add_data(&clsidStore, (LPBYTE)rgPin2.clsPinCategory, sizeof(CLSID)); + index += size; + + add_data(&mainStore, (LPBYTE)&index, sizeof(index)); + } + + for (j = 0; j < rgPin2.nMediaTypes; j++) + { + struct REG_TYPE rt; + rt.signature[0] = '0'; + rt.signature[1] = 't'; + rt.signature[2] = 'y'; + rt.signature[3] = '3'; + rt.signature[0] += j; + + rt.dwUnused = 0; + rt.dwOffsetMajor = find_data(&clsidStore, (LPBYTE)rgPin2.lpMediaType[j].clsMajorType, sizeof(CLSID)); + if (rt.dwOffsetMajor == -1) + rt.dwOffsetMajor = add_data(&clsidStore, (LPBYTE)rgPin2.lpMediaType[j].clsMajorType, sizeof(CLSID)); + rt.dwOffsetMajor += size; + rt.dwOffsetMinor = find_data(&clsidStore, (LPBYTE)rgPin2.lpMediaType[j].clsMinorType, sizeof(CLSID)); + if (rt.dwOffsetMinor == -1) + rt.dwOffsetMinor = add_data(&clsidStore, (LPBYTE)rgPin2.lpMediaType[j].clsMinorType, sizeof(CLSID)); + rt.dwOffsetMinor += size; + + add_data(&mainStore, (LPBYTE)&rt, sizeof(rt)); + } + + for (j = 0; j < rgPin2.nMediums; j++) + { + DWORD index = find_data(&clsidStore, (LPBYTE)(rgPin2.lpMedium + j), sizeof(REGPINMEDIUM)); + if (index == -1) + index = add_data(&clsidStore, (LPBYTE)(rgPin2.lpMedium + j), sizeof(REGPINMEDIUM)); + index += size; + + add_data(&mainStore, (LPBYTE)&index, sizeof(index)); + } + } + + saBound.lLbound = 0; + saBound.cElements = mainStore.current + clsidStore.current; + psa = SafeArrayCreate(VT_UI1, 1, &saBound); + if (!psa) + { + ERR("Couldn't create SAFEARRAY\n"); + hr = E_FAIL; + } + + if (SUCCEEDED(hr)) + { + LPBYTE pbSAData; + hr = SafeArrayAccessData(psa, (LPVOID *)&pbSAData); + if (SUCCEEDED(hr)) + { + memcpy(pbSAData, mainStore.pData, mainStore.current); + memcpy(pbSAData + mainStore.current, clsidStore.pData, clsidStore.current); + hr = SafeArrayUnaccessData(psa); + } + } + + V_VT(&var) = VT_ARRAY | VT_UI1; + V_UNION(&var, parray) = psa; + + if (SUCCEEDED(hr)) + hr = IPropertyBag_Write(pPropBag, wszFilterDataName, &var); + + if (psa) + SafeArrayDestroy(psa); + + delete_vector(&mainStore); + delete_vector(&clsidStore); + return hr; +} + +static HRESULT FM2_ReadFilterData(IPropertyBag * pPropBag, REGFILTER2 * prf2) +{ + VARIANT var; + HRESULT hr; + LPBYTE pData = NULL; + struct REG_RF * prrf; + LPBYTE pCurrent; + DWORD i; + REGFILTERPINS2 * rgPins2; + + VariantInit(&var); + V_VT(&var) = VT_ARRAY | VT_UI1; + + hr = IPropertyBag_Read(pPropBag, wszFilterDataName, &var, NULL); + + if (SUCCEEDED(hr)) + hr = SafeArrayAccessData(V_UNION(&var, parray), (LPVOID*)&pData); + + if (SUCCEEDED(hr)) + { + prrf = (struct REG_RF *)pData; + pCurrent = pData; + + if (prrf->dwVersion != 2) + { + FIXME("Filter registry version %ld not supported\n", prrf->dwVersion); + ZeroMemory(prf2, sizeof(*prf2)); + hr = E_FAIL; + } + } + + if (SUCCEEDED(hr)) + { + TRACE("version = %ld, merit = %lx, #pins = %ld, unused = %lx\n", + prrf->dwVersion, prrf->dwMerit, prrf->dwPins, prrf->dwUnused); + + prf2->dwVersion = prrf->dwVersion; + prf2->dwMerit = prrf->dwMerit; + prf2->u.s1.cPins2 = prrf->dwPins; + rgPins2 = CoTaskMemAlloc(prrf->dwPins * sizeof(*rgPins2)); + prf2->u.s1.rgPins2 = rgPins2; + pCurrent += sizeof(struct REG_RF); + + for (i = 0; i < prrf->dwPins; i++) + { + struct REG_RFP * prrfp = (struct REG_RFP *)pCurrent; + REGPINTYPES * lpMediaType; + REGPINMEDIUM * lpMedium; + UINT j; + + /* FIXME: check signature */ + + TRACE("\tsignature = %s\n", debugstr_an(prrfp->signature, 4)); + + TRACE("\tpin[%ld]: flags = %lx, instances = %ld, media types = %ld, mediums = %ld\n", + i, prrfp->dwFlags, prrfp->dwInstances, prrfp->dwMediaTypes, prrfp->dwMediums); + + rgPins2[i].dwFlags = prrfp->dwFlags; + rgPins2[i].cInstances = prrfp->dwInstances; + rgPins2[i].nMediaTypes = prrfp->dwMediaTypes; + rgPins2[i].nMediums = prrfp->dwMediums; + pCurrent += sizeof(struct REG_RFP); + if (prrfp->bCategory) + { + CLSID * clsCat = CoTaskMemAlloc(sizeof(CLSID)); + memcpy(clsCat, pData + *(DWORD*)(pCurrent), sizeof(CLSID)); + pCurrent += sizeof(DWORD); + rgPins2[i].clsPinCategory = clsCat; + } + else + rgPins2[i].clsPinCategory = NULL; + + if (rgPins2[i].nMediaTypes > 0) + lpMediaType = CoTaskMemAlloc(rgPins2[i].nMediaTypes * sizeof(*lpMediaType)); + else + lpMediaType = NULL; + + rgPins2[i].lpMediaType = lpMediaType; + + for (j = 0; j < rgPins2[i].nMediaTypes; j++) + { + struct REG_TYPE * prt = (struct REG_TYPE *)pCurrent; + CLSID * clsMajor = CoTaskMemAlloc(sizeof(CLSID)); + CLSID * clsMinor = CoTaskMemAlloc(sizeof(CLSID)); + + /* FIXME: check signature */ + TRACE("\t\tsignature = %s\n", debugstr_an(prt->signature, 4)); + + memcpy(clsMajor, pData + prt->dwOffsetMajor, sizeof(CLSID)); + memcpy(clsMinor, pData + prt->dwOffsetMinor, sizeof(CLSID)); + + lpMediaType[j].clsMajorType = clsMajor; + lpMediaType[j].clsMinorType = clsMinor; + + pCurrent += sizeof(*prt); + } + + if (rgPins2[i].nMediums > 0) + lpMedium = CoTaskMemAlloc(rgPins2[i].nMediums * sizeof(*lpMedium)); + else + lpMedium = NULL; + + rgPins2[i].lpMedium = lpMedium; + + for (j = 0; j < rgPins2[i].nMediums; j++) + { + DWORD dwOffset = *(DWORD *)pCurrent; + + memcpy(lpMedium + j, pData + dwOffset, sizeof(REGPINMEDIUM)); + + pCurrent += sizeof(dwOffset); + } + } + + } + + if (pData) + SafeArrayUnaccessData(V_UNION(&var, parray)); + + VariantClear(&var); + + return hr; +} + +static void FM2_DeleteRegFilter(REGFILTER2 * prf2) +{ + UINT i; + for (i = 0; i < prf2->u.s1.cPins2; i++) + { + UINT j; + if (prf2->u.s1.rgPins2[i].clsPinCategory) + CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].clsPinCategory); + + for (j = 0; j < prf2->u.s1.rgPins2[i].nMediaTypes; j++) + { + CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType[j].clsMajorType); + CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType[j].clsMinorType); + } + CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMedium); + } +} + +static HRESULT WINAPI FilterMapper2_RegisterFilter( + IFilterMapper2 * iface, + REFCLSID clsidFilter, + LPCWSTR szName, + IMoniker **ppMoniker, + const CLSID *pclsidCategory, + const OLECHAR *szInstance, + const REGFILTER2 *prf2) +{ + IParseDisplayName * pParser = NULL; + IBindCtx * pBindCtx = NULL; + IMoniker * pMoniker = NULL; + IPropertyBag * pPropBag = NULL; + HRESULT hr = S_OK; + LPWSTR pwszParseName = NULL; + LPWSTR pCurrent; + static const WCHAR wszDevice[] = {'@','d','e','v','i','c','e',':','s','w',':',0}; + int nameLen; + ULONG ulEaten; + LPWSTR szClsidTemp = NULL; + + TRACE("(%s, %s, %p, %s, %s, %p)\n", + debugstr_guid(clsidFilter), + debugstr_w(szName), + ppMoniker, + debugstr_guid(pclsidCategory), + debugstr_w(szInstance), + prf2); + + if (ppMoniker) + FIXME("ppMoniker != NULL not supported at the moment\n"); + + if (prf2->dwVersion != 2) + { + FIXME("dwVersion != 2 not supported at the moment\n"); + return E_NOTIMPL; + } + + if (!pclsidCategory) + pclsidCategory = &CLSID_ActiveMovieCategories; + + /* sizeof... will include null terminator and + * the + 1 is for the seperator ('\\'). The -1 is + * because CHARS_IN_GUID includes the null terminator + */ + nameLen = sizeof(wszDevice)/sizeof(wszDevice[0]) + CHARS_IN_GUID - 1 + 1; + + if (szInstance) + nameLen += strlenW(szInstance); + else + nameLen += CHARS_IN_GUID - 1; /* CHARS_IN_GUID includes null terminator */ + + pwszParseName = CoTaskMemAlloc(nameLen); + pCurrent = pwszParseName; + if (!pwszParseName) + return E_OUTOFMEMORY; + + strcpyW(pwszParseName, wszDevice); + pCurrent += strlenW(wszDevice); + + hr = StringFromCLSID(pclsidCategory, &szClsidTemp); + strcpyW(pCurrent, szClsidTemp); + pCurrent += CHARS_IN_GUID - 1; + pCurrent[0] = '\\'; + + if (SUCCEEDED(hr)) + { + if (szInstance) + strcpyW(pCurrent+1, szInstance); + else + { + if (szClsidTemp) + { + CoTaskMemFree(szClsidTemp); + szClsidTemp = NULL; + } + hr = StringFromCLSID(clsidFilter, &szClsidTemp); + strcpyW(pCurrent+1, szClsidTemp); + } + } + + if (SUCCEEDED(hr)) + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (LPVOID *)&pParser); + + if (SUCCEEDED(hr)) + hr = CreateBindCtx(0, &pBindCtx); + + if (SUCCEEDED(hr)) + { + hr = IParseDisplayName_ParseDisplayName(pParser, pBindCtx, pwszParseName, &ulEaten, &pMoniker); + } + + if (pBindCtx) + IBindCtx_Release(pBindCtx); pBindCtx = NULL; + + if (pParser) + IParseDisplayName_Release(pParser); pParser = NULL; + + if (SUCCEEDED(hr)) + hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag); + + if (SUCCEEDED(hr)) + hr = FM2_WriteFriendlyName(pPropBag, szName); + + if (SUCCEEDED(hr)) + hr = FM2_WriteClsid(pPropBag, clsidFilter); + + if (SUCCEEDED(hr)) + hr = FM2_WriteFilterData(pPropBag, prf2); + + if (pMoniker) + IMoniker_Release(pMoniker); pMoniker = NULL; + + if (pPropBag) + IPropertyBag_Release(pPropBag); pPropBag = NULL; + + if (szClsidTemp) + CoTaskMemFree(szClsidTemp); + + TRACE("-- returning %lx\n", hr); + + return hr; +} + +/* internal helper function */ +static BOOL MatchTypes( + BOOL bExactMatch, + DWORD nPinTypes, + const REGPINTYPES * pPinTypes, + DWORD nMatchTypes, + const GUID * pMatchTypes) +{ + BOOL bMatch = FALSE; + DWORD j; + + if ((nMatchTypes == 0) && (nPinTypes > 0)) + bMatch = TRUE; + + for (j = 0; j < nPinTypes; j++) + { + DWORD i; + for (i = 0; i < nMatchTypes*2; i+=2) + { + if (((!bExactMatch && IsEqualGUID(pPinTypes[j].clsMajorType, &GUID_NULL)) || IsEqualGUID(&pMatchTypes[i], &GUID_NULL) || IsEqualGUID(pPinTypes[j].clsMajorType, &pMatchTypes[i])) && + ((!bExactMatch && IsEqualGUID(pPinTypes[j].clsMinorType, &GUID_NULL)) || IsEqualGUID(&pMatchTypes[i+1], &GUID_NULL) || IsEqualGUID(pPinTypes[j].clsMinorType, &pMatchTypes[i+1]))) + { + bMatch = TRUE; + break; + } + } + } + return bMatch; +} + +/* internal helper function for qsort of MONIKER_MERIT array */ +static int mm_compare(const void * left, const void * right) +{ + const struct MONIKER_MERIT * mmLeft = (struct MONIKER_MERIT *)left; + const struct MONIKER_MERIT * mmRight = (struct MONIKER_MERIT *)right; + + if (mmLeft->dwMerit == mmRight->dwMerit) + return 0; + if (mmLeft->dwMerit > mmRight->dwMerit) + return -1; + return 1; +} + +/* NOTES: + * Exact match means whether or not to treat GUID_NULL's in filter data as wild cards + * (GUID_NULL's in input to function automatically treated as wild cards) + * Input/Output needed means match only on criteria if TRUE (with zero input types + * meaning match any input/output pin as long as one exists), otherwise match any + * filter that meets the rest of the requirements. + */ +static HRESULT WINAPI FilterMapper2_EnumMatchingFilters( + IFilterMapper2 * iface, + IEnumMoniker **ppEnum, + DWORD dwFlags, + BOOL bExactMatch, + DWORD dwMerit, + BOOL bInputNeeded, + DWORD cInputTypes, + const GUID *pInputTypes, + const REGPINMEDIUM *pMedIn, + const CLSID *pPinCategoryIn, + BOOL bRender, + BOOL bOutputNeeded, + DWORD cOutputTypes, + const GUID *pOutputTypes, + const REGPINMEDIUM *pMedOut, + const CLSID *pPinCategoryOut) +{ + ICreateDevEnum * pCreateDevEnum; + IMoniker * pMonikerCat; + IEnumMoniker * pEnumCat; + HRESULT hr; + struct Vector monikers = {NULL, 0, 0}; + + TRACE("(%p, %lx, %s, %lx, %s, %ld, %p, %p, %p, %s, %s, %p, %p, %p)\n", + ppEnum, + dwFlags, + bExactMatch ? "true" : "false", + dwMerit, + bInputNeeded ? "true" : "false", + cInputTypes, + pInputTypes, + pMedIn, + pPinCategoryIn, + bRender ? "true" : "false", + bOutputNeeded ? "true" : "false", + pOutputTypes, + pMedOut, + pPinCategoryOut); + + if (dwFlags != 0) + { + FIXME("dwFlags = %lx not implemented\n", dwFlags); + } + + *ppEnum = NULL; + + hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, &IID_ICreateDevEnum, (LPVOID*)&pCreateDevEnum); + + if (SUCCEEDED(hr)) + hr = ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum, &CLSID_ActiveMovieCategories, &pEnumCat, 0); + + while (IEnumMoniker_Next(pEnumCat, 1, &pMonikerCat, NULL) == S_OK) + { + IPropertyBag * pPropBagCat = NULL; + VARIANT var; + HRESULT hrSub; /* this is so that one buggy filter + doesn't make the whole lot fail */ + + VariantInit(&var); + + hrSub = IMoniker_BindToStorage(pMonikerCat, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat); + + if (SUCCEEDED(hrSub)) + hrSub = IPropertyBag_Read(pPropBagCat, wszMeritName, &var, NULL); + + if (SUCCEEDED(hrSub) && (V_UNION(&var, ulVal) >= dwMerit)) + { + CLSID clsidCat; + IEnumMoniker * pEnum; + IMoniker * pMoniker; + + VariantClear(&var); + + if (TRACE_ON(quartz)) + { + VARIANT temp; + V_VT(&temp) = VT_EMPTY; + IPropertyBag_Read(pPropBagCat, wszFriendlyName, &temp, NULL); + TRACE("Considering category %s\n", debugstr_w(V_UNION(&temp, bstrVal))); + VariantClear(&temp); + } + + hrSub = IPropertyBag_Read(pPropBagCat, wszClsidName, &var, NULL); + + if (SUCCEEDED(hrSub)) + hrSub = CLSIDFromString(V_UNION(&var, bstrVal), &clsidCat); + + if (SUCCEEDED(hrSub)) + hrSub = ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum, &clsidCat, &pEnum, 0); + + if (SUCCEEDED(hrSub)) + { + while (IEnumMoniker_Next(pEnum, 1, &pMoniker, NULL) == S_OK) + { + IPropertyBag * pPropBag = NULL; + REGFILTER2 rf2; + DWORD i; + BOOL bInputMatch = !bInputNeeded; + BOOL bOutputMatch = !bOutputNeeded; + + ZeroMemory(&rf2, sizeof(rf2)); + + hrSub = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBag); + + if (SUCCEEDED(hrSub)) + hrSub = FM2_ReadFilterData(pPropBag, &rf2); + + /* Logic used for bInputMatch expression: + * There exists some pin such that bInputNeeded implies (pin is an input and + * (bRender implies pin has render flag) and major/minor types members of + * pInputTypes ) + * bOutputMatch is similar, but without the "bRender implies ..." part + * and substituting variables names containing input for output + */ + + /* determine whether filter meets requirements */ + if (SUCCEEDED(hrSub) && (rf2.dwMerit >= dwMerit)) + { + for (i = 0; (i < rf2.u.s1.cPins2) && (!bInputMatch || !bOutputMatch); i++) + { + const REGFILTERPINS2 * rfp2 = rf2.u.s1.rgPins2 + i; + + bInputMatch = bInputMatch || (!(rfp2->dwFlags & REG_PINFLAG_B_OUTPUT) && + (!bRender || (rfp2->dwFlags & REG_PINFLAG_B_RENDERER)) && + MatchTypes(bExactMatch, rfp2->nMediaTypes, rfp2->lpMediaType, cInputTypes, pInputTypes)); + bOutputMatch = bOutputMatch || ((rfp2->dwFlags & REG_PINFLAG_B_OUTPUT) && + MatchTypes(bExactMatch, rfp2->nMediaTypes, rfp2->lpMediaType, cOutputTypes, pOutputTypes)); + } + + if (bInputMatch && bOutputMatch) + { + struct MONIKER_MERIT mm = {pMoniker, rf2.dwMerit}; + IMoniker_AddRef(pMoniker); + add_data(&monikers, (LPBYTE)&mm, sizeof(mm)); + } + } + + FM2_DeleteRegFilter(&rf2); + if (pPropBag) + IPropertyBag_Release(pPropBag); + IMoniker_Release(pMoniker); + } + IEnumMoniker_Release(pEnum); + } + } + + VariantClear(&var); + if (pPropBagCat) + IPropertyBag_Release(pPropBagCat); + IMoniker_Release(pMonikerCat); + } + + + if (SUCCEEDED(hr)) + { + IMoniker ** ppMoniker; + int i; + ULONG nMonikerCount = monikers.current / sizeof(struct MONIKER_MERIT); + + /* sort the monikers in descending merit order */ + qsort(monikers.pData, nMonikerCount, + sizeof(struct MONIKER_MERIT), + mm_compare); + + /* construct an IEnumMoniker interface */ + ppMoniker = CoTaskMemAlloc(nMonikerCount * sizeof(IMoniker *)); + for (i = 0; i < nMonikerCount; i++) + { + /* no need to AddRef here as already AddRef'd above */ + ppMoniker[i] = ((struct MONIKER_MERIT *)monikers.pData)[i].pMoniker; + } + hr = EnumMonikerImpl_Create(ppMoniker, nMonikerCount, ppEnum); + CoTaskMemFree(ppMoniker); + } + + delete_vector(&monikers); + IEnumMoniker_Release(pEnumCat); + ICreateDevEnum_Release(pCreateDevEnum); + + return hr; +} + +static ICOM_VTABLE(IFilterMapper2) fm2vtbl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + + FilterMapper2_QueryInterface, + FilterMapper2_AddRef, + FilterMapper2_Release, + + FilterMapper2_CreateCategory, + FilterMapper2_UnregisterFilter, + FilterMapper2_RegisterFilter, + FilterMapper2_EnumMatchingFilters +}; + +/*** IUnknown methods ***/ + +static HRESULT WINAPI FilterMapper_QueryInterface(IFilterMapper * iface, REFIID riid, LPVOID *ppv) +{ + ICOM_THIS_From_IFilterMapper(FilterMapper2Impl, iface); + + TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv); + + return FilterMapper2_QueryInterface((IFilterMapper2*)&This->lpVtbl, riid, ppv); +} + +static ULONG WINAPI FilterMapper_AddRef(IFilterMapper * iface) +{ + ICOM_THIS_From_IFilterMapper(FilterMapper2Impl, iface); + + return FilterMapper2_AddRef((IFilterMapper2*)This); +} + +static ULONG WINAPI FilterMapper_Release(IFilterMapper * iface) +{ + ICOM_THIS_From_IFilterMapper(FilterMapper2Impl, iface); + + return FilterMapper2_Release((IFilterMapper2*)This); +} + +/*** IFilterMapper methods ***/ + +static HRESULT WINAPI FilterMapper_EnumMatchingFilters( + IFilterMapper * iface, + IEnumRegFilters **ppEnum, + DWORD dwMerit, + BOOL bInputNeeded, + CLSID clsInMaj, + CLSID clsInSub, + BOOL bRender, + BOOL bOutputNeeded, + CLSID clsOutMaj, + CLSID clsOutSub) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + + +static HRESULT WINAPI FilterMapper_RegisterFilter(IFilterMapper * iface, CLSID clsid, LPCWSTR szName, DWORD dwMerit) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI FilterMapper_RegisterFilterInstance(IFilterMapper * iface, CLSID clsid, LPCWSTR szName, CLSID *MRId) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI FilterMapper_RegisterPin( + IFilterMapper * iface, + CLSID Filter, + LPCWSTR szName, + BOOL bRendered, + BOOL bOutput, + BOOL bZero, + BOOL bMany, + CLSID ConnectsToFilter, + LPCWSTR ConnectsToPin) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + + +static HRESULT WINAPI FilterMapper_RegisterPinType( + IFilterMapper * iface, + CLSID clsFilter, + LPCWSTR szName, + CLSID clsMajorType, + CLSID clsSubType) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI FilterMapper_UnregisterFilter(IFilterMapper * iface, CLSID Filter) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI FilterMapper_UnregisterFilterInstance(IFilterMapper * iface, CLSID MRId) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI FilterMapper_UnregisterPin(IFilterMapper * iface, CLSID Filter, LPCWSTR Name) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + +static ICOM_VTABLE(IFilterMapper) fmvtbl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + + FilterMapper_QueryInterface, + FilterMapper_AddRef, + FilterMapper_Release, + + FilterMapper_RegisterFilter, + FilterMapper_RegisterFilterInstance, + FilterMapper_RegisterPin, + FilterMapper_RegisterPinType, + FilterMapper_UnregisterFilter, + FilterMapper_UnregisterFilterInstance, + FilterMapper_UnregisterPin, + FilterMapper_EnumMatchingFilters +}; diff -u -N -r -x *~ -x .#* -x CVS wine/dlls/quartz01/main.c wine/dlls/quartz/main.c --- wine/dlls/quartz01/main.c Tue Jun 24 14:26:20 2003 +++ wine/dlls/quartz/main.c Fri Jun 27 01:04:52 2003 @@ -34,6 +34,7 @@ { switch(fdwReason) { case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hInstDLL); break; case DLL_PROCESS_DETACH: break; @@ -60,6 +61,8 @@ static const struct object_creation_info object_creation[] = { { &CLSID_FilterGraph, FILTERGRAPH_create }, + { &CLSID_FilterMapper, FilterMapper2_create }, + { &CLSID_FilterMapper2, FilterMapper2_create }, }; static HRESULT WINAPI diff -u -N -r -x *~ -x .#* -x CVS wine/dlls/quartz01/quartz_private.h wine/dlls/quartz/quartz_private.h --- wine/dlls/quartz01/quartz_private.h Tue Jun 24 14:26:20 2003 +++ wine/dlls/quartz/quartz_private.h Sun Jun 29 16:41:41 2003 @@ -29,17 +29,9 @@ #include "winuser.h" #include "dshow.h" -typedef struct _IFilterGraphImpl { - ICOM_VTABLE(IGraphBuilder) *IGraphBuilder_vtbl; - ICOM_VTABLE(IMediaControl) *IMediaControl_vtbl; - ICOM_VTABLE(IMediaSeeking) *IMediaSeeking_vtbl; - ICOM_VTABLE(IBasicAudio) *IBasicAudio_vtbl; - ICOM_VTABLE(IBasicVideo) *IBasicVideo_vtbl; - ICOM_VTABLE(IVideoWindow) *IVideoWindow_vtbl; - ICOM_VTABLE(IMediaEventEx) *IMediaEventEx_vtbl; - ULONG ref; -} IFilterGraphImpl; - HRESULT FILTERGRAPH_create(IUnknown *pUnkOuter, LPVOID *ppObj) ; +HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj); + +HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum); #endif /* __QUARTZ_PRIVATE_INCLUDED__ */