ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

filtermapper.c
Go to the documentation of this file.
00001 /*
00002  * IFilterMapper & IFilterMapper2 Implementations
00003  *
00004  * Copyright 2003 Robert Shearman
00005  * Copyright 2004 Christian Costa
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #define NONAMELESSUNION
00023 #define NONAMELESSSTRUCT
00024 #include <stdarg.h>
00025 
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "winuser.h"
00029 #include "winreg.h"
00030 #include "winerror.h"
00031 
00032 #include "quartz_private.h"
00033 
00034 #include "ole2.h"
00035 #include "olectl.h"
00036 #include "strmif.h"
00037 #include "wine/unicode.h"
00038 #include "uuids.h"
00039 
00040 #include "wine/debug.h"
00041 
00042 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
00043 
00044 #define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
00045 
00046 /* Unexposed IAMFilterData interface */
00047 typedef struct IAMFilterData IAMFilterData;
00048 
00049 typedef struct IAMFilterDataVtbl
00050 {
00051     BEGIN_INTERFACE
00052 
00053     /*** IUnknown methods ***/
00054     HRESULT (STDMETHODCALLTYPE *QueryInterface)(
00055         IAMFilterData *This,
00056         REFIID riid,
00057         void **ppvObject);
00058 
00059     ULONG (STDMETHODCALLTYPE *AddRef)(
00060         IAMFilterData *This);
00061 
00062     ULONG (STDMETHODCALLTYPE *Release)(
00063         IAMFilterData *This);
00064 
00065     /*** IAMFilterData methods ***/
00066     HRESULT (STDMETHODCALLTYPE *ParseFilterData)(
00067         IAMFilterData *This,
00068         BYTE *pData,
00069         ULONG cb,
00070         BYTE **ppRegFilter2);
00071 
00072     HRESULT (STDMETHODCALLTYPE *CreateFilterData)(
00073         IAMFilterData* This,
00074         REGFILTER2 *prf2,
00075         BYTE **pRegFilterData,
00076         ULONG *pcb);
00077 
00078     END_INTERFACE
00079 } IAMFilterDataVtbl;
00080 struct IAMFilterData
00081 {
00082     const IAMFilterDataVtbl *lpVtbl;
00083 };
00084 static const GUID IID_IAMFilterData = {
00085  0x97f7c4d4, 0x547b, 0x4a5f, { 0x83,0x32, 0x53,0x64,0x30,0xad,0x2e,0x4d }
00086 };
00087 
00088 
00089 typedef struct FilterMapper2Impl
00090 {
00091     const IFilterMapper2Vtbl *lpVtbl;
00092     const IFilterMapperVtbl  *lpVtblFilterMapper;
00093     const IAMFilterDataVtbl  *lpVtblAMFilterData;
00094     const IUnknownVtbl *IInner_vtbl;
00095     LONG refCount;
00096     IUnknown * pUnkOuter;
00097     BOOL bUnkOuterValid;
00098     BOOL bAggregatable;
00099 } FilterMapper2Impl;
00100 
00101 static const IUnknownVtbl IInner_VTable;
00102 static const IFilterMapper2Vtbl fm2vtbl;
00103 static const IFilterMapperVtbl fmvtbl;
00104 static const IAMFilterDataVtbl AMFilterDataVtbl;
00105 
00106 static inline FilterMapper2Impl *impl_from_IFilterMapper( IFilterMapper *iface )
00107 {
00108     return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, lpVtblFilterMapper));
00109 }
00110 
00111 static inline FilterMapper2Impl *impl_from_IAMFilterData( IAMFilterData *iface )
00112 {
00113     return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, lpVtblAMFilterData));
00114 }
00115 
00116 static inline FilterMapper2Impl *impl_from_inner_IUnknown( IUnknown *iface )
00117 {
00118     return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, IInner_vtbl));
00119 }
00120 
00121 static const WCHAR wszClsidSlash[] = {'C','L','S','I','D','\\',0};
00122 static const WCHAR wszSlashInstance[] = {'\\','I','n','s','t','a','n','c','e','\\',0};
00123 static const WCHAR wszSlash[] = {'\\',0};
00124 
00125 /* CLSID property in media category Moniker */
00126 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
00127 /* FriendlyName property in media category Moniker */
00128 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
00129 /* Merit property in media category Moniker (CLSID_ActiveMovieCategories only) */
00130 static const WCHAR wszMeritName[] = {'M','e','r','i','t',0};
00131 /* FilterData property in media category Moniker (not CLSID_ActiveMovieCategories) */
00132 static const WCHAR wszFilterDataName[] = {'F','i','l','t','e','r','D','a','t','a',0};
00133 /* For filters registered with IFilterMapper */
00134 static const WCHAR wszFilterSlash[] = {'F','i','l','t','e','r','\\',0};
00135 static const WCHAR wszFilter[] = {'F','i','l','t','e','r',0};
00136 /* For pins registered with IFilterMapper */
00137 static const WCHAR wszPins[] = {'P','i','n','s',0};
00138 static const WCHAR wszAllowedMany[] = {'A','l','l','o','w','e','d','M','a','n','y',0};
00139 static const WCHAR wszAllowedZero[] = {'A','l','l','o','w','e','d','Z','e','r','o',0};
00140 static const WCHAR wszDirection[] = {'D','i','r','e','c','t','i','o','n',0};
00141 static const WCHAR wszIsRendered[] = {'I','s','R','e','n','d','e','r','e','d',0};
00142 /* For types registered with IFilterMapper */
00143 static const WCHAR wszTypes[] = {'T','y','p','e','s',0};
00144 
00145 
00146 /* registry format for REGFILTER2 */
00147 struct REG_RF
00148 {
00149     DWORD dwVersion;
00150     DWORD dwMerit;
00151     DWORD dwPins;
00152     DWORD dwUnused;
00153 };
00154 
00155 struct REG_RFP
00156 {
00157     BYTE signature[4]; /* e.g. "0pi3" */
00158     DWORD dwFlags;
00159     DWORD dwInstances;
00160     DWORD dwMediaTypes;
00161     DWORD dwMediums;
00162     DWORD bCategory; /* is there a category clsid? */
00163     /* optional: dwOffsetCategoryClsid */
00164 };
00165 
00166 struct REG_TYPE
00167 {
00168     BYTE signature[4]; /* e.g. "0ty3" */
00169     DWORD dwUnused;
00170     DWORD dwOffsetMajor;
00171     DWORD dwOffsetMinor;
00172 };
00173 
00174 struct MONIKER_MERIT
00175 {
00176     IMoniker * pMoniker;
00177     DWORD dwMerit;
00178 };
00179 
00180 struct Vector
00181 {
00182     LPBYTE pData;
00183     int capacity; /* in bytes */
00184     int current; /* pointer to next free byte */
00185 };
00186 
00187 /* returns the position it was added at */
00188 static int add_data(struct Vector * v, const BYTE * pData, int size)
00189 {
00190     int index = v->current;
00191     if (v->current + size > v->capacity)
00192     {
00193         LPBYTE pOldData = v->pData;
00194         v->capacity = (v->capacity + size) * 2;
00195         v->pData = CoTaskMemAlloc(v->capacity);
00196         memcpy(v->pData, pOldData, v->current);
00197         CoTaskMemFree(pOldData);
00198     }
00199     memcpy(v->pData + v->current, pData, size);
00200     v->current += size;
00201     return index;
00202 }
00203 
00204 static int find_data(const struct Vector * v, const BYTE * pData, int size)
00205 {
00206     int index;
00207     for (index = 0; index < v->current; index++)
00208         if (!memcmp(v->pData + index, pData, size))
00209             return index;
00210     /* not found */
00211     return -1;
00212 }
00213 
00214 static void delete_vector(struct Vector * v)
00215 {
00216     CoTaskMemFree(v->pData);
00217     v->current = 0;
00218     v->capacity = 0;
00219 }
00220 
00221 HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj)
00222 {
00223     FilterMapper2Impl * pFM2impl;
00224 
00225     TRACE("(%p, %p)\n", pUnkOuter, ppObj);
00226 
00227     pFM2impl = CoTaskMemAlloc(sizeof(*pFM2impl));
00228     if (!pFM2impl)
00229         return E_OUTOFMEMORY;
00230 
00231     pFM2impl->pUnkOuter = pUnkOuter;
00232     pFM2impl->bUnkOuterValid = FALSE;
00233     pFM2impl->bAggregatable = FALSE;
00234     pFM2impl->IInner_vtbl = &IInner_VTable;
00235     pFM2impl->lpVtbl = &fm2vtbl;
00236     pFM2impl->lpVtblFilterMapper = &fmvtbl;
00237     pFM2impl->lpVtblAMFilterData = &AMFilterDataVtbl;
00238     pFM2impl->refCount = 1;
00239 
00240     *ppObj = pFM2impl;
00241 
00242     TRACE("-- created at %p\n", pFM2impl);
00243 
00244     return S_OK;
00245 }
00246 
00247 HRESULT FilterMapper_create(IUnknown *pUnkOuter, LPVOID *ppObj)
00248 {
00249     FilterMapper2Impl *pFM2impl;
00250     HRESULT hr;
00251 
00252     TRACE("(%p, %p)\n", pUnkOuter, ppObj);
00253 
00254     hr = FilterMapper2_create(pUnkOuter, (LPVOID*)&pFM2impl);
00255     if (FAILED(hr))
00256         return hr;
00257 
00258     *ppObj = &pFM2impl->lpVtblFilterMapper;
00259 
00260     return hr;
00261 }
00262 
00263 /*** IUnknown (inner) methods ***/
00264 
00265 static HRESULT WINAPI Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
00266 {
00267     FilterMapper2Impl *This = impl_from_inner_IUnknown(iface);
00268     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
00269 
00270     if (This->bAggregatable)
00271         This->bUnkOuterValid = TRUE;
00272 
00273     *ppv = NULL;
00274 
00275     if (IsEqualIID(riid, &IID_IUnknown))
00276         *ppv = &This->IInner_vtbl;
00277     else if (IsEqualIID(riid, &IID_IFilterMapper2))
00278         *ppv = This;
00279     else if (IsEqualIID(riid, &IID_IFilterMapper))
00280         *ppv = &This->lpVtblFilterMapper;
00281     else if (IsEqualIID(riid, &IID_IAMFilterData))
00282         *ppv = &This->lpVtblAMFilterData;
00283 
00284     if (*ppv != NULL)
00285     {
00286         IUnknown_AddRef((IUnknown *)*ppv);
00287         return S_OK;
00288     }
00289 
00290     FIXME("No interface for %s\n", debugstr_guid(riid));
00291     return E_NOINTERFACE;
00292 }
00293 
00294 static ULONG WINAPI Inner_AddRef(IUnknown * iface)
00295 {
00296     FilterMapper2Impl *This = impl_from_inner_IUnknown(iface);
00297     ULONG refCount = InterlockedIncrement(&This->refCount);
00298 
00299     TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
00300 
00301     return refCount;
00302 }
00303 
00304 static ULONG WINAPI Inner_Release(IUnknown * iface)
00305 {
00306     FilterMapper2Impl *This = impl_from_inner_IUnknown(iface);
00307     ULONG refCount = InterlockedDecrement(&This->refCount);
00308 
00309     TRACE("(%p)->() Release from %d\n", This, refCount + 1);
00310 
00311     if (refCount == 0)
00312     {
00313         CoTaskMemFree(This);
00314         return 0;
00315     }
00316     return refCount;
00317 }
00318 
00319 static const IUnknownVtbl IInner_VTable =
00320 {
00321     Inner_QueryInterface,
00322     Inner_AddRef,
00323     Inner_Release
00324 };
00325 
00326 static HRESULT WINAPI FilterMapper2_QueryInterface(IFilterMapper2 * iface, REFIID riid, LPVOID *ppv)
00327 {
00328     FilterMapper2Impl *This = (FilterMapper2Impl *)iface;
00329 
00330     if (This->bAggregatable)
00331         This->bUnkOuterValid = TRUE;
00332 
00333     if (This->pUnkOuter)
00334     {
00335         if (This->bAggregatable)
00336             return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
00337 
00338         if (IsEqualIID(riid, &IID_IUnknown))
00339         {
00340             HRESULT hr;
00341 
00342             IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
00343             hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
00344             IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
00345             This->bAggregatable = TRUE;
00346             return hr;
00347         }
00348 
00349         *ppv = NULL;
00350         return E_NOINTERFACE;
00351     }
00352 
00353     return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
00354 }
00355 
00356 static ULONG WINAPI FilterMapper2_AddRef(IFilterMapper2 * iface)
00357 {
00358     FilterMapper2Impl *This = (FilterMapper2Impl *)iface;
00359 
00360     if (This->pUnkOuter && This->bUnkOuterValid)
00361         return IUnknown_AddRef(This->pUnkOuter);
00362     return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
00363 }
00364 
00365 static ULONG WINAPI FilterMapper2_Release(IFilterMapper2 * iface)
00366 {
00367     FilterMapper2Impl *This = (FilterMapper2Impl *)iface;
00368 
00369     if (This->pUnkOuter && This->bUnkOuterValid)
00370         return IUnknown_Release(This->pUnkOuter);
00371     return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
00372 }
00373 
00374 /*** IFilterMapper2 methods ***/
00375 
00376 static HRESULT WINAPI FilterMapper2_CreateCategory(
00377     IFilterMapper2 * iface,
00378     REFCLSID clsidCategory,
00379     DWORD dwCategoryMerit,
00380     LPCWSTR szDescription)
00381 {
00382     LPWSTR wClsidAMCat = NULL;
00383     LPWSTR wClsidCategory = NULL;
00384     WCHAR wszKeyName[ARRAYSIZE(wszClsidSlash)-1 + ARRAYSIZE(wszSlashInstance)-1 + (CHARS_IN_GUID-1) * 2 + 1];
00385     HKEY hKey = NULL;
00386     LONG lRet;
00387     HRESULT hr;
00388 
00389     TRACE("(%s, %x, %s)\n", debugstr_guid(clsidCategory), dwCategoryMerit, debugstr_w(szDescription));
00390 
00391     hr = StringFromCLSID(&CLSID_ActiveMovieCategories, &wClsidAMCat);
00392 
00393     if (SUCCEEDED(hr))
00394     {
00395         hr = StringFromCLSID(clsidCategory, &wClsidCategory);
00396     }
00397 
00398     if (SUCCEEDED(hr))
00399     {
00400         strcpyW(wszKeyName, wszClsidSlash);
00401         strcatW(wszKeyName, wClsidAMCat);
00402         strcatW(wszKeyName, wszSlashInstance);
00403         strcatW(wszKeyName, wClsidCategory);
00404 
00405         lRet = RegCreateKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
00406         hr = HRESULT_FROM_WIN32(lRet);
00407     }
00408 
00409     if (SUCCEEDED(hr))
00410     {
00411         lRet = RegSetValueExW(hKey, wszFriendlyName, 0, REG_SZ, (const BYTE*)szDescription, (strlenW(szDescription) + 1) * sizeof(WCHAR));
00412         hr = HRESULT_FROM_WIN32(lRet);
00413     }
00414 
00415     if (SUCCEEDED(hr))
00416     {
00417         lRet = RegSetValueExW(hKey, wszClsidName, 0, REG_SZ, (LPBYTE)wClsidCategory, (strlenW(wClsidCategory) + 1) * sizeof(WCHAR));
00418         hr = HRESULT_FROM_WIN32(lRet);
00419     }
00420 
00421     if (SUCCEEDED(hr))
00422     {
00423         lRet = RegSetValueExW(hKey, wszMeritName, 0, REG_DWORD, (LPBYTE)&dwCategoryMerit, sizeof(dwCategoryMerit));
00424         hr = HRESULT_FROM_WIN32(lRet);
00425     }
00426 
00427     CloseHandle(hKey);
00428     CoTaskMemFree(wClsidCategory);
00429     CoTaskMemFree(wClsidAMCat);
00430 
00431     return hr;
00432 }
00433 
00434 static HRESULT WINAPI FilterMapper2_UnregisterFilter(
00435     IFilterMapper2 * iface,
00436     const CLSID *pclsidCategory,
00437     const OLECHAR *szInstance,
00438     REFCLSID Filter)
00439 {
00440     WCHAR wszKeyName[MAX_PATH];
00441     LPWSTR wClsidCategory = NULL;
00442     LPWSTR wFilter = NULL;
00443     HRESULT hr;
00444 
00445     TRACE("(%p, %s, %s)\n", pclsidCategory, debugstr_w(szInstance), debugstr_guid(Filter));
00446 
00447     if (!pclsidCategory)
00448         pclsidCategory = &CLSID_LegacyAmFilterCategory;
00449 
00450     hr = StringFromCLSID(pclsidCategory, &wClsidCategory);
00451 
00452     if (SUCCEEDED(hr))
00453     {
00454         strcpyW(wszKeyName, wszClsidSlash);
00455         strcatW(wszKeyName, wClsidCategory);
00456         strcatW(wszKeyName, wszSlashInstance);
00457         if (szInstance)
00458             strcatW(wszKeyName, szInstance);
00459         else
00460         {
00461             hr = StringFromCLSID(Filter, &wFilter);
00462             if (SUCCEEDED(hr))
00463                 strcatW(wszKeyName, wFilter);
00464         }
00465     }
00466 
00467     if (SUCCEEDED(hr))
00468     {
00469         LONG lRet = RegDeleteKeyW(HKEY_CLASSES_ROOT, wszKeyName);
00470         hr = HRESULT_FROM_WIN32(lRet);
00471     }
00472 
00473     CoTaskMemFree(wClsidCategory);
00474     CoTaskMemFree(wFilter);
00475 
00476     return hr;
00477 }
00478 
00479 static HRESULT FM2_WriteFriendlyName(IPropertyBag * pPropBag, LPCWSTR szName)
00480 {
00481     VARIANT var;
00482     HRESULT ret;
00483     BSTR value;
00484 
00485     V_VT(&var) = VT_BSTR;
00486     V_UNION(&var, bstrVal) = value = SysAllocString(szName);
00487 
00488     ret = IPropertyBag_Write(pPropBag, wszFriendlyName, &var);
00489     SysFreeString(value);
00490 
00491     return ret;
00492 }
00493 
00494 static HRESULT FM2_WriteClsid(IPropertyBag * pPropBag, REFCLSID clsid)
00495 {
00496     LPWSTR wszClsid = NULL;
00497     VARIANT var;
00498     HRESULT hr;
00499 
00500     hr = StringFromCLSID(clsid, &wszClsid);
00501 
00502     if (SUCCEEDED(hr))
00503     {
00504         V_VT(&var) = VT_BSTR;
00505         V_UNION(&var, bstrVal) = wszClsid;
00506         hr = IPropertyBag_Write(pPropBag, wszClsidName, &var);
00507     }
00508     CoTaskMemFree(wszClsid);
00509     return hr;
00510 }
00511 
00512 static HRESULT FM2_WriteFilterData(const REGFILTER2 * prf2, BYTE **ppData, ULONG *pcbData)
00513 {
00514     int size = sizeof(struct REG_RF);
00515     unsigned int i;
00516     struct Vector mainStore = {NULL, 0, 0};
00517     struct Vector clsidStore = {NULL, 0, 0};
00518     struct REG_RF rrf;
00519     HRESULT hr = S_OK;
00520 
00521     rrf.dwVersion = prf2->dwVersion;
00522     rrf.dwMerit = prf2->dwMerit;
00523     rrf.dwPins = prf2->u.s1.cPins2;
00524     rrf.dwUnused = 0;
00525 
00526     add_data(&mainStore, (LPBYTE)&rrf, sizeof(rrf));
00527 
00528     for (i = 0; i < prf2->u.s1.cPins2; i++)
00529     {
00530         size += sizeof(struct REG_RFP);
00531         if (prf2->u.s1.rgPins2[i].clsPinCategory)
00532             size += sizeof(DWORD);
00533         size += prf2->u.s1.rgPins2[i].nMediaTypes * sizeof(struct REG_TYPE);
00534         size += prf2->u.s1.rgPins2[i].nMediums * sizeof(DWORD);
00535     }
00536 
00537     for (i = 0; i < prf2->u.s1.cPins2; i++)
00538     {
00539         struct REG_RFP rrfp;
00540         REGFILTERPINS2 rgPin2 = prf2->u.s1.rgPins2[i];
00541         unsigned int j;
00542 
00543         rrfp.signature[0] = '0';
00544         rrfp.signature[1] = 'p';
00545         rrfp.signature[2] = 'i';
00546         rrfp.signature[3] = '3';
00547         rrfp.signature[0] += i;
00548         rrfp.dwFlags = rgPin2.dwFlags;
00549         rrfp.dwInstances = rgPin2.cInstances;
00550         rrfp.dwMediaTypes = rgPin2.nMediaTypes;
00551         rrfp.dwMediums = rgPin2.nMediums;
00552         rrfp.bCategory = rgPin2.clsPinCategory ? 1 : 0;
00553 
00554         add_data(&mainStore, (LPBYTE)&rrfp, sizeof(rrfp));
00555         if (rrfp.bCategory)
00556         {
00557             DWORD index = find_data(&clsidStore, (const BYTE*)rgPin2.clsPinCategory, sizeof(CLSID));
00558             if (index == -1)
00559                 index = add_data(&clsidStore, (const BYTE*)rgPin2.clsPinCategory, sizeof(CLSID));
00560             index += size;
00561 
00562             add_data(&mainStore, (LPBYTE)&index, sizeof(index));
00563         }
00564 
00565         for (j = 0; j < rgPin2.nMediaTypes; j++)
00566         {
00567             struct REG_TYPE rt;
00568             const CLSID * clsMinorType = rgPin2.lpMediaType[j].clsMinorType ? rgPin2.lpMediaType[j].clsMinorType : &MEDIASUBTYPE_NULL;
00569             rt.signature[0] = '0';
00570             rt.signature[1] = 't';
00571             rt.signature[2] = 'y';
00572             rt.signature[3] = '3';
00573             rt.signature[0] += j;
00574             rt.dwUnused = 0;
00575             rt.dwOffsetMajor = find_data(&clsidStore, (const BYTE*)rgPin2.lpMediaType[j].clsMajorType, sizeof(CLSID));
00576             if (rt.dwOffsetMajor == -1)
00577                 rt.dwOffsetMajor = add_data(&clsidStore, (const BYTE*)rgPin2.lpMediaType[j].clsMajorType, sizeof(CLSID));
00578             rt.dwOffsetMajor += size;
00579             rt.dwOffsetMinor = find_data(&clsidStore, (const BYTE*)clsMinorType, sizeof(CLSID));
00580             if (rt.dwOffsetMinor == -1)
00581                 rt.dwOffsetMinor = add_data(&clsidStore, (const BYTE*)clsMinorType, sizeof(CLSID));
00582             rt.dwOffsetMinor += size;
00583 
00584             add_data(&mainStore, (LPBYTE)&rt, sizeof(rt));
00585         }
00586 
00587         for (j = 0; j < rgPin2.nMediums; j++)
00588         {
00589             DWORD index = find_data(&clsidStore, (const BYTE*)(rgPin2.lpMedium + j), sizeof(REGPINMEDIUM));
00590             if (index == -1)
00591                 index = add_data(&clsidStore, (const BYTE*)(rgPin2.lpMedium + j), sizeof(REGPINMEDIUM));
00592             index += size;
00593 
00594             add_data(&mainStore, (LPBYTE)&index, sizeof(index));
00595         }
00596     }
00597 
00598     if (SUCCEEDED(hr))
00599     {
00600         *pcbData = mainStore.current + clsidStore.current;
00601         *ppData = CoTaskMemAlloc(*pcbData);
00602         if (!*ppData)
00603             hr = E_OUTOFMEMORY;
00604     }
00605 
00606     if (SUCCEEDED(hr))
00607     {
00608         memcpy(*ppData, mainStore.pData, mainStore.current);
00609         memcpy((*ppData) + mainStore.current, clsidStore.pData, clsidStore.current);
00610     }
00611 
00612     delete_vector(&mainStore);
00613     delete_vector(&clsidStore);
00614     return hr;
00615 }
00616 
00617 static HRESULT FM2_ReadFilterData(BYTE *pData, REGFILTER2 * prf2)
00618 {
00619     HRESULT hr = S_OK;
00620     struct REG_RF * prrf;
00621     LPBYTE pCurrent;
00622     DWORD i;
00623     REGFILTERPINS2 * rgPins2;
00624 
00625     prrf = (struct REG_RF *)pData;
00626     pCurrent = pData;
00627 
00628     if (prrf->dwVersion != 2)
00629     {
00630         FIXME("Filter registry version %d not supported\n", prrf->dwVersion);
00631         ZeroMemory(prf2, sizeof(*prf2));
00632         hr = E_FAIL;
00633     }
00634 
00635     if (SUCCEEDED(hr))
00636     {
00637         TRACE("version = %d, merit = %x, #pins = %d, unused = %x\n",
00638             prrf->dwVersion, prrf->dwMerit, prrf->dwPins, prrf->dwUnused);
00639 
00640         prf2->dwVersion = prrf->dwVersion;
00641         prf2->dwMerit = prrf->dwMerit;
00642         prf2->u.s1.cPins2 = prrf->dwPins;
00643         rgPins2 = CoTaskMemAlloc(prrf->dwPins * sizeof(*rgPins2));
00644         prf2->u.s1.rgPins2 = rgPins2;
00645         pCurrent += sizeof(struct REG_RF);
00646 
00647         for (i = 0; i < prrf->dwPins; i++)
00648         {
00649             struct REG_RFP * prrfp = (struct REG_RFP *)pCurrent;
00650             REGPINTYPES * lpMediaType;
00651             REGPINMEDIUM * lpMedium;
00652             UINT j;
00653 
00654             /* FIXME: check signature */
00655 
00656             TRACE("\tsignature = %s\n", debugstr_an((const char*)prrfp->signature, 4));
00657 
00658             TRACE("\tpin[%d]: flags = %x, instances = %d, media types = %d, mediums = %d\n",
00659                 i, prrfp->dwFlags, prrfp->dwInstances, prrfp->dwMediaTypes, prrfp->dwMediums);
00660 
00661             rgPins2[i].dwFlags = prrfp->dwFlags;
00662             rgPins2[i].cInstances = prrfp->dwInstances;
00663             rgPins2[i].nMediaTypes = prrfp->dwMediaTypes;
00664             rgPins2[i].nMediums = prrfp->dwMediums;
00665             pCurrent += sizeof(struct REG_RFP);
00666             if (prrfp->bCategory)
00667             {
00668                 CLSID * clsCat = CoTaskMemAlloc(sizeof(CLSID));
00669                 memcpy(clsCat, pData + *(DWORD*)(pCurrent), sizeof(CLSID));
00670                 pCurrent += sizeof(DWORD);
00671                 rgPins2[i].clsPinCategory = clsCat;
00672             }
00673             else
00674                 rgPins2[i].clsPinCategory = NULL;
00675 
00676             if (rgPins2[i].nMediaTypes > 0)
00677                 lpMediaType = CoTaskMemAlloc(rgPins2[i].nMediaTypes * sizeof(*lpMediaType));
00678             else
00679                 lpMediaType = NULL;
00680 
00681             rgPins2[i].lpMediaType = lpMediaType;
00682 
00683             for (j = 0; j < rgPins2[i].nMediaTypes; j++)
00684             {
00685                 struct REG_TYPE * prt = (struct REG_TYPE *)pCurrent;
00686                 CLSID * clsMajor = CoTaskMemAlloc(sizeof(CLSID));
00687                 CLSID * clsMinor = CoTaskMemAlloc(sizeof(CLSID));
00688 
00689                 /* FIXME: check signature */
00690                 TRACE("\t\tsignature = %s\n", debugstr_an((const char*)prt->signature, 4));
00691 
00692                 memcpy(clsMajor, pData + prt->dwOffsetMajor, sizeof(CLSID));
00693                 memcpy(clsMinor, pData + prt->dwOffsetMinor, sizeof(CLSID));
00694 
00695                 lpMediaType[j].clsMajorType = clsMajor;
00696                 lpMediaType[j].clsMinorType = clsMinor;
00697 
00698                 pCurrent += sizeof(*prt);
00699             }
00700 
00701             if (rgPins2[i].nMediums > 0)
00702                 lpMedium = CoTaskMemAlloc(rgPins2[i].nMediums * sizeof(*lpMedium));
00703             else
00704                 lpMedium = NULL;
00705 
00706             rgPins2[i].lpMedium = lpMedium;
00707 
00708             for (j = 0; j < rgPins2[i].nMediums; j++)
00709             {
00710                 DWORD dwOffset = *(DWORD *)pCurrent;
00711 
00712                 memcpy(lpMedium + j, pData + dwOffset, sizeof(REGPINMEDIUM));
00713 
00714                 pCurrent += sizeof(dwOffset);
00715             }
00716         }
00717 
00718     }
00719 
00720     return hr;
00721 }
00722 
00723 static void FM2_DeleteRegFilter(REGFILTER2 * prf2)
00724 {
00725     UINT i;
00726     for (i = 0; i < prf2->u.s1.cPins2; i++)
00727     {
00728         UINT j;
00729         if (prf2->u.s1.rgPins2[i].clsPinCategory)
00730             CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].clsPinCategory);
00731 
00732         for (j = 0; j < prf2->u.s1.rgPins2[i].nMediaTypes; j++)
00733         {
00734             CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType[j].clsMajorType);
00735             CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType[j].clsMinorType);
00736         }
00737         CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType);
00738         CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMedium);
00739     }
00740     CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2);
00741 }
00742 
00743 static HRESULT WINAPI FilterMapper2_RegisterFilter(
00744     IFilterMapper2 * iface,
00745     REFCLSID clsidFilter,
00746     LPCWSTR szName,
00747     IMoniker **ppMoniker,
00748     const CLSID *pclsidCategory,
00749     const OLECHAR *szInstance,
00750     const REGFILTER2 *prf2)
00751 {
00752     IParseDisplayName * pParser = NULL;
00753     IBindCtx * pBindCtx = NULL;
00754     IMoniker * pMoniker = NULL;
00755     IPropertyBag * pPropBag = NULL;
00756     HRESULT hr;
00757     LPWSTR pwszParseName = NULL;
00758     LPWSTR pCurrent;
00759     static const WCHAR wszDevice[] = {'@','d','e','v','i','c','e',':','s','w',':',0};
00760     int nameLen;
00761     ULONG ulEaten;
00762     LPWSTR szClsidTemp = NULL;
00763     REGFILTER2 regfilter2;
00764     REGFILTERPINS2* pregfp2 = NULL;
00765 
00766     TRACE("(%s, %s, %p, %s, %s, %p)\n",
00767         debugstr_guid(clsidFilter),
00768         debugstr_w(szName),
00769         ppMoniker,
00770         debugstr_guid(pclsidCategory),
00771         debugstr_w(szInstance),
00772         prf2);
00773 
00774     if (prf2->dwVersion == 2)
00775     {
00776         regfilter2 = *prf2;
00777     }
00778     else if (prf2->dwVersion == 1)
00779     {
00780         ULONG i;
00781         DWORD flags;
00782         /* REGFILTER2 structure is converted from version 1 to 2. Tested on Win2k. */
00783         regfilter2.dwVersion = 2;
00784         regfilter2.dwMerit = prf2->dwMerit;
00785         regfilter2.u.s1.cPins2 = prf2->u.s.cPins;
00786         pregfp2 = CoTaskMemAlloc(prf2->u.s.cPins * sizeof(REGFILTERPINS2));
00787         regfilter2.u.s1.rgPins2 = pregfp2;
00788         for (i = 0; i < prf2->u.s.cPins; i++)
00789         {
00790             flags = 0;
00791             if (prf2->u.s.rgPins[i].bRendered)
00792                 flags |= REG_PINFLAG_B_RENDERER;
00793             if (prf2->u.s.rgPins[i].bOutput)
00794                 flags |= REG_PINFLAG_B_OUTPUT;
00795             if (prf2->u.s.rgPins[i].bZero)
00796                 flags |= REG_PINFLAG_B_ZERO;
00797             if (prf2->u.s.rgPins[i].bMany)
00798                 flags |= REG_PINFLAG_B_MANY;
00799             pregfp2[i].dwFlags = flags;
00800             pregfp2[i].cInstances = 1;
00801             pregfp2[i].nMediaTypes = prf2->u.s.rgPins[i].nMediaTypes;
00802             pregfp2[i].lpMediaType = prf2->u.s.rgPins[i].lpMediaType;
00803             pregfp2[i].nMediums = 0;
00804             pregfp2[i].lpMedium = NULL;
00805             pregfp2[i].clsPinCategory = NULL;
00806         }
00807     }
00808     else
00809     {
00810         FIXME("dwVersion other that 1 or 2 not supported at the moment\n");
00811         return E_NOTIMPL;
00812     }
00813 
00814     if (ppMoniker)
00815         *ppMoniker = NULL;
00816 
00817     if (!pclsidCategory)
00818         /* MSDN mentions the inexistent CLSID_ActiveMovieFilters GUID.
00819          * In fact this is the CLSID_LegacyAmFilterCategory one */
00820         pclsidCategory = &CLSID_LegacyAmFilterCategory;
00821 
00822     /* sizeof... will include the null terminator and
00823      * the + 1 is for the separator ('\\'). The -1 is
00824      * because CHARS_IN_GUID includes the null terminator
00825      */
00826     nameLen = sizeof(wszDevice)/sizeof(wszDevice[0]) + CHARS_IN_GUID - 1 + 1;
00827 
00828     if (szInstance)
00829         nameLen += strlenW(szInstance);
00830     else
00831         nameLen += CHARS_IN_GUID - 1; /* CHARS_IN_GUID includes null terminator */
00832 
00833     pCurrent = pwszParseName = CoTaskMemAlloc(nameLen*sizeof(WCHAR));
00834     if (!pwszParseName)
00835         return E_OUTOFMEMORY;
00836 
00837     strcpyW(pwszParseName, wszDevice);
00838     pCurrent += strlenW(wszDevice);
00839 
00840     hr = StringFromCLSID(pclsidCategory, &szClsidTemp);
00841 
00842     if (SUCCEEDED(hr))
00843     {
00844         memcpy(pCurrent, szClsidTemp, CHARS_IN_GUID * sizeof(WCHAR));
00845         pCurrent += CHARS_IN_GUID - 1;
00846         pCurrent[0] = '\\';
00847 
00848         if (szInstance)
00849             strcpyW(pCurrent+1, szInstance);
00850         else
00851         {
00852             CoTaskMemFree(szClsidTemp);
00853             szClsidTemp = NULL;
00854 
00855             hr = StringFromCLSID(clsidFilter, &szClsidTemp);
00856             if (SUCCEEDED(hr))
00857                 strcpyW(pCurrent+1, szClsidTemp);
00858         }
00859     }
00860 
00861     if (SUCCEEDED(hr))
00862         hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (LPVOID *)&pParser);
00863 
00864     if (SUCCEEDED(hr))
00865         hr = CreateBindCtx(0, &pBindCtx);
00866 
00867     if (SUCCEEDED(hr))
00868         hr = IParseDisplayName_ParseDisplayName(pParser, pBindCtx, pwszParseName, &ulEaten, &pMoniker);
00869 
00870     if (pBindCtx)
00871         IBindCtx_Release(pBindCtx);
00872     if (pParser)
00873         IParseDisplayName_Release(pParser);
00874 
00875     if (SUCCEEDED(hr))
00876         hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag);
00877 
00878     if (SUCCEEDED(hr))
00879         hr = FM2_WriteFriendlyName(pPropBag, szName);
00880 
00881     if (SUCCEEDED(hr))
00882         hr = FM2_WriteClsid(pPropBag, clsidFilter);
00883 
00884     if (SUCCEEDED(hr))
00885     {
00886         BYTE *pData;
00887         ULONG cbData;
00888 
00889         hr = FM2_WriteFilterData(&regfilter2, &pData, &cbData);
00890         if (SUCCEEDED(hr))
00891         {
00892             VARIANT var;
00893             SAFEARRAY *psa;
00894             SAFEARRAYBOUND saBound;
00895 
00896             saBound.lLbound = 0;
00897             saBound.cElements = cbData;
00898             psa = SafeArrayCreate(VT_UI1, 1, &saBound);
00899             if (!psa)
00900             {
00901                 ERR("Couldn't create SAFEARRAY\n");
00902                 hr = E_FAIL;
00903             }
00904 
00905             if (SUCCEEDED(hr))
00906             {
00907                 LPBYTE pbSAData;
00908                 hr = SafeArrayAccessData(psa, (LPVOID *)&pbSAData);
00909                 if (SUCCEEDED(hr))
00910                 {
00911                     memcpy(pbSAData, pData, cbData);
00912                     hr = SafeArrayUnaccessData(psa);
00913                 }
00914             }
00915 
00916             V_VT(&var) = VT_ARRAY | VT_UI1;
00917             V_UNION(&var, parray) = psa;
00918 
00919             if (SUCCEEDED(hr))
00920                 hr = IPropertyBag_Write(pPropBag, wszFilterDataName, &var);
00921 
00922             if (psa)
00923                 SafeArrayDestroy(psa);
00924             CoTaskMemFree(pData);
00925         }
00926     }
00927 
00928     if (pPropBag)
00929         IPropertyBag_Release(pPropBag);
00930     CoTaskMemFree(szClsidTemp);
00931     CoTaskMemFree(pwszParseName);
00932 
00933     if (SUCCEEDED(hr) && ppMoniker)
00934         *ppMoniker = pMoniker;
00935     else if (pMoniker)
00936         IMoniker_Release(pMoniker);
00937 
00938     CoTaskMemFree(pregfp2);
00939 
00940     TRACE("-- returning %x\n", hr);
00941 
00942     return hr;
00943 }
00944 
00945 /* internal helper function */
00946 static BOOL MatchTypes(
00947     BOOL bExactMatch,
00948     DWORD nPinTypes,
00949     const REGPINTYPES * pPinTypes,
00950     DWORD nMatchTypes,
00951     const GUID * pMatchTypes)
00952 {
00953     BOOL bMatch = FALSE;
00954     DWORD j;
00955 
00956     if ((nMatchTypes == 0) && (nPinTypes > 0))
00957         bMatch = TRUE;
00958 
00959     for (j = 0; j < nPinTypes; j++)
00960     {
00961         DWORD i;
00962         for (i = 0; i < nMatchTypes*2; i+=2)
00963         {
00964             if (((!bExactMatch && IsEqualGUID(pPinTypes[j].clsMajorType, &GUID_NULL)) || IsEqualGUID(&pMatchTypes[i], &GUID_NULL) || IsEqualGUID(pPinTypes[j].clsMajorType, &pMatchTypes[i])) &&
00965                 ((!bExactMatch && IsEqualGUID(pPinTypes[j].clsMinorType, &GUID_NULL)) || IsEqualGUID(&pMatchTypes[i+1], &GUID_NULL) || IsEqualGUID(pPinTypes[j].clsMinorType, &pMatchTypes[i+1])))
00966             {
00967                 bMatch = TRUE;
00968                 break;
00969             }
00970         }
00971     }
00972     return bMatch;
00973 }
00974 
00975 /* internal helper function for qsort of MONIKER_MERIT array */
00976 static int mm_compare(const void * left, const void * right)
00977 {
00978     const struct MONIKER_MERIT * mmLeft = left;
00979     const struct MONIKER_MERIT * mmRight = right;
00980 
00981     if (mmLeft->dwMerit == mmRight->dwMerit)
00982         return 0;
00983     if (mmLeft->dwMerit > mmRight->dwMerit)
00984         return -1;
00985     return 1;
00986 }
00987 
00988 /* NOTES:
00989  *   Exact match means whether or not to treat GUID_NULL's in filter data as wild cards
00990  *    (GUID_NULL's in input to function automatically treated as wild cards)
00991  *   Input/Output needed means match only on criteria if TRUE (with zero input types
00992  *    meaning match any input/output pin as long as one exists), otherwise match any
00993  *    filter that meets the rest of the requirements.
00994  */
00995 static HRESULT WINAPI FilterMapper2_EnumMatchingFilters(
00996     IFilterMapper2 * iface,
00997     IEnumMoniker **ppEnum,
00998     DWORD dwFlags,
00999     BOOL bExactMatch,
01000     DWORD dwMerit,
01001     BOOL bInputNeeded,
01002     DWORD cInputTypes,
01003     const GUID *pInputTypes,
01004     const REGPINMEDIUM *pMedIn,
01005     const CLSID *pPinCategoryIn,
01006     BOOL bRender,
01007     BOOL bOutputNeeded,
01008     DWORD cOutputTypes,
01009     const GUID *pOutputTypes,
01010     const REGPINMEDIUM *pMedOut,
01011     const CLSID *pPinCategoryOut)
01012 {
01013     ICreateDevEnum * pCreateDevEnum;
01014     IMoniker * pMonikerCat;
01015     IEnumMoniker * pEnumCat;
01016     HRESULT hr;
01017     struct Vector monikers = {NULL, 0, 0};
01018 
01019     TRACE("(%p, %x, %s, %x, %s, %d, %p, %p, %p, %s, %s, %p, %p, %p)\n",
01020         ppEnum,
01021         dwFlags,
01022         bExactMatch ? "true" : "false",
01023         dwMerit,
01024         bInputNeeded ? "true" : "false",
01025         cInputTypes,
01026         pInputTypes,
01027         pMedIn,
01028         pPinCategoryIn,
01029         bRender ? "true" : "false",
01030         bOutputNeeded ? "true" : "false",
01031         pOutputTypes,
01032         pMedOut,
01033         pPinCategoryOut);
01034 
01035     if (dwFlags != 0)
01036     {
01037         FIXME("dwFlags = %x not implemented\n", dwFlags);
01038     }
01039 
01040     *ppEnum = NULL;
01041 
01042     hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, &IID_ICreateDevEnum, (LPVOID*)&pCreateDevEnum);
01043     if (FAILED(hr))
01044         return hr;
01045 
01046     hr = ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum, &CLSID_ActiveMovieCategories, &pEnumCat, 0);
01047     if (FAILED(hr)) {
01048         ICreateDevEnum_Release(pCreateDevEnum);
01049         return hr;
01050     }
01051 
01052     while (IEnumMoniker_Next(pEnumCat, 1, &pMonikerCat, NULL) == S_OK)
01053     {
01054         IPropertyBag * pPropBagCat = NULL;
01055         VARIANT var;
01056         HRESULT hrSub; /* this is so that one buggy filter
01057                           doesn't make the whole lot fail */
01058 
01059         VariantInit(&var);
01060 
01061         hrSub = IMoniker_BindToStorage(pMonikerCat, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
01062 
01063         if (SUCCEEDED(hrSub))
01064             hrSub = IPropertyBag_Read(pPropBagCat, wszMeritName, &var, NULL);
01065 
01066         if (SUCCEEDED(hrSub) && (V_UNION(&var, ulVal) >= dwMerit))
01067         {
01068             CLSID clsidCat;
01069             IEnumMoniker * pEnum;
01070             IMoniker * pMoniker;
01071 
01072             VariantClear(&var);
01073 
01074             if (TRACE_ON(quartz))
01075             {
01076                 VARIANT temp;
01077                 V_VT(&temp) = VT_EMPTY;
01078                 IPropertyBag_Read(pPropBagCat, wszFriendlyName, &temp, NULL);
01079                 TRACE("Considering category %s\n", debugstr_w(V_UNION(&temp, bstrVal)));
01080                 VariantClear(&temp);
01081             }
01082 
01083             hrSub = IPropertyBag_Read(pPropBagCat, wszClsidName, &var, NULL);
01084 
01085             if (SUCCEEDED(hrSub))
01086                 hrSub = CLSIDFromString(V_UNION(&var, bstrVal), &clsidCat);
01087 
01088             if (SUCCEEDED(hrSub))
01089                 hrSub = ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum, &clsidCat, &pEnum, 0);
01090 
01091             if (hrSub == S_OK)
01092             {
01093                 while (IEnumMoniker_Next(pEnum, 1, &pMoniker, NULL) == S_OK)
01094                 {
01095                     IPropertyBag * pPropBag = NULL;
01096                     VARIANT var;
01097                     BYTE *pData = NULL;
01098                     REGFILTER2 rf2;
01099                     DWORD i;
01100                     BOOL bInputMatch = !bInputNeeded;
01101                     BOOL bOutputMatch = !bOutputNeeded;
01102 
01103                     ZeroMemory(&rf2, sizeof(rf2));
01104                     VariantInit(&var);
01105 
01106                     hrSub = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBag);
01107 
01108                     if (TRACE_ON(quartz))
01109                     {
01110                         VARIANT temp;
01111                         V_VT(&temp) = VT_EMPTY;
01112                         IPropertyBag_Read(pPropBag, wszFriendlyName, &temp, NULL);
01113                         TRACE("Considering filter %s\n", debugstr_w(V_UNION(&temp, bstrVal)));
01114                         VariantClear(&temp);
01115                     }
01116 
01117                     if (SUCCEEDED(hrSub))
01118                     {
01119                         hrSub = IPropertyBag_Read(pPropBag, wszFilterDataName, &var, NULL);
01120                     }
01121 
01122                     if (SUCCEEDED(hrSub))
01123                         hrSub = SafeArrayAccessData(V_UNION(&var, parray), (LPVOID*)&pData);
01124 
01125                     if (SUCCEEDED(hrSub))
01126                         hrSub = FM2_ReadFilterData(pData, &rf2);
01127 
01128                     if (pData)
01129                         SafeArrayUnaccessData(V_UNION(&var, parray));
01130 
01131                     VariantClear(&var);
01132 
01133                     /* Logic used for bInputMatch expression:
01134                      * There exists some pin such that bInputNeeded implies (pin is an input and
01135                      * (bRender implies pin has render flag) and major/minor types members of
01136                      * pInputTypes )
01137                      * bOutputMatch is similar, but without the "bRender implies ..." part
01138                      * and substituting variables names containing input for output
01139                      */
01140 
01141                     /* determine whether filter meets requirements */
01142                     if (SUCCEEDED(hrSub) && (rf2.dwMerit >= dwMerit))
01143                     {
01144                         for (i = 0; (i < rf2.u.s1.cPins2) && (!bInputMatch || !bOutputMatch); i++)
01145                         {
01146                             const REGFILTERPINS2 * rfp2 = rf2.u.s1.rgPins2 + i;
01147 
01148                             bInputMatch = bInputMatch || (!(rfp2->dwFlags & REG_PINFLAG_B_OUTPUT) &&
01149                                 (!bRender || (rfp2->dwFlags & REG_PINFLAG_B_RENDERER)) &&
01150                                 MatchTypes(bExactMatch, rfp2->nMediaTypes, rfp2->lpMediaType, cInputTypes, pInputTypes));
01151                             bOutputMatch = bOutputMatch || ((rfp2->dwFlags & REG_PINFLAG_B_OUTPUT) &&
01152                                 MatchTypes(bExactMatch, rfp2->nMediaTypes, rfp2->lpMediaType, cOutputTypes, pOutputTypes));
01153                         }
01154 
01155                         if (bInputMatch && bOutputMatch)
01156                         {
01157                             struct MONIKER_MERIT mm = {pMoniker, rf2.dwMerit};
01158                             IMoniker_AddRef(pMoniker);
01159                             add_data(&monikers, (LPBYTE)&mm, sizeof(mm));
01160                         }
01161                     }
01162 
01163                     FM2_DeleteRegFilter(&rf2);
01164                     if (pPropBag)
01165                         IPropertyBag_Release(pPropBag);
01166                     IMoniker_Release(pMoniker);
01167                 }
01168                 IEnumMoniker_Release(pEnum);
01169             }
01170         }
01171 
01172         VariantClear(&var);
01173         if (pPropBagCat)
01174             IPropertyBag_Release(pPropBagCat);
01175         IMoniker_Release(pMonikerCat);
01176     }
01177 
01178     if (SUCCEEDED(hr))
01179     {
01180         IMoniker ** ppMoniker;
01181         unsigned int i;
01182         ULONG nMonikerCount = monikers.current / sizeof(struct MONIKER_MERIT);
01183 
01184         /* sort the monikers in descending merit order */
01185         qsort(monikers.pData, nMonikerCount,
01186               sizeof(struct MONIKER_MERIT),
01187               mm_compare);
01188 
01189         /* construct an IEnumMoniker interface */
01190         ppMoniker = CoTaskMemAlloc(nMonikerCount * sizeof(IMoniker *));
01191         for (i = 0; i < nMonikerCount; i++)
01192         {
01193             /* no need to AddRef here as already AddRef'd above */
01194             ppMoniker[i] = ((struct MONIKER_MERIT *)monikers.pData)[i].pMoniker;
01195         }
01196         hr = EnumMonikerImpl_Create(ppMoniker, nMonikerCount, ppEnum);
01197         CoTaskMemFree(ppMoniker);
01198     }
01199 
01200     delete_vector(&monikers);
01201     IEnumMoniker_Release(pEnumCat);
01202     ICreateDevEnum_Release(pCreateDevEnum);
01203 
01204     return hr;
01205 }
01206 
01207 static const IFilterMapper2Vtbl fm2vtbl =
01208 {
01209 
01210     FilterMapper2_QueryInterface,
01211     FilterMapper2_AddRef,
01212     FilterMapper2_Release,
01213 
01214     FilterMapper2_CreateCategory,
01215     FilterMapper2_UnregisterFilter,
01216     FilterMapper2_RegisterFilter,
01217     FilterMapper2_EnumMatchingFilters
01218 };
01219 
01220 /*** IUnknown methods ***/
01221 
01222 static HRESULT WINAPI FilterMapper_QueryInterface(IFilterMapper * iface, REFIID riid, LPVOID *ppv)
01223 {
01224     FilterMapper2Impl *This = impl_from_IFilterMapper(iface);
01225 
01226     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
01227 
01228     return FilterMapper2_QueryInterface((IFilterMapper2*)&This->lpVtbl, riid, ppv);
01229 }
01230 
01231 static ULONG WINAPI FilterMapper_AddRef(IFilterMapper * iface)
01232 {
01233     FilterMapper2Impl *This = impl_from_IFilterMapper(iface);
01234 
01235     return FilterMapper2_AddRef((IFilterMapper2*)This);
01236 }
01237 
01238 static ULONG WINAPI FilterMapper_Release(IFilterMapper * iface)
01239 {
01240     FilterMapper2Impl *This = impl_from_IFilterMapper(iface);
01241 
01242     return FilterMapper2_Release((IFilterMapper2*)This);
01243 }
01244 
01245 /*** IFilterMapper methods ***/
01246 
01247 static HRESULT WINAPI FilterMapper_EnumMatchingFilters(
01248     IFilterMapper * iface,
01249     IEnumRegFilters **ppEnum,
01250     DWORD dwMerit,
01251     BOOL bInputNeeded,
01252     CLSID clsInMaj,
01253     CLSID clsInSub,
01254     BOOL bRender,
01255     BOOL bOutputNeeded,
01256     CLSID clsOutMaj,
01257     CLSID clsOutSub)
01258 {
01259     FilterMapper2Impl *This = impl_from_IFilterMapper(iface);
01260     GUID InputType[2];
01261     GUID OutputType[2];
01262     IEnumMoniker* ppEnumMoniker;
01263     IMoniker* IMon;
01264     ULONG nb;
01265     ULONG idx = 0, nb_mon = 0;
01266     REGFILTER* regfilters;
01267     HRESULT hr;
01268 
01269     TRACE("(%p/%p)->(%p, %x, %s, %s, %s, %s, %s, %s, %s) stub!\n",
01270         iface,This,
01271         ppEnum,
01272         dwMerit,
01273         bInputNeeded ? "true" : "false",
01274         debugstr_guid(&clsInMaj),
01275         debugstr_guid(&clsInSub),
01276         bRender ? "true" : "false",
01277         bOutputNeeded ? "true" : "false",
01278         debugstr_guid(&clsOutMaj),
01279         debugstr_guid(&clsOutSub));
01280 
01281     InputType[0] = clsInMaj;
01282     InputType[1] = clsInSub;
01283     OutputType[0] = clsOutMaj;
01284     OutputType[1] = clsOutSub;
01285 
01286     *ppEnum = NULL;
01287 
01288     hr = IFilterMapper2_EnumMatchingFilters((IFilterMapper2*)This,
01289                                        &ppEnumMoniker,
01290                                        0,
01291                                        TRUE,
01292                                        dwMerit,
01293                                        bInputNeeded,
01294                                        1,
01295                                        InputType,
01296                                        NULL,
01297                                        &GUID_NULL,
01298                                        bRender,
01299                                        bOutputNeeded,
01300                                        1,
01301                                        OutputType,
01302                                        NULL,
01303                                        &GUID_NULL);
01304 
01305     if (FAILED(hr))
01306         return hr;
01307     
01308     while(IEnumMoniker_Next(ppEnumMoniker, 1, &IMon, &nb) == S_OK)
01309     {
01310         IMoniker_Release(IMon);
01311         nb_mon++;
01312     }
01313 
01314     if (!nb_mon)
01315     {
01316         IEnumMoniker_Release(ppEnumMoniker);
01317         return IEnumRegFiltersImpl_Construct(NULL, 0, ppEnum);
01318     }
01319 
01320     regfilters = CoTaskMemAlloc(nb_mon * sizeof(REGFILTER));
01321     if (!regfilters)
01322     {
01323         IEnumMoniker_Release(ppEnumMoniker);
01324         return E_OUTOFMEMORY;
01325     }
01326     ZeroMemory(regfilters, nb_mon * sizeof(REGFILTER)); /* will prevent bad free of Name in case of error. */
01327     
01328     IEnumMoniker_Reset(ppEnumMoniker);
01329     while(IEnumMoniker_Next(ppEnumMoniker, 1, &IMon, &nb) == S_OK)
01330     {
01331         IPropertyBag * pPropBagCat = NULL;
01332         VARIANT var;
01333         HRESULT hrSub;
01334         GUID clsid;
01335         int len;
01336 
01337         VariantInit(&var);
01338 
01339         hrSub = IMoniker_BindToStorage(IMon, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
01340 
01341         if (SUCCEEDED(hrSub))
01342             hrSub = IPropertyBag_Read(pPropBagCat, wszClsidName, &var, NULL);
01343 
01344         if (SUCCEEDED(hrSub))
01345             hrSub = CLSIDFromString(V_UNION(&var, bstrVal), &clsid);
01346 
01347         VariantClear(&var);
01348 
01349         if (SUCCEEDED(hrSub))
01350             hrSub = IPropertyBag_Read(pPropBagCat, wszFriendlyName, &var, NULL);
01351 
01352         if (SUCCEEDED(hrSub))
01353         {
01354             len = (strlenW(V_UNION(&var, bstrVal))+1) * sizeof(WCHAR);
01355             if (!(regfilters[idx].Name = CoTaskMemAlloc(len*2)))
01356                 hr = E_OUTOFMEMORY;
01357         }
01358 
01359         if (SUCCEEDED(hrSub) && regfilters[idx].Name)
01360         {
01361             memcpy(regfilters[idx].Name, V_UNION(&var, bstrVal), len);
01362             regfilters[idx].Clsid = clsid;
01363             idx++;
01364         }
01365 
01366         if (pPropBagCat)
01367             IPropertyBag_Release(pPropBagCat);
01368         IMoniker_Release(IMon);
01369         VariantClear(&var);
01370     }
01371 
01372     if (SUCCEEDED(hr))
01373     {
01374         hr = IEnumRegFiltersImpl_Construct(regfilters, nb_mon, ppEnum);
01375     }
01376 
01377     for (idx = 0; idx < nb_mon; idx++)
01378         CoTaskMemFree(regfilters[idx].Name);
01379     CoTaskMemFree(regfilters);
01380     IEnumMoniker_Release(ppEnumMoniker);
01381     
01382     return hr;
01383 }
01384 
01385 
01386 static HRESULT WINAPI FilterMapper_RegisterFilter(IFilterMapper * iface, CLSID clsid, LPCWSTR szName, DWORD dwMerit)
01387 {
01388     HRESULT hr;
01389     LPWSTR wszClsid = NULL;
01390     HKEY hKey;
01391     LONG lRet;
01392     WCHAR wszKeyName[ARRAYSIZE(wszFilterSlash)-1 + (CHARS_IN_GUID-1) + 1];
01393 
01394     TRACE("(%p)->(%s, %s, %x)\n", iface, debugstr_guid(&clsid), debugstr_w(szName), dwMerit);
01395 
01396     hr = StringFromCLSID(&clsid, &wszClsid);
01397 
01398     if (SUCCEEDED(hr))
01399     {
01400         strcpyW(wszKeyName, wszFilterSlash);
01401         strcatW(wszKeyName, wszClsid);
01402     
01403         lRet = RegCreateKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
01404         hr = HRESULT_FROM_WIN32(lRet);
01405     }
01406 
01407     if (SUCCEEDED(hr))
01408     {
01409         lRet = RegSetValueExW(hKey, NULL, 0, REG_SZ, (const BYTE*)szName, (strlenW(szName) + 1) * sizeof(WCHAR));
01410         hr = HRESULT_FROM_WIN32(lRet);
01411         CloseHandle(hKey);
01412     }
01413 
01414     if (SUCCEEDED(hr))
01415     {
01416         strcpyW(wszKeyName, wszClsidSlash);
01417         strcatW(wszKeyName, wszClsid);
01418     
01419         lRet = RegCreateKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
01420         hr = HRESULT_FROM_WIN32(lRet);
01421     }
01422 
01423     if (SUCCEEDED(hr))
01424     {
01425         lRet = RegSetValueExW(hKey, wszMeritName, 0, REG_DWORD, (LPBYTE)&dwMerit, sizeof(dwMerit));
01426         hr = HRESULT_FROM_WIN32(lRet);
01427         CloseHandle(hKey);
01428     }
01429     
01430     CoTaskMemFree(wszClsid);
01431 
01432     return hr;
01433 }
01434 
01435 static HRESULT WINAPI FilterMapper_RegisterFilterInstance(IFilterMapper * iface, CLSID clsid, LPCWSTR szName, CLSID *MRId)
01436 {
01437     TRACE("(%p)->(%s, %s, %p)\n", iface, debugstr_guid(&clsid), debugstr_w(szName), MRId);
01438 
01439     /* Not implemented in Windows (tested on Win2k) */
01440 
01441     return E_NOTIMPL;
01442 }
01443 
01444 static HRESULT WINAPI FilterMapper_RegisterPin(
01445     IFilterMapper * iface,
01446     CLSID Filter,
01447     LPCWSTR szName,
01448     BOOL bRendered,
01449     BOOL bOutput,
01450     BOOL bZero,
01451     BOOL bMany,
01452     CLSID ConnectsToFilter,
01453     LPCWSTR ConnectsToPin)
01454 {
01455     HRESULT hr;
01456     LONG lRet;
01457     LPWSTR wszClsid = NULL;
01458     HKEY hKey = NULL;
01459     HKEY hPinsKey = NULL;
01460     WCHAR * wszPinsKeyName;
01461     WCHAR wszKeyName[ARRAYSIZE(wszClsidSlash)-1 + (CHARS_IN_GUID-1) + 1];
01462 
01463     TRACE("(%p)->(%s, %s, %d, %d, %d, %d, %s, %s)\n", iface, debugstr_guid(&Filter), debugstr_w(szName), bRendered,
01464                 bOutput, bZero, bMany, debugstr_guid(&ConnectsToFilter), debugstr_w(ConnectsToPin));
01465 
01466     hr = StringFromCLSID(&Filter, &wszClsid);
01467 
01468     if (SUCCEEDED(hr))
01469     {
01470         strcpyW(wszKeyName, wszClsidSlash);
01471         strcatW(wszKeyName, wszClsid);
01472 
01473         lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, KEY_WRITE, &hKey);
01474         hr = HRESULT_FROM_WIN32(lRet);
01475     }
01476 
01477     if (SUCCEEDED(hr))
01478     {
01479         wszPinsKeyName = CoTaskMemAlloc((strlenW(wszPins) + 1 + strlenW(szName) + 1) * 2);
01480         if (!wszPinsKeyName)
01481              hr = E_OUTOFMEMORY;
01482     }
01483 
01484     if (SUCCEEDED(hr))
01485     {
01486         strcpyW(wszPinsKeyName, wszPins);
01487         strcatW(wszPinsKeyName, wszSlash);
01488         strcatW(wszPinsKeyName, szName);
01489     
01490         lRet = RegCreateKeyExW(hKey, wszPinsKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hPinsKey, NULL);
01491         hr = HRESULT_FROM_WIN32(lRet);
01492         CoTaskMemFree(wszPinsKeyName);
01493     }
01494 
01495     if (SUCCEEDED(hr))
01496     {
01497         lRet = RegSetValueExW(hPinsKey, wszAllowedMany, 0, REG_DWORD, (LPBYTE)&bMany, sizeof(bMany));
01498         hr = HRESULT_FROM_WIN32(lRet);
01499     }
01500 
01501     if (SUCCEEDED(hr))
01502     {
01503         lRet = RegSetValueExW(hPinsKey, wszAllowedZero, 0, REG_DWORD, (LPBYTE)&bZero, sizeof(bZero));
01504         hr = HRESULT_FROM_WIN32(lRet);
01505     }
01506 
01507     if (SUCCEEDED(hr))
01508     {
01509         lRet = RegSetValueExW(hPinsKey, wszDirection, 0, REG_DWORD, (LPBYTE)&bOutput, sizeof(bOutput));
01510         hr = HRESULT_FROM_WIN32(lRet);
01511     }
01512 
01513     if (SUCCEEDED(hr))
01514     {
01515         lRet = RegSetValueExW(hPinsKey, wszIsRendered, 0, REG_DWORD, (LPBYTE)&bRendered, sizeof(bRendered));
01516         hr = HRESULT_FROM_WIN32(lRet);
01517     }
01518 
01519     if (SUCCEEDED(hr))
01520     {
01521         HKEY hkeyDummy = NULL;
01522 
01523         lRet = RegCreateKeyExW(hPinsKey, wszTypes, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyDummy, NULL);
01524         hr = HRESULT_FROM_WIN32(lRet);
01525 
01526         if (hkeyDummy) RegCloseKey(hkeyDummy);
01527     }
01528 
01529     CoTaskMemFree(wszClsid);
01530     if (hKey)
01531         CloseHandle(hKey);
01532     if (hPinsKey)
01533         CloseHandle(hPinsKey);
01534 
01535     return hr;
01536 }
01537 
01538 
01539 static HRESULT WINAPI FilterMapper_RegisterPinType(
01540     IFilterMapper * iface,
01541     CLSID clsFilter,
01542     LPCWSTR szName,
01543     CLSID clsMajorType,
01544     CLSID clsSubType)
01545 {
01546     HRESULT hr;
01547     LONG lRet;
01548     LPWSTR wszClsid = NULL;
01549     LPWSTR wszClsidMajorType = NULL;
01550     LPWSTR wszClsidSubType = NULL;
01551     HKEY hKey = NULL;
01552     WCHAR * wszTypesKey;
01553     WCHAR wszKeyName[MAX_PATH];
01554 
01555     TRACE("(%p)->(%s, %s, %s, %s)\n", iface, debugstr_guid(&clsFilter), debugstr_w(szName),
01556                     debugstr_guid(&clsMajorType), debugstr_guid(&clsSubType));
01557 
01558     hr = StringFromCLSID(&clsFilter, &wszClsid);
01559 
01560     if (SUCCEEDED(hr))
01561     {
01562         hr = StringFromCLSID(&clsMajorType, &wszClsidMajorType);
01563     }
01564 
01565     if (SUCCEEDED(hr))
01566     {
01567         hr = StringFromCLSID(&clsSubType, &wszClsidSubType);
01568     }
01569 
01570     if (SUCCEEDED(hr))
01571     {
01572         wszTypesKey = CoTaskMemAlloc((strlenW(wszClsidSlash) + strlenW(wszClsid) + strlenW(wszPins) +
01573                         strlenW(szName) + strlenW(wszTypes) + 3 + 1) * 2);
01574         if (!wszTypesKey)
01575             hr = E_OUTOFMEMORY;
01576     }
01577 
01578     if (SUCCEEDED(hr))
01579     {
01580         strcpyW(wszTypesKey, wszClsidSlash);
01581         strcatW(wszTypesKey, wszClsid);
01582         strcatW(wszTypesKey, wszSlash);
01583         strcatW(wszTypesKey, wszPins);
01584         strcatW(wszTypesKey, wszSlash);
01585         strcatW(wszTypesKey, szName);
01586         strcatW(wszTypesKey, wszSlash);
01587         strcatW(wszTypesKey, wszTypes);
01588 
01589         lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszTypesKey, 0, KEY_WRITE, &hKey);
01590         hr = HRESULT_FROM_WIN32(lRet);
01591         CoTaskMemFree(wszTypesKey);
01592     }
01593 
01594     if (SUCCEEDED(hr))
01595     {
01596         HKEY hkeyDummy = NULL;
01597 
01598         strcpyW(wszKeyName, wszClsidMajorType);
01599         strcatW(wszKeyName, wszSlash);
01600         strcatW(wszKeyName, wszClsidSubType);
01601 
01602         lRet = RegCreateKeyExW(hKey, wszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyDummy, NULL);
01603         hr = HRESULT_FROM_WIN32(lRet);
01604         CloseHandle(hKey);
01605 
01606         if (hkeyDummy) RegCloseKey(hkeyDummy);
01607     }
01608 
01609     CoTaskMemFree(wszClsid);
01610     CoTaskMemFree(wszClsidMajorType);
01611     CoTaskMemFree(wszClsidSubType);
01612 
01613     return hr;
01614 }
01615 
01616 static HRESULT WINAPI FilterMapper_UnregisterFilter(IFilterMapper * iface, CLSID Filter)
01617 {
01618     HRESULT hr;
01619     LONG lRet;
01620     LPWSTR wszClsid = NULL;
01621     HKEY hKey;
01622     WCHAR wszKeyName[ARRAYSIZE(wszClsidSlash)-1 + (CHARS_IN_GUID-1) + 1];
01623 
01624     TRACE("(%p)->(%s)\n", iface, debugstr_guid(&Filter));
01625 
01626     hr = StringFromCLSID(&Filter, &wszClsid);
01627 
01628     if (SUCCEEDED(hr))
01629     {
01630         lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszFilter, 0, KEY_WRITE, &hKey);
01631         hr = HRESULT_FROM_WIN32(lRet);
01632     }
01633 
01634     if (SUCCEEDED(hr))
01635     {
01636         lRet = RegDeleteKeyW(hKey, wszClsid);
01637         hr = HRESULT_FROM_WIN32(lRet);
01638         CloseHandle(hKey);
01639     }
01640 
01641     if (SUCCEEDED(hr))
01642     {
01643         strcpyW(wszKeyName, wszClsidSlash);
01644         strcatW(wszKeyName, wszClsid);
01645 
01646         lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, KEY_WRITE, &hKey);
01647         hr = HRESULT_FROM_WIN32(lRet);
01648     }
01649 
01650     if (SUCCEEDED(hr))
01651     {
01652         lRet = RegDeleteValueW(hKey, wszMeritName);
01653         if (lRet != ERROR_SUCCESS)
01654             hr = HRESULT_FROM_WIN32(lRet);
01655 
01656         lRet = RegDeleteTreeW(hKey, wszPins);
01657         if (lRet != ERROR_SUCCESS)
01658             hr = HRESULT_FROM_WIN32(lRet);
01659 
01660         CloseHandle(hKey);
01661     }
01662 
01663     CoTaskMemFree(wszClsid);
01664 
01665     return hr;
01666 }
01667 
01668 static HRESULT WINAPI FilterMapper_UnregisterFilterInstance(IFilterMapper * iface, CLSID MRId)
01669 {
01670     TRACE("(%p)->(%s)\n", iface, debugstr_guid(&MRId));
01671 
01672     /* Not implemented in Windows (tested on Win2k) */
01673 
01674     return E_NOTIMPL;
01675 }
01676 
01677 static HRESULT WINAPI FilterMapper_UnregisterPin(IFilterMapper * iface, CLSID Filter, LPCWSTR Name)
01678 {
01679     HRESULT hr;
01680     LONG lRet;
01681     LPWSTR wszClsid = NULL;
01682     HKEY hKey = NULL;
01683     WCHAR * wszPinNameKey;
01684     WCHAR wszKeyName[ARRAYSIZE(wszClsidSlash)-1 + (CHARS_IN_GUID-1) + 1];
01685 
01686     TRACE("(%p)->(%s, %s)\n", iface, debugstr_guid(&Filter), debugstr_w(Name));
01687 
01688     if (!Name)
01689         return E_INVALIDARG;
01690 
01691     hr = StringFromCLSID(&Filter, &wszClsid);
01692 
01693     if (SUCCEEDED(hr))
01694     {
01695         strcpyW(wszKeyName, wszClsidSlash);
01696         strcatW(wszKeyName, wszClsid);
01697 
01698         lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKeyName, 0, KEY_WRITE, &hKey);
01699         hr = HRESULT_FROM_WIN32(lRet);
01700     }
01701 
01702     if (SUCCEEDED(hr))
01703     {
01704         wszPinNameKey = CoTaskMemAlloc((strlenW(wszPins) + 1 + strlenW(Name) + 1) * 2);
01705         if (!wszPinNameKey)
01706             hr = E_OUTOFMEMORY;
01707     }
01708 
01709     if (SUCCEEDED(hr))
01710     {
01711         strcpyW(wszPinNameKey, wszPins);
01712         strcatW(wszPinNameKey, wszSlash);
01713         strcatW(wszPinNameKey, Name);
01714 
01715         lRet = RegDeleteTreeW(hKey, wszPinNameKey);
01716         hr = HRESULT_FROM_WIN32(lRet);
01717         CoTaskMemFree(wszPinNameKey);
01718     }
01719 
01720     CoTaskMemFree(wszClsid);
01721     if (hKey)
01722         CloseHandle(hKey);
01723 
01724     return hr;
01725 }
01726 
01727 static const IFilterMapperVtbl fmvtbl =
01728 {
01729 
01730     FilterMapper_QueryInterface,
01731     FilterMapper_AddRef,
01732     FilterMapper_Release,
01733 
01734     FilterMapper_RegisterFilter,
01735     FilterMapper_RegisterFilterInstance,
01736     FilterMapper_RegisterPin,
01737     FilterMapper_RegisterPinType,
01738     FilterMapper_UnregisterFilter,
01739     FilterMapper_UnregisterFilterInstance,
01740     FilterMapper_UnregisterPin,
01741     FilterMapper_EnumMatchingFilters
01742 };
01743 
01744 
01745 /*** IUnknown methods ***/
01746 static HRESULT WINAPI AMFilterData_QueryInterface(IAMFilterData * iface, REFIID riid, LPVOID *ppv)
01747 {
01748     FilterMapper2Impl *This = impl_from_IAMFilterData(iface);
01749 
01750     return FilterMapper2_QueryInterface((IFilterMapper2*)This, riid, ppv);
01751 }
01752 
01753 static ULONG WINAPI AMFilterData_AddRef(IAMFilterData * iface)
01754 {
01755     FilterMapper2Impl *This = impl_from_IAMFilterData(iface);
01756 
01757     return FilterMapper2_AddRef((IFilterMapper2*)This);
01758 }
01759 
01760 static ULONG WINAPI AMFilterData_Release(IAMFilterData * iface)
01761 {
01762     FilterMapper2Impl *This = impl_from_IAMFilterData(iface);
01763 
01764     return FilterMapper2_Release((IFilterMapper2*)This);
01765 }
01766 
01767 /*** IAMFilterData methods ***/
01768 static HRESULT WINAPI AMFilterData_ParseFilterData(IAMFilterData* iface,
01769                                                    BYTE *pData, ULONG cb,
01770                                                    BYTE **ppRegFilter2)
01771 {
01772     FilterMapper2Impl *This = impl_from_IAMFilterData(iface);
01773     HRESULT hr = S_OK;
01774     REGFILTER2 *prf2;
01775 
01776     TRACE("(%p/%p)->(%p, %d, %p)\n", This, iface, pData, cb, ppRegFilter2);
01777 
01778     prf2 = CoTaskMemAlloc(sizeof(*prf2));
01779     if (!prf2)
01780         return E_OUTOFMEMORY;
01781     *ppRegFilter2 = (BYTE *)prf2;
01782 
01783     hr = FM2_ReadFilterData(pData, prf2);
01784     if (FAILED(hr))
01785     {
01786         CoTaskMemFree(prf2);
01787         *ppRegFilter2 = NULL;
01788     }
01789 
01790     return hr;
01791 }
01792 
01793 static HRESULT WINAPI AMFilterData_CreateFilterData(IAMFilterData* iface,
01794                                                     REGFILTER2 *prf2,
01795                                                     BYTE **pRegFilterData,
01796                                                     ULONG *pcb)
01797 {
01798     FilterMapper2Impl *This = impl_from_IAMFilterData(iface);
01799 
01800     TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, prf2, pRegFilterData, pcb);
01801 
01802     return FM2_WriteFilterData(prf2, pRegFilterData, pcb);
01803 }
01804 
01805 static const IAMFilterDataVtbl AMFilterDataVtbl = {
01806     AMFilterData_QueryInterface,
01807     AMFilterData_AddRef,
01808     AMFilterData_Release,
01809     AMFilterData_ParseFilterData,
01810     AMFilterData_CreateFilterData
01811 };

Generated on Mon May 28 2012 04:21:27 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.