2 * IFilterMapper & IFilterMapper2 Implementations
4 * Copyright 2003 Robert Shearman
5 * Copyright 2004 Christian Costa
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
32 #include "quartz_private.h"
34 #define COM_NO_WINDOWS_H
38 #include "wine/unicode.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
45 typedef struct FilterMapper2Impl
47 ICOM_VFIELD(IFilterMapper2
);
48 ICOM_VTABLE(IFilterMapper
) * lpVtblFilterMapper
;
52 static struct ICOM_VTABLE(IFilterMapper2
) fm2vtbl
;
53 static struct ICOM_VTABLE(IFilterMapper
) fmvtbl
;
55 #define _IFilterMapper_Offset ((int)(&(((FilterMapper2Impl*)0)->lpVtblFilterMapper)))
56 #define ICOM_THIS_From_IFilterMapper(impl, iface) impl* This = (impl*)(((char*)iface)-_IFilterMapper_Offset)
58 static const WCHAR wszClsidSlash
[] = {'C','L','S','I','D','\\',0};
59 static const WCHAR wszSlashInstance
[] = {'\\','I','n','s','t','a','n','c','e','\\',0};
60 static const WCHAR wszSlash
[] = {'\\',0};
62 /* CLSID property in media category Moniker */
63 static const WCHAR wszClsidName
[] = {'C','L','S','I','D',0};
64 /* FriendlyName property in media category Moniker */
65 static const WCHAR wszFriendlyName
[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
66 /* Merit property in media category Moniker (CLSID_ActiveMovieCategories only) */
67 static const WCHAR wszMeritName
[] = {'M','e','r','i','t',0};
68 /* FilterData property in media category Moniker (not CLSID_ActiveMovieCategories) */
69 static const WCHAR wszFilterDataName
[] = {'F','i','l','t','e','r','D','a','t','a',0};
70 /* For filters registered with IFilterMapper */
71 static const WCHAR wszFilterSlash
[] = {'F','i','l','t','e','r','\\',0};
72 static const WCHAR wszFilter
[] = {'F','i','l','t','e','r',0};
73 /* For pins registered with IFilterMapper */
74 static const WCHAR wszPins
[] = {'P','i','n','s',0};
75 static const WCHAR wszAllowedMany
[] = {'A','l','l','o','w','e','d','M','a','n','y',0};
76 static const WCHAR wszAllowedZero
[] = {'A','l','l','o','w','e','d','Z','e','r','o',0};
77 static const WCHAR wszDirection
[] = {'D','i','r','e','c','t','i','o','n',0};
78 static const WCHAR wszIsRendered
[] = {'I','s','R','e','n','d','e','r','e','d',0};
79 /* For types registered with IFilterMapper */
80 static const WCHAR wszTypes
[] = {'T','y','p','e','s',0};
83 /* registry format for REGFILTER2 */
94 BYTE signature
[4]; /* e.g. "0pi3" */
99 DWORD bCategory
; /* is there a category clsid? */
100 /* optional: dwOffsetCategoryClsid */
105 BYTE signature
[4]; /* e.g. "0ty3" */
120 int capacity
; /* in bytes */
121 int current
; /* pointer to next free byte */
124 /* returns the position it was added at */
125 static int add_data(struct Vector
* v
, const BYTE
* pData
, int size
)
127 int index
= v
->current
;
128 if (v
->current
+ size
> v
->capacity
)
130 LPBYTE pOldData
= v
->pData
;
131 v
->capacity
= (v
->capacity
+ size
) * 2;
132 v
->pData
= CoTaskMemAlloc(v
->capacity
);
133 memcpy(v
->pData
, pOldData
, v
->current
);
134 CoTaskMemFree(pOldData
);
136 memcpy(v
->pData
+ v
->current
, pData
, size
);
141 static int find_data(struct Vector
* v
, const BYTE
* pData
, int size
)
144 for (index
= 0; index
< v
->current
; index
++)
145 if (!memcmp(v
->pData
+ index
, pData
, size
))
151 static void delete_vector(struct Vector
* v
)
154 CoTaskMemFree(v
->pData
);
159 HRESULT
FilterMapper2_create(IUnknown
*pUnkOuter
, LPVOID
*ppObj
)
161 FilterMapper2Impl
* pFM2impl
;
163 TRACE("(%p, %p)\n", pUnkOuter
, ppObj
);
166 return CLASS_E_NOAGGREGATION
;
168 pFM2impl
= CoTaskMemAlloc(sizeof(*pFM2impl
));
170 return E_OUTOFMEMORY
;
172 pFM2impl
->lpVtbl
= &fm2vtbl
;
173 pFM2impl
->lpVtblFilterMapper
= &fmvtbl
;
174 pFM2impl
->refCount
= 1;
178 TRACE("-- created at %p\n", pFM2impl
);
183 /*** IUnknown methods ***/
185 static HRESULT WINAPI
FilterMapper2_QueryInterface(IFilterMapper2
* iface
, REFIID riid
, LPVOID
*ppv
)
187 ICOM_THIS(FilterMapper2Impl
, iface
);
189 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
193 if (IsEqualIID(riid
, &IID_IUnknown
))
195 else if (IsEqualIID(riid
, &IID_IFilterMapper2
))
197 else if (IsEqualIID(riid
, &IID_IFilterMapper
))
198 *ppv
= &This
->lpVtblFilterMapper
;
202 IUnknown_AddRef((IUnknown
*)*ppv
);
206 FIXME("No interface for %s\n", debugstr_guid(riid
));
207 return E_NOINTERFACE
;
210 static ULONG WINAPI
FilterMapper2_AddRef(IFilterMapper2
* iface
)
212 ICOM_THIS(FilterMapper2Impl
, iface
);
214 TRACE("(%p)->()\n", iface
);
216 return InterlockedIncrement(&This
->refCount
);
219 static ULONG WINAPI
FilterMapper2_Release(IFilterMapper2
* iface
)
221 ICOM_THIS(FilterMapper2Impl
, iface
);
223 TRACE("(%p)->()\n", iface
);
225 if (InterlockedDecrement(&This
->refCount
) == 0)
230 return This
->refCount
;
233 /*** IFilterMapper2 methods ***/
235 static HRESULT WINAPI
FilterMapper2_CreateCategory(
236 IFilterMapper2
* iface
,
237 REFCLSID clsidCategory
,
238 DWORD dwCategoryMerit
,
239 LPCWSTR szDescription
)
241 LPWSTR wClsidAMCat
= NULL
;
242 LPWSTR wClsidCategory
= NULL
;
243 WCHAR wszKeyName
[strlenW(wszClsidSlash
) + strlenW(wszSlashInstance
) + (CHARS_IN_GUID
-1) * 2 + 1];
247 TRACE("(%s, %lx, %s)\n", debugstr_guid(clsidCategory
), dwCategoryMerit
, debugstr_w(szDescription
));
249 hr
= StringFromCLSID(&CLSID_ActiveMovieCategories
, &wClsidAMCat
);
253 hr
= StringFromCLSID(clsidCategory
, &wClsidCategory
);
258 strcpyW(wszKeyName
, wszClsidSlash
);
259 strcatW(wszKeyName
, wClsidAMCat
);
260 strcatW(wszKeyName
, wszSlashInstance
);
261 strcatW(wszKeyName
, wClsidCategory
);
263 hr
= HRESULT_FROM_WIN32(RegCreateKeyExW(HKEY_CLASSES_ROOT
, wszKeyName
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hKey
, NULL
));
268 hr
= HRESULT_FROM_WIN32(RegSetValueExW(hKey
, wszFriendlyName
, 0, REG_SZ
, (LPBYTE
)szDescription
, strlenW(szDescription
) + 1));
273 hr
= HRESULT_FROM_WIN32(RegSetValueExW(hKey
, wszClsidName
, 0, REG_SZ
, (LPBYTE
)wClsidCategory
, strlenW(wClsidCategory
) + 1));
278 hr
= HRESULT_FROM_WIN32(RegSetValueExW(hKey
, wszMeritName
, 0, REG_DWORD
, (LPBYTE
)&dwCategoryMerit
, sizeof(dwCategoryMerit
)));
284 CoTaskMemFree(wClsidCategory
);
286 CoTaskMemFree(wClsidAMCat
);
291 static HRESULT WINAPI
FilterMapper2_UnregisterFilter(
292 IFilterMapper2
* iface
,
293 const CLSID
*pclsidCategory
,
294 const OLECHAR
*szInstance
,
297 WCHAR wszKeyName
[MAX_PATH
];
298 LPWSTR wClsidCategory
= NULL
;
299 LPWSTR wFilter
= NULL
;
302 TRACE("(%p, %s, %s)\n", pclsidCategory
, debugstr_w(szInstance
), debugstr_guid(Filter
));
305 pclsidCategory
= &CLSID_LegacyAmFilterCategory
;
307 hr
= StringFromCLSID(pclsidCategory
, &wClsidCategory
);
311 strcpyW(wszKeyName
, wszClsidSlash
);
312 strcatW(wszKeyName
, wClsidCategory
);
313 strcatW(wszKeyName
, wszSlashInstance
);
315 strcatW(wszKeyName
, szInstance
);
318 hr
= StringFromCLSID(Filter
, &wFilter
);
320 strcatW(wszKeyName
, wFilter
);
326 hr
= HRESULT_FROM_WIN32(RegDeleteKeyW(HKEY_CLASSES_ROOT
, wszKeyName
));
330 CoTaskMemFree(wClsidCategory
);
332 CoTaskMemFree(wFilter
);
337 static HRESULT
FM2_WriteFriendlyName(IPropertyBag
* pPropBag
, LPCWSTR szName
)
341 V_VT(&var
) = VT_BSTR
;
342 V_UNION(&var
, bstrVal
) = (BSTR
)szName
;
344 return IPropertyBag_Write(pPropBag
, wszFriendlyName
, &var
);
347 static HRESULT
FM2_WriteClsid(IPropertyBag
* pPropBag
, REFCLSID clsid
)
349 LPWSTR wszClsid
= NULL
;
353 hr
= StringFromCLSID(clsid
, &wszClsid
);
357 V_VT(&var
) = VT_BSTR
;
358 V_UNION(&var
, bstrVal
) = wszClsid
;
359 hr
= IPropertyBag_Write(pPropBag
, wszClsidName
, &var
);
362 CoTaskMemFree(wszClsid
);
366 static HRESULT
FM2_WriteFilterData(IPropertyBag
* pPropBag
, const REGFILTER2
* prf2
)
369 int size
= sizeof(struct REG_RF
);
371 struct Vector mainStore
= {NULL
, 0, 0};
372 struct Vector clsidStore
= {NULL
, 0, 0};
375 SAFEARRAYBOUND saBound
;
378 rrf
.dwVersion
= prf2
->dwVersion
;
379 rrf
.dwMerit
= prf2
->dwMerit
;
380 rrf
.dwPins
= prf2
->u
.s1
.cPins2
;
383 add_data(&mainStore
, (LPBYTE
)&rrf
, sizeof(rrf
));
385 for (i
= 0; i
< prf2
->u
.s1
.cPins2
; i
++)
387 size
+= sizeof(struct REG_RFP
);
388 if (prf2
->u
.s1
.rgPins2
[i
].clsPinCategory
)
389 size
+= sizeof(DWORD
);
390 size
+= prf2
->u
.s1
.rgPins2
[i
].nMediaTypes
* sizeof(struct REG_TYPE
);
391 size
+= prf2
->u
.s1
.rgPins2
[i
].nMediums
* sizeof(DWORD
);
394 for (i
= 0; i
< prf2
->u
.s1
.cPins2
; i
++)
397 REGFILTERPINS2 rgPin2
= prf2
->u
.s1
.rgPins2
[i
];
400 rrfp
.signature
[0] = '0';
401 rrfp
.signature
[1] = 'p';
402 rrfp
.signature
[2] = 'i';
403 rrfp
.signature
[3] = '3';
404 rrfp
.signature
[0] += i
;
405 rrfp
.dwFlags
= rgPin2
.dwFlags
;
406 rrfp
.dwInstances
= rgPin2
.cInstances
;
407 rrfp
.dwMediaTypes
= rgPin2
.nMediaTypes
;
408 rrfp
.dwMediums
= rgPin2
.nMediums
;
409 rrfp
.bCategory
= rgPin2
.clsPinCategory
? 1 : 0;
411 add_data(&mainStore
, (LPBYTE
)&rrfp
, sizeof(rrfp
));
414 DWORD index
= find_data(&clsidStore
, (LPBYTE
)rgPin2
.clsPinCategory
, sizeof(CLSID
));
416 index
= add_data(&clsidStore
, (LPBYTE
)rgPin2
.clsPinCategory
, sizeof(CLSID
));
419 add_data(&mainStore
, (LPBYTE
)&index
, sizeof(index
));
422 for (j
= 0; j
< rgPin2
.nMediaTypes
; j
++)
425 rt
.signature
[0] = '0';
426 rt
.signature
[1] = 't';
427 rt
.signature
[2] = 'y';
428 rt
.signature
[3] = '3';
429 rt
.signature
[0] += j
;
432 rt
.dwOffsetMajor
= find_data(&clsidStore
, (LPBYTE
)rgPin2
.lpMediaType
[j
].clsMajorType
, sizeof(CLSID
));
433 if (rt
.dwOffsetMajor
== -1)
434 rt
.dwOffsetMajor
= add_data(&clsidStore
, (LPBYTE
)rgPin2
.lpMediaType
[j
].clsMajorType
, sizeof(CLSID
));
435 rt
.dwOffsetMajor
+= size
;
436 rt
.dwOffsetMinor
= find_data(&clsidStore
, (LPBYTE
)rgPin2
.lpMediaType
[j
].clsMinorType
, sizeof(CLSID
));
437 if (rt
.dwOffsetMinor
== -1)
438 rt
.dwOffsetMinor
= add_data(&clsidStore
, (LPBYTE
)rgPin2
.lpMediaType
[j
].clsMinorType
, sizeof(CLSID
));
439 rt
.dwOffsetMinor
+= size
;
441 add_data(&mainStore
, (LPBYTE
)&rt
, sizeof(rt
));
444 for (j
= 0; j
< rgPin2
.nMediums
; j
++)
446 DWORD index
= find_data(&clsidStore
, (LPBYTE
)(rgPin2
.lpMedium
+ j
), sizeof(REGPINMEDIUM
));
448 index
= add_data(&clsidStore
, (LPBYTE
)(rgPin2
.lpMedium
+ j
), sizeof(REGPINMEDIUM
));
451 add_data(&mainStore
, (LPBYTE
)&index
, sizeof(index
));
456 saBound
.cElements
= mainStore
.current
+ clsidStore
.current
;
457 psa
= SafeArrayCreate(VT_UI1
, 1, &saBound
);
460 ERR("Couldn't create SAFEARRAY\n");
467 hr
= SafeArrayAccessData(psa
, (LPVOID
*)&pbSAData
);
470 memcpy(pbSAData
, mainStore
.pData
, mainStore
.current
);
471 memcpy(pbSAData
+ mainStore
.current
, clsidStore
.pData
, clsidStore
.current
);
472 hr
= SafeArrayUnaccessData(psa
);
476 V_VT(&var
) = VT_ARRAY
| VT_UI1
;
477 V_UNION(&var
, parray
) = psa
;
480 hr
= IPropertyBag_Write(pPropBag
, wszFilterDataName
, &var
);
483 SafeArrayDestroy(psa
);
485 delete_vector(&mainStore
);
486 delete_vector(&clsidStore
);
490 static HRESULT
FM2_ReadFilterData(IPropertyBag
* pPropBag
, REGFILTER2
* prf2
)
495 struct REG_RF
* prrf
;
498 REGFILTERPINS2
* rgPins2
;
501 V_VT(&var
) = VT_ARRAY
| VT_UI1
;
503 hr
= IPropertyBag_Read(pPropBag
, wszFilterDataName
, &var
, NULL
);
506 hr
= SafeArrayAccessData(V_UNION(&var
, parray
), (LPVOID
*)&pData
);
510 prrf
= (struct REG_RF
*)pData
;
513 if (prrf
->dwVersion
!= 2)
515 FIXME("Filter registry version %ld not supported\n", prrf
->dwVersion
);
516 ZeroMemory(prf2
, sizeof(*prf2
));
523 TRACE("version = %ld, merit = %lx, #pins = %ld, unused = %lx\n",
524 prrf
->dwVersion
, prrf
->dwMerit
, prrf
->dwPins
, prrf
->dwUnused
);
526 prf2
->dwVersion
= prrf
->dwVersion
;
527 prf2
->dwMerit
= prrf
->dwMerit
;
528 prf2
->u
.s1
.cPins2
= prrf
->dwPins
;
529 rgPins2
= CoTaskMemAlloc(prrf
->dwPins
* sizeof(*rgPins2
));
530 prf2
->u
.s1
.rgPins2
= rgPins2
;
531 pCurrent
+= sizeof(struct REG_RF
);
533 for (i
= 0; i
< prrf
->dwPins
; i
++)
535 struct REG_RFP
* prrfp
= (struct REG_RFP
*)pCurrent
;
536 REGPINTYPES
* lpMediaType
;
537 REGPINMEDIUM
* lpMedium
;
540 /* FIXME: check signature */
542 TRACE("\tsignature = %s\n", debugstr_an(prrfp
->signature
, 4));
544 TRACE("\tpin[%ld]: flags = %lx, instances = %ld, media types = %ld, mediums = %ld\n",
545 i
, prrfp
->dwFlags
, prrfp
->dwInstances
, prrfp
->dwMediaTypes
, prrfp
->dwMediums
);
547 rgPins2
[i
].dwFlags
= prrfp
->dwFlags
;
548 rgPins2
[i
].cInstances
= prrfp
->dwInstances
;
549 rgPins2
[i
].nMediaTypes
= prrfp
->dwMediaTypes
;
550 rgPins2
[i
].nMediums
= prrfp
->dwMediums
;
551 pCurrent
+= sizeof(struct REG_RFP
);
552 if (prrfp
->bCategory
)
554 CLSID
* clsCat
= CoTaskMemAlloc(sizeof(CLSID
));
555 memcpy(clsCat
, pData
+ *(DWORD
*)(pCurrent
), sizeof(CLSID
));
556 pCurrent
+= sizeof(DWORD
);
557 rgPins2
[i
].clsPinCategory
= clsCat
;
560 rgPins2
[i
].clsPinCategory
= NULL
;
562 if (rgPins2
[i
].nMediaTypes
> 0)
563 lpMediaType
= CoTaskMemAlloc(rgPins2
[i
].nMediaTypes
* sizeof(*lpMediaType
));
567 rgPins2
[i
].lpMediaType
= lpMediaType
;
569 for (j
= 0; j
< rgPins2
[i
].nMediaTypes
; j
++)
571 struct REG_TYPE
* prt
= (struct REG_TYPE
*)pCurrent
;
572 CLSID
* clsMajor
= CoTaskMemAlloc(sizeof(CLSID
));
573 CLSID
* clsMinor
= CoTaskMemAlloc(sizeof(CLSID
));
575 /* FIXME: check signature */
576 TRACE("\t\tsignature = %s\n", debugstr_an(prt
->signature
, 4));
578 memcpy(clsMajor
, pData
+ prt
->dwOffsetMajor
, sizeof(CLSID
));
579 memcpy(clsMinor
, pData
+ prt
->dwOffsetMinor
, sizeof(CLSID
));
581 lpMediaType
[j
].clsMajorType
= clsMajor
;
582 lpMediaType
[j
].clsMinorType
= clsMinor
;
584 pCurrent
+= sizeof(*prt
);
587 if (rgPins2
[i
].nMediums
> 0)
588 lpMedium
= CoTaskMemAlloc(rgPins2
[i
].nMediums
* sizeof(*lpMedium
));
592 rgPins2
[i
].lpMedium
= lpMedium
;
594 for (j
= 0; j
< rgPins2
[i
].nMediums
; j
++)
596 DWORD dwOffset
= *(DWORD
*)pCurrent
;
598 memcpy(lpMedium
+ j
, pData
+ dwOffset
, sizeof(REGPINMEDIUM
));
600 pCurrent
+= sizeof(dwOffset
);
607 SafeArrayUnaccessData(V_UNION(&var
, parray
));
614 static void FM2_DeleteRegFilter(REGFILTER2
* prf2
)
617 for (i
= 0; i
< prf2
->u
.s1
.cPins2
; i
++)
620 if (prf2
->u
.s1
.rgPins2
[i
].clsPinCategory
)
621 CoTaskMemFree((LPVOID
)prf2
->u
.s1
.rgPins2
[i
].clsPinCategory
);
623 for (j
= 0; j
< prf2
->u
.s1
.rgPins2
[i
].nMediaTypes
; j
++)
625 CoTaskMemFree((LPVOID
)prf2
->u
.s1
.rgPins2
[i
].lpMediaType
[j
].clsMajorType
);
626 CoTaskMemFree((LPVOID
)prf2
->u
.s1
.rgPins2
[i
].lpMediaType
[j
].clsMinorType
);
628 CoTaskMemFree((LPVOID
)prf2
->u
.s1
.rgPins2
[i
].lpMedium
);
632 static HRESULT WINAPI
FilterMapper2_RegisterFilter(
633 IFilterMapper2
* iface
,
634 REFCLSID clsidFilter
,
636 IMoniker
**ppMoniker
,
637 const CLSID
*pclsidCategory
,
638 const OLECHAR
*szInstance
,
639 const REGFILTER2
*prf2
)
641 IParseDisplayName
* pParser
= NULL
;
642 IBindCtx
* pBindCtx
= NULL
;
643 IMoniker
* pMoniker
= NULL
;
644 IPropertyBag
* pPropBag
= NULL
;
646 LPWSTR pwszParseName
= NULL
;
648 static const WCHAR wszDevice
[] = {'@','d','e','v','i','c','e',':','s','w',':',0};
651 LPWSTR szClsidTemp
= NULL
;
653 TRACE("(%s, %s, %p, %s, %s, %p)\n",
654 debugstr_guid(clsidFilter
),
657 debugstr_guid(pclsidCategory
),
658 debugstr_w(szInstance
),
661 if (prf2
->dwVersion
!= 2)
663 FIXME("dwVersion != 2 not supported at the moment\n");
671 pclsidCategory
= &CLSID_ActiveMovieCategories
;
673 /* sizeof... will include null terminator and
674 * the + 1 is for the separator ('\\'). The -1 is
675 * because CHARS_IN_GUID includes the null terminator
677 nameLen
= sizeof(wszDevice
)/sizeof(wszDevice
[0]) + CHARS_IN_GUID
- 1 + 1;
680 nameLen
+= strlenW(szInstance
);
682 nameLen
+= CHARS_IN_GUID
- 1; /* CHARS_IN_GUID includes null terminator */
684 pCurrent
= pwszParseName
= CoTaskMemAlloc(nameLen
*sizeof(WCHAR
));
686 return E_OUTOFMEMORY
;
688 strcpyW(pwszParseName
, wszDevice
);
689 pCurrent
+= strlenW(wszDevice
);
691 hr
= StringFromCLSID(pclsidCategory
, &szClsidTemp
);
695 strncpyW(pCurrent
, szClsidTemp
, CHARS_IN_GUID
);
696 pCurrent
+= CHARS_IN_GUID
- 1;
700 strcpyW(pCurrent
+1, szInstance
);
705 CoTaskMemFree(szClsidTemp
);
708 hr
= StringFromCLSID(clsidFilter
, &szClsidTemp
);
710 strcpyW(pCurrent
+1, szClsidTemp
);
715 hr
= CoCreateInstance(&CLSID_CDeviceMoniker
, NULL
, CLSCTX_INPROC
, &IID_IParseDisplayName
, (LPVOID
*)&pParser
);
718 hr
= CreateBindCtx(0, &pBindCtx
);
721 hr
= IParseDisplayName_ParseDisplayName(pParser
, pBindCtx
, pwszParseName
, &ulEaten
, &pMoniker
);
724 IBindCtx_Release(pBindCtx
); pBindCtx
= NULL
;
726 IParseDisplayName_Release(pParser
); pParser
= NULL
;
729 hr
= IMoniker_BindToStorage(pMoniker
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
)&pPropBag
);
732 hr
= FM2_WriteFriendlyName(pPropBag
, szName
);
735 hr
= FM2_WriteClsid(pPropBag
, clsidFilter
);
738 hr
= FM2_WriteFilterData(pPropBag
, prf2
);
741 IPropertyBag_Release(pPropBag
); pPropBag
= NULL
;
743 CoTaskMemFree(szClsidTemp
);
745 if (SUCCEEDED(hr
) && ppMoniker
)
746 *ppMoniker
= pMoniker
;
748 IMoniker_Release(pMoniker
); pMoniker
= NULL
;
750 TRACE("-- returning %lx\n", hr
);
755 /* internal helper function */
756 static BOOL
MatchTypes(
759 const REGPINTYPES
* pPinTypes
,
761 const GUID
* pMatchTypes
)
766 if ((nMatchTypes
== 0) && (nPinTypes
> 0))
769 for (j
= 0; j
< nPinTypes
; j
++)
772 for (i
= 0; i
< nMatchTypes
*2; i
+=2)
774 if (((!bExactMatch
&& IsEqualGUID(pPinTypes
[j
].clsMajorType
, &GUID_NULL
)) || IsEqualGUID(&pMatchTypes
[i
], &GUID_NULL
) || IsEqualGUID(pPinTypes
[j
].clsMajorType
, &pMatchTypes
[i
])) &&
775 ((!bExactMatch
&& IsEqualGUID(pPinTypes
[j
].clsMinorType
, &GUID_NULL
)) || IsEqualGUID(&pMatchTypes
[i
+1], &GUID_NULL
) || IsEqualGUID(pPinTypes
[j
].clsMinorType
, &pMatchTypes
[i
+1])))
785 /* internal helper function for qsort of MONIKER_MERIT array */
786 static int mm_compare(const void * left
, const void * right
)
788 const struct MONIKER_MERIT
* mmLeft
= (struct MONIKER_MERIT
*)left
;
789 const struct MONIKER_MERIT
* mmRight
= (struct MONIKER_MERIT
*)right
;
791 if (mmLeft
->dwMerit
== mmRight
->dwMerit
)
793 if (mmLeft
->dwMerit
> mmRight
->dwMerit
)
799 * Exact match means whether or not to treat GUID_NULL's in filter data as wild cards
800 * (GUID_NULL's in input to function automatically treated as wild cards)
801 * Input/Output needed means match only on criteria if TRUE (with zero input types
802 * meaning match any input/output pin as long as one exists), otherwise match any
803 * filter that meets the rest of the requirements.
805 static HRESULT WINAPI
FilterMapper2_EnumMatchingFilters(
806 IFilterMapper2
* iface
,
807 IEnumMoniker
**ppEnum
,
813 const GUID
*pInputTypes
,
814 const REGPINMEDIUM
*pMedIn
,
815 const CLSID
*pPinCategoryIn
,
819 const GUID
*pOutputTypes
,
820 const REGPINMEDIUM
*pMedOut
,
821 const CLSID
*pPinCategoryOut
)
823 ICreateDevEnum
* pCreateDevEnum
;
824 IMoniker
* pMonikerCat
;
825 IEnumMoniker
* pEnumCat
;
827 struct Vector monikers
= {NULL
, 0, 0};
829 TRACE("(%p, %lx, %s, %lx, %s, %ld, %p, %p, %p, %s, %s, %p, %p, %p)\n",
832 bExactMatch
? "true" : "false",
834 bInputNeeded
? "true" : "false",
839 bRender
? "true" : "false",
840 bOutputNeeded
? "true" : "false",
847 FIXME("dwFlags = %lx not implemented\n", dwFlags
);
852 hr
= CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC
, &IID_ICreateDevEnum
, (LPVOID
*)&pCreateDevEnum
);
855 hr
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &CLSID_ActiveMovieCategories
, &pEnumCat
, 0);
857 while (IEnumMoniker_Next(pEnumCat
, 1, &pMonikerCat
, NULL
) == S_OK
)
859 IPropertyBag
* pPropBagCat
= NULL
;
861 HRESULT hrSub
; /* this is so that one buggy filter
862 doesn't make the whole lot fail */
866 hrSub
= IMoniker_BindToStorage(pMonikerCat
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBagCat
);
868 if (SUCCEEDED(hrSub
))
869 hrSub
= IPropertyBag_Read(pPropBagCat
, wszMeritName
, &var
, NULL
);
871 if (SUCCEEDED(hrSub
) && (V_UNION(&var
, ulVal
) >= dwMerit
))
874 IEnumMoniker
* pEnum
;
879 if (TRACE_ON(quartz
))
882 V_VT(&temp
) = VT_EMPTY
;
883 IPropertyBag_Read(pPropBagCat
, wszFriendlyName
, &temp
, NULL
);
884 TRACE("Considering category %s\n", debugstr_w(V_UNION(&temp
, bstrVal
)));
888 hrSub
= IPropertyBag_Read(pPropBagCat
, wszClsidName
, &var
, NULL
);
890 if (SUCCEEDED(hrSub
))
891 hrSub
= CLSIDFromString(V_UNION(&var
, bstrVal
), &clsidCat
);
893 if (SUCCEEDED(hrSub
))
894 hrSub
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &clsidCat
, &pEnum
, 0);
898 while (IEnumMoniker_Next(pEnum
, 1, &pMoniker
, NULL
) == S_OK
)
900 IPropertyBag
* pPropBag
= NULL
;
903 BOOL bInputMatch
= !bInputNeeded
;
904 BOOL bOutputMatch
= !bOutputNeeded
;
906 ZeroMemory(&rf2
, sizeof(rf2
));
908 hrSub
= IMoniker_BindToStorage(pMoniker
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBag
);
910 if (SUCCEEDED(hrSub
))
911 hrSub
= FM2_ReadFilterData(pPropBag
, &rf2
);
913 /* Logic used for bInputMatch expression:
914 * There exists some pin such that bInputNeeded implies (pin is an input and
915 * (bRender implies pin has render flag) and major/minor types members of
917 * bOutputMatch is similar, but without the "bRender implies ..." part
918 * and substituting variables names containing input for output
921 /* determine whether filter meets requirements */
922 if (SUCCEEDED(hrSub
) && (rf2
.dwMerit
>= dwMerit
))
924 for (i
= 0; (i
< rf2
.u
.s1
.cPins2
) && (!bInputMatch
|| !bOutputMatch
); i
++)
926 const REGFILTERPINS2
* rfp2
= rf2
.u
.s1
.rgPins2
+ i
;
928 bInputMatch
= bInputMatch
|| (!(rfp2
->dwFlags
& REG_PINFLAG_B_OUTPUT
) &&
929 (!bRender
|| (rfp2
->dwFlags
& REG_PINFLAG_B_RENDERER
)) &&
930 MatchTypes(bExactMatch
, rfp2
->nMediaTypes
, rfp2
->lpMediaType
, cInputTypes
, pInputTypes
));
931 bOutputMatch
= bOutputMatch
|| ((rfp2
->dwFlags
& REG_PINFLAG_B_OUTPUT
) &&
932 MatchTypes(bExactMatch
, rfp2
->nMediaTypes
, rfp2
->lpMediaType
, cOutputTypes
, pOutputTypes
));
935 if (bInputMatch
&& bOutputMatch
)
937 struct MONIKER_MERIT mm
= {pMoniker
, rf2
.dwMerit
};
938 IMoniker_AddRef(pMoniker
);
939 add_data(&monikers
, (LPBYTE
)&mm
, sizeof(mm
));
943 FM2_DeleteRegFilter(&rf2
);
945 IPropertyBag_Release(pPropBag
);
946 IMoniker_Release(pMoniker
);
948 IEnumMoniker_Release(pEnum
);
954 IPropertyBag_Release(pPropBagCat
);
955 IMoniker_Release(pMonikerCat
);
960 IMoniker
** ppMoniker
;
962 ULONG nMonikerCount
= monikers
.current
/ sizeof(struct MONIKER_MERIT
);
964 /* sort the monikers in descending merit order */
965 qsort(monikers
.pData
, nMonikerCount
,
966 sizeof(struct MONIKER_MERIT
),
969 /* construct an IEnumMoniker interface */
970 ppMoniker
= CoTaskMemAlloc(nMonikerCount
* sizeof(IMoniker
*));
971 for (i
= 0; i
< nMonikerCount
; i
++)
973 /* no need to AddRef here as already AddRef'd above */
974 ppMoniker
[i
] = ((struct MONIKER_MERIT
*)monikers
.pData
)[i
].pMoniker
;
976 hr
= EnumMonikerImpl_Create(ppMoniker
, nMonikerCount
, ppEnum
);
977 CoTaskMemFree(ppMoniker
);
980 delete_vector(&monikers
);
981 IEnumMoniker_Release(pEnumCat
);
982 ICreateDevEnum_Release(pCreateDevEnum
);
987 static ICOM_VTABLE(IFilterMapper2
) fm2vtbl
=
989 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
991 FilterMapper2_QueryInterface
,
992 FilterMapper2_AddRef
,
993 FilterMapper2_Release
,
995 FilterMapper2_CreateCategory
,
996 FilterMapper2_UnregisterFilter
,
997 FilterMapper2_RegisterFilter
,
998 FilterMapper2_EnumMatchingFilters
1001 /*** IUnknown methods ***/
1003 static HRESULT WINAPI
FilterMapper_QueryInterface(IFilterMapper
* iface
, REFIID riid
, LPVOID
*ppv
)
1005 ICOM_THIS_From_IFilterMapper(FilterMapper2Impl
, iface
);
1007 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
1009 return FilterMapper2_QueryInterface((IFilterMapper2
*)&This
->lpVtbl
, riid
, ppv
);
1012 static ULONG WINAPI
FilterMapper_AddRef(IFilterMapper
* iface
)
1014 ICOM_THIS_From_IFilterMapper(FilterMapper2Impl
, iface
);
1016 return FilterMapper2_AddRef((IFilterMapper2
*)This
);
1019 static ULONG WINAPI
FilterMapper_Release(IFilterMapper
* iface
)
1021 ICOM_THIS_From_IFilterMapper(FilterMapper2Impl
, iface
);
1023 return FilterMapper2_Release((IFilterMapper2
*)This
);
1026 /*** IFilterMapper methods ***/
1028 static HRESULT WINAPI
FilterMapper_EnumMatchingFilters(
1029 IFilterMapper
* iface
,
1030 IEnumRegFilters
**ppEnum
,
1040 ICOM_THIS_From_IFilterMapper(FilterMapper2Impl
, iface
);
1043 IEnumMoniker
* ppEnumMoniker
;
1046 ULONG idx
= 0, nb_mon
= 0;
1047 REGFILTER
* regfilters
;
1050 TRACE("(%p/%p)->(%p, %lx, %s, %s, %s, %s, %s, %s, %s) stub!\n",
1054 bInputNeeded
? "true" : "false",
1055 debugstr_guid(&clsInMaj
),
1056 debugstr_guid(&clsInSub
),
1057 bRender
? "true" : "false",
1058 bOutputNeeded
? "true" : "false",
1059 debugstr_guid(&clsOutMaj
),
1060 debugstr_guid(&clsOutSub
));
1062 InputType
[0] = clsInMaj
;
1063 InputType
[1] = clsInSub
;
1064 OutputType
[0] = clsOutMaj
;
1065 OutputType
[1] = clsOutSub
;
1067 hr
= IFilterMapper2_EnumMatchingFilters((IFilterMapper2
*)This
,
1087 while(IEnumMoniker_Next(ppEnumMoniker
, 1, &IMon
, &nb
) == S_OK
)
1089 IMoniker_Release(IMon
);
1096 IEnumMoniker_Release(ppEnumMoniker
);
1097 return IEnumRegFiltersImpl_Construct(NULL
, 0, ppEnum
);
1100 regfilters
= CoTaskMemAlloc(nb_mon
* sizeof(REGFILTER
));
1103 IEnumMoniker_Release(ppEnumMoniker
);
1104 return E_OUTOFMEMORY
;
1107 IEnumMoniker_Reset(ppEnumMoniker
);
1108 while(IEnumMoniker_Next(ppEnumMoniker
, 1, &IMon
, &nb
) == S_OK
)
1110 IPropertyBag
* pPropBagCat
= NULL
;
1117 V_VT(&var
) = VT_BSTR
;
1119 hrSub
= IMoniker_BindToStorage(IMon
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBagCat
);
1121 if (SUCCEEDED(hrSub
))
1122 hrSub
= IPropertyBag_Read(pPropBagCat
, wszClsidName
, &var
, NULL
);
1124 if (SUCCEEDED(hrSub
))
1125 hrSub
= CLSIDFromString(V_UNION(&var
, bstrVal
), &clsid
);
1127 if (SUCCEEDED(hrSub
))
1128 hrSub
= IPropertyBag_Read(pPropBagCat
, wszFriendlyName
, &var
, NULL
);
1130 if (SUCCEEDED(hrSub
))
1132 len
= (strlenW((WCHAR
*)&V_UNION(&var
, bstrVal
))+1) * sizeof(WCHAR
);
1133 if (!(regfilters
[idx
].Name
= CoTaskMemAlloc(len
*2)))
1137 if (SUCCEEDED(hrSub
))
1139 memcpy(regfilters
[idx
].Name
, &V_UNION(&var
, bstrVal
), len
);
1140 regfilters
[idx
].Clsid
= clsid
;
1145 IPropertyBag_Release(pPropBagCat
);
1146 IMoniker_Release(IMon
);
1149 /* In case of release all resources */
1152 for (idx
= 0; idx
< nb_mon
; idx
++)
1153 CoTaskMemFree(regfilters
[idx
].Name
);
1154 CoTaskMemFree(regfilters
);
1155 IEnumMoniker_Release(ppEnumMoniker
);
1159 hr
= IEnumRegFiltersImpl_Construct(regfilters
, nb_mon
, ppEnum
);
1160 CoTaskMemFree(regfilters
);
1161 IEnumMoniker_Release(ppEnumMoniker
);
1167 static HRESULT WINAPI
FilterMapper_RegisterFilter(IFilterMapper
* iface
, CLSID clsid
, LPCWSTR szName
, DWORD dwMerit
)
1170 LPWSTR wszClsid
= NULL
;
1172 WCHAR wszKeyName
[strlenW(wszFilterSlash
) + (CHARS_IN_GUID
-1) + 1];
1174 TRACE("(%p)->(%s, %s, %lx)\n", iface
, debugstr_guid(&clsid
), debugstr_w(szName
), dwMerit
);
1176 hr
= StringFromCLSID(&clsid
, &wszClsid
);
1180 strcpyW(wszKeyName
, wszFilterSlash
);
1181 strcatW(wszKeyName
, wszClsid
);
1183 hr
= HRESULT_FROM_WIN32(RegCreateKeyExW(HKEY_CLASSES_ROOT
, wszKeyName
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hKey
, NULL
));
1188 hr
= HRESULT_FROM_WIN32(RegSetValueExW(hKey
, NULL
, 0, REG_SZ
, (LPBYTE
)szName
, strlenW(szName
) + 1));
1194 strcpyW(wszKeyName
, wszClsidSlash
);
1195 strcatW(wszKeyName
, wszClsid
);
1197 hr
= HRESULT_FROM_WIN32(RegCreateKeyExW(HKEY_CLASSES_ROOT
, wszKeyName
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hKey
, NULL
));
1202 hr
= HRESULT_FROM_WIN32(RegSetValueExW(hKey
, wszMeritName
, 0, REG_DWORD
, (LPBYTE
)&dwMerit
, sizeof(dwMerit
)));
1209 static HRESULT WINAPI
FilterMapper_RegisterFilterInstance(IFilterMapper
* iface
, CLSID clsid
, LPCWSTR szName
, CLSID
*MRId
)
1211 TRACE("(%p)->(%s, %s, %p)\n", iface
, debugstr_guid(&clsid
), debugstr_w(szName
), MRId
);
1213 /* Not implemented in Windows (tested on Win2k) */
1218 static HRESULT WINAPI
FilterMapper_RegisterPin(
1219 IFilterMapper
* iface
,
1226 CLSID ConnectsToFilter
,
1227 LPCWSTR ConnectsToPin
)
1230 LPWSTR wszClsid
= NULL
;
1232 HKEY hPinsKey
= NULL
;
1233 WCHAR
* wszPinsKeyName
;
1234 WCHAR wszKeyName
[strlenW(wszClsidSlash
) + (CHARS_IN_GUID
-1) + 1];
1236 TRACE("(%p)->(%s, %s, %d, %d, %d, %d, %s, %s)\n", iface
, debugstr_guid(&Filter
), debugstr_w(szName
), bRendered
,
1237 bOutput
, bZero
, bMany
, debugstr_guid(&ConnectsToFilter
), debugstr_w(ConnectsToPin
));
1239 hr
= StringFromCLSID(&Filter
, &wszClsid
);
1243 strcpyW(wszKeyName
, wszClsidSlash
);
1244 strcatW(wszKeyName
, wszClsid
);
1246 hr
= HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszKeyName
, 0, KEY_WRITE
, &hKey
));
1251 wszPinsKeyName
= CoTaskMemAlloc((strlenW(wszPins
) + 1 + strlenW(szName
) + 1) * 2);
1252 if (!wszPinsKeyName
)
1258 strcpyW(wszPinsKeyName
, wszPins
);
1259 strcatW(wszPinsKeyName
, wszSlash
);
1260 strcatW(wszPinsKeyName
, szName
);
1262 hr
= HRESULT_FROM_WIN32(RegCreateKeyExW(hKey
, wszPinsKeyName
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hPinsKey
, NULL
));
1263 CoTaskMemFree(wszPinsKeyName
);
1268 hr
= HRESULT_FROM_WIN32(RegSetValueExW(hPinsKey
, wszAllowedMany
, 0, REG_DWORD
, (LPBYTE
)&bMany
, sizeof(bMany
)));
1273 hr
= HRESULT_FROM_WIN32(RegSetValueExW(hPinsKey
, wszAllowedZero
, 0, REG_DWORD
, (LPBYTE
)&bZero
, sizeof(bZero
)));
1278 hr
= HRESULT_FROM_WIN32(RegSetValueExW(hPinsKey
, wszDirection
, 0, REG_DWORD
, (LPBYTE
)&bOutput
, sizeof(bOutput
)));
1283 hr
= HRESULT_FROM_WIN32(RegSetValueExW(hPinsKey
, wszIsRendered
, 0, REG_DWORD
, (LPBYTE
)&bRendered
, sizeof(bRendered
)));
1288 hr
= HRESULT_FROM_WIN32(RegCreateKeyExW(hPinsKey
, wszTypes
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, NULL
, NULL
));
1292 CoTaskMemFree(wszClsid
);
1296 CloseHandle(hPinsKey
);
1302 static HRESULT WINAPI
FilterMapper_RegisterPinType(
1303 IFilterMapper
* iface
,
1310 LPWSTR wszClsid
= NULL
;
1311 LPWSTR wszClsidMajorType
= NULL
;
1312 LPWSTR wszClsidSubType
= NULL
;
1314 WCHAR
* wszTypesKey
;
1315 WCHAR wszKeyName
[strlenW(wszClsidSlash
) + (CHARS_IN_GUID
-1) + 1];
1317 TRACE("(%p)->(%s, %s, %s, %s)\n", iface
, debugstr_guid(&clsFilter
), debugstr_w(szName
),
1318 debugstr_guid(&clsMajorType
), debugstr_guid(&clsSubType
));
1320 hr
= StringFromCLSID(&clsFilter
, &wszClsid
);
1324 hr
= StringFromCLSID(&clsMajorType
, &wszClsidMajorType
);
1329 hr
= StringFromCLSID(&clsSubType
, &wszClsidSubType
);
1334 wszTypesKey
= CoTaskMemAlloc((strlenW(wszClsidSlash
) + strlenW(wszClsid
) + strlenW(wszPins
) +
1335 strlenW(szName
) + strlenW(wszTypes
) + 3 + 1) * 2);
1342 strcpyW(wszTypesKey
, wszClsidSlash
);
1343 strcatW(wszTypesKey
, wszClsid
);
1344 strcatW(wszTypesKey
, wszSlash
);
1345 strcatW(wszTypesKey
, wszPins
);
1346 strcatW(wszTypesKey
, wszSlash
);
1347 strcatW(wszTypesKey
, szName
);
1348 strcatW(wszTypesKey
, wszSlash
);
1349 strcatW(wszTypesKey
, wszTypes
);
1351 hr
= HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszTypesKey
, 0, KEY_WRITE
, &hKey
));
1352 CoTaskMemFree(wszTypesKey
);
1357 strcpyW(wszKeyName
, wszClsidMajorType
);
1358 strcatW(wszKeyName
, wszSlash
);
1359 strcatW(wszKeyName
, wszClsidSubType
);
1361 hr
= HRESULT_FROM_WIN32(RegCreateKeyExW(hKey
, wszKeyName
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, NULL
, NULL
));
1366 CoTaskMemFree(wszClsid
);
1367 if (wszClsidMajorType
)
1368 CoTaskMemFree(wszClsidMajorType
);
1369 if (wszClsidSubType
)
1370 CoTaskMemFree(wszClsidSubType
);
1375 static HRESULT WINAPI
FilterMapper_UnregisterFilter(IFilterMapper
* iface
, CLSID Filter
)
1378 LPWSTR wszClsid
= NULL
;
1380 WCHAR wszKeyName
[strlenW(wszClsidSlash
) + (CHARS_IN_GUID
-1) + 1];
1382 TRACE("(%p)->(%s)\n", iface
, debugstr_guid(&Filter
));
1384 hr
= StringFromCLSID(&Filter
, &wszClsid
);
1388 hr
= HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszFilter
, 0, KEY_WRITE
, &hKey
));
1393 hr
= HRESULT_FROM_WIN32(RegDeleteKeyW(hKey
, wszClsid
));
1399 strcpyW(wszKeyName
, wszClsidSlash
);
1400 strcatW(wszKeyName
, wszClsid
);
1402 hr
= HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszKeyName
, 0, KEY_WRITE
, &hKey
));
1407 hr
= HRESULT_FROM_WIN32(RegDeleteKeyW(hKey
, wszMeritName
));
1412 CoTaskMemFree(wszClsid
);
1417 static HRESULT WINAPI
FilterMapper_UnregisterFilterInstance(IFilterMapper
* iface
, CLSID MRId
)
1419 TRACE("(%p)->(%s)\n", iface
, debugstr_guid(&MRId
));
1421 /* Not implemented in Windows (tested on Win2k) */
1426 static HRESULT WINAPI
FilterMapper_UnregisterPin(IFilterMapper
* iface
, CLSID Filter
, LPCWSTR Name
)
1429 LPWSTR wszClsid
= NULL
;
1431 WCHAR
* wszPinNameKey
;
1432 WCHAR wszKeyName
[strlenW(wszClsidSlash
) + (CHARS_IN_GUID
-1) + 1];
1434 TRACE("(%p)->(%s, %s)\n", iface
, debugstr_guid(&Filter
), debugstr_w(Name
));
1437 return E_INVALIDARG
;
1439 hr
= StringFromCLSID(&Filter
, &wszClsid
);
1443 strcpyW(wszKeyName
, wszClsidSlash
);
1444 strcatW(wszKeyName
, wszClsid
);
1446 hr
= HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszKeyName
, 0, KEY_WRITE
, &hKey
));
1451 wszPinNameKey
= CoTaskMemAlloc((strlenW(wszPins
) + 1 + strlenW(Name
) + 1) * 2);
1458 strcpyW(wszPinNameKey
, wszPins
);
1459 strcatW(wszPinNameKey
, wszSlash
);
1460 strcatW(wszPinNameKey
, Name
);
1462 hr
= HRESULT_FROM_WIN32(RegDeleteKeyW(hKey
, wszPinNameKey
));
1463 CoTaskMemFree(wszPinNameKey
);
1467 CoTaskMemFree(wszClsid
);
1474 static ICOM_VTABLE(IFilterMapper
) fmvtbl
=
1476 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1478 FilterMapper_QueryInterface
,
1479 FilterMapper_AddRef
,
1480 FilterMapper_Release
,
1482 FilterMapper_RegisterFilter
,
1483 FilterMapper_RegisterFilterInstance
,
1484 FilterMapper_RegisterPin
,
1485 FilterMapper_RegisterPinType
,
1486 FilterMapper_UnregisterFilter
,
1487 FilterMapper_UnregisterFilterInstance
,
1488 FilterMapper_UnregisterPin
,
1489 FilterMapper_EnumMatchingFilters