2 * IFilterMapper & IFilterMapper3 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "quartz_private.h"
37 #include "wine/fil_data.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
43 struct enum_reg_filters
45 IEnumRegFilters IEnumRegFilters_iface
;
48 unsigned int index
, count
;
52 static struct enum_reg_filters
*impl_from_IEnumRegFilters(IEnumRegFilters
*iface
)
54 return CONTAINING_RECORD(iface
, struct enum_reg_filters
, IEnumRegFilters_iface
);
57 static HRESULT WINAPI
enum_reg_filters_QueryInterface(IEnumRegFilters
*iface
, REFIID iid
, void **out
)
59 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
61 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumRegFilters
))
63 IEnumRegFilters_AddRef(iface
);
68 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
73 static ULONG WINAPI
enum_reg_filters_AddRef(IEnumRegFilters
*iface
)
75 struct enum_reg_filters
*enumerator
= impl_from_IEnumRegFilters(iface
);
76 ULONG refcount
= InterlockedIncrement(&enumerator
->refcount
);
77 TRACE("%p increasing refcount to %lu.\n", enumerator
, refcount
);
81 static ULONG WINAPI
enum_reg_filters_Release(IEnumRegFilters
*iface
)
83 struct enum_reg_filters
*enumerator
= impl_from_IEnumRegFilters(iface
);
84 ULONG refcount
= InterlockedDecrement(&enumerator
->refcount
);
87 TRACE("%p decreasing refcount to %lu.\n", enumerator
, refcount
);
90 for (i
= 0; i
< enumerator
->count
; ++i
)
91 free(enumerator
->filters
[i
].Name
);
92 free(enumerator
->filters
);
98 static HRESULT WINAPI
enum_reg_filters_Next(IEnumRegFilters
*iface
, ULONG count
,
99 REGFILTER
**filters
, ULONG
*ret_count
)
101 struct enum_reg_filters
*enumerator
= impl_from_IEnumRegFilters(iface
);
104 TRACE("iface %p, count %lu, filters %p, ret_count %p.\n", iface
, count
, filters
, ret_count
);
106 for (i
= 0; i
< count
&& enumerator
->index
+ i
< enumerator
->count
; ++i
)
108 REGFILTER
*filter
= &enumerator
->filters
[enumerator
->index
+ i
];
110 if (!(filters
[i
] = CoTaskMemAlloc(sizeof(REGFILTER
) + (wcslen(filter
->Name
) + 1) * sizeof(WCHAR
))))
113 CoTaskMemFree(filters
[i
]);
114 memset(filters
, 0, count
* sizeof(*filters
));
116 return E_OUTOFMEMORY
;
119 filters
[i
]->Clsid
= filter
->Clsid
;
120 filters
[i
]->Name
= (WCHAR
*)(filters
[i
] + 1);
121 wcscpy(filters
[i
]->Name
, filter
->Name
);
124 enumerator
->index
+= i
;
127 return i
? S_OK
: S_FALSE
;
130 static HRESULT WINAPI
enum_reg_filters_Skip(IEnumRegFilters
*iface
, ULONG count
)
132 TRACE("iface %p, count %lu, unimplemented.\n", iface
, count
);
136 static HRESULT WINAPI
enum_reg_filters_Reset(IEnumRegFilters
*iface
)
138 struct enum_reg_filters
*enumerator
= impl_from_IEnumRegFilters(iface
);
140 TRACE("iface %p.\n", iface
);
142 enumerator
->index
= 0;
146 static HRESULT WINAPI
enum_reg_filters_Clone(IEnumRegFilters
*iface
, IEnumRegFilters
**out
)
148 TRACE("iface %p, out %p, unimplemented.\n", iface
, out
);
152 static const IEnumRegFiltersVtbl enum_reg_filters_vtbl
=
154 enum_reg_filters_QueryInterface
,
155 enum_reg_filters_AddRef
,
156 enum_reg_filters_Release
,
157 enum_reg_filters_Next
,
158 enum_reg_filters_Skip
,
159 enum_reg_filters_Reset
,
160 enum_reg_filters_Clone
,
163 static HRESULT
enum_reg_filters_create(REGFILTER
*filters
, unsigned int count
, IEnumRegFilters
**out
)
165 struct enum_reg_filters
*object
;
170 if (!(object
= calloc(1, sizeof(*object
))))
171 return E_OUTOFMEMORY
;
173 if (!(object
->filters
= malloc(count
* sizeof(*object
->filters
))))
176 return E_OUTOFMEMORY
;
179 for (i
= 0; i
< count
; ++i
)
181 object
->filters
[i
].Clsid
= filters
[i
].Clsid
;
182 if (!(object
->filters
[i
].Name
= wcsdup(filters
[i
].Name
)))
185 free(object
->filters
[i
].Name
);
186 free(object
->filters
);
188 return E_OUTOFMEMORY
;
192 object
->IEnumRegFilters_iface
.lpVtbl
= &enum_reg_filters_vtbl
;
193 object
->refcount
= 1;
194 object
->count
= count
;
196 TRACE("Created enumerator %p.\n", object
);
197 *out
= &object
->IEnumRegFilters_iface
;
203 IEnumMoniker IEnumMoniker_iface
;
206 unsigned int index
, count
;
210 static struct enum_moniker
*impl_from_IEnumMoniker(IEnumMoniker
*iface
)
212 return CONTAINING_RECORD(iface
, struct enum_moniker
, IEnumMoniker_iface
);
215 static HRESULT WINAPI
enum_moniker_QueryInterface(IEnumMoniker
*iface
, REFIID iid
, void **out
)
217 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
219 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumMoniker
))
221 IEnumMoniker_AddRef(iface
);
226 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
228 return E_NOINTERFACE
;
231 static ULONG WINAPI
enum_moniker_AddRef(IEnumMoniker
*iface
)
233 struct enum_moniker
*enumerator
= impl_from_IEnumMoniker(iface
);
234 ULONG refcount
= InterlockedIncrement(&enumerator
->refcount
);
235 TRACE("%p increasing refcount to %lu.\n", enumerator
, refcount
);
239 static ULONG WINAPI
enum_moniker_Release(IEnumMoniker
*iface
)
241 struct enum_moniker
*enumerator
= impl_from_IEnumMoniker(iface
);
242 ULONG refcount
= InterlockedDecrement(&enumerator
->refcount
);
245 TRACE("%p decreasing refcount to %lu.\n", enumerator
, refcount
);
248 for (i
= 0; i
< enumerator
->count
; ++i
)
249 IMoniker_Release(enumerator
->filters
[i
]);
250 free(enumerator
->filters
);
256 static HRESULT WINAPI
enum_moniker_Next(IEnumMoniker
*iface
, ULONG count
,
257 IMoniker
**filters
, ULONG
*ret_count
)
259 struct enum_moniker
*enumerator
= impl_from_IEnumMoniker(iface
);
262 TRACE("iface %p, count %lu, filters %p, ret_count %p.\n", iface
, count
, filters
, ret_count
);
264 for (i
= 0; i
< count
&& enumerator
->index
+ i
< enumerator
->count
; ++i
)
265 IMoniker_AddRef(filters
[i
] = enumerator
->filters
[enumerator
->index
+ i
]);
267 enumerator
->index
+= i
;
270 return i
? S_OK
: S_FALSE
;
273 static HRESULT WINAPI
enum_moniker_Skip(IEnumMoniker
*iface
, ULONG count
)
275 struct enum_moniker
*enumerator
= impl_from_IEnumMoniker(iface
);
277 TRACE("iface %p, count %lu.\n", iface
, count
);
279 enumerator
->index
+= count
;
283 static HRESULT WINAPI
enum_moniker_Reset(IEnumMoniker
*iface
)
285 struct enum_moniker
*enumerator
= impl_from_IEnumMoniker(iface
);
287 TRACE("iface %p.\n", iface
);
289 enumerator
->index
= 0;
293 static HRESULT WINAPI
enum_moniker_Clone(IEnumMoniker
*iface
, IEnumMoniker
**out
)
295 TRACE("iface %p, out %p, unimplemented.\n", iface
, out
);
299 static const IEnumMonikerVtbl enum_moniker_vtbl
=
301 enum_moniker_QueryInterface
,
303 enum_moniker_Release
,
310 static HRESULT
enum_moniker_create(IMoniker
**filters
, unsigned int count
, IEnumMoniker
**out
)
312 struct enum_moniker
*object
;
316 if (!(object
= calloc(1, sizeof(*object
))))
317 return E_OUTOFMEMORY
;
319 if (!(object
->filters
= malloc(count
* sizeof(*object
->filters
))))
322 return E_OUTOFMEMORY
;
324 memcpy(object
->filters
, filters
, count
* sizeof(*filters
));
326 object
->IEnumMoniker_iface
.lpVtbl
= &enum_moniker_vtbl
;
327 object
->refcount
= 1;
328 object
->count
= count
;
330 TRACE("Created enumerator %p.\n", object
);
331 *out
= &object
->IEnumMoniker_iface
;
335 typedef struct FilterMapper3Impl
337 IUnknown IUnknown_inner
;
338 IFilterMapper3 IFilterMapper3_iface
;
339 IFilterMapper IFilterMapper_iface
;
340 IAMFilterData IAMFilterData_iface
;
345 static inline FilterMapper3Impl
*impl_from_IFilterMapper3( IFilterMapper3
*iface
)
347 return CONTAINING_RECORD(iface
, FilterMapper3Impl
, IFilterMapper3_iface
);
350 static inline FilterMapper3Impl
*impl_from_IFilterMapper( IFilterMapper
*iface
)
352 return CONTAINING_RECORD(iface
, FilterMapper3Impl
, IFilterMapper_iface
);
355 static inline FilterMapper3Impl
*impl_from_IAMFilterData( IAMFilterData
*iface
)
357 return CONTAINING_RECORD(iface
, FilterMapper3Impl
, IAMFilterData_iface
);
360 static inline FilterMapper3Impl
*impl_from_IUnknown( IUnknown
*iface
)
362 return CONTAINING_RECORD(iface
, FilterMapper3Impl
, IUnknown_inner
);
365 /* registry format for REGFILTER2 */
376 BYTE signature
[4]; /* e.g. "0pi3" */
381 DWORD bCategory
; /* is there a category clsid? */
382 /* optional: dwOffsetCategoryClsid */
387 BYTE signature
[4]; /* e.g. "0ty3" */
402 int capacity
; /* in bytes */
403 int current
; /* pointer to next free byte */
406 /* returns the position it was added at */
407 static int add_data(struct Vector
*v
, const void *pData
, int size
)
409 int index
= v
->current
;
410 if (v
->current
+ size
> v
->capacity
)
412 int new_capacity
= (v
->capacity
+ size
) * 2;
413 BYTE
*new_data
= CoTaskMemRealloc(v
->pData
, new_capacity
);
414 if (!new_data
) return -1;
415 v
->capacity
= new_capacity
;
418 memcpy(v
->pData
+ v
->current
, pData
, size
);
423 static int find_data(const struct Vector
*v
, const void *pData
, int size
)
426 for (index
= 0; index
+ size
<= v
->current
; index
++)
427 if (!memcmp(v
->pData
+ index
, pData
, size
))
433 static void delete_vector(struct Vector
* v
)
435 CoTaskMemFree(v
->pData
);
440 /*** IUnknown (inner) methods ***/
442 static HRESULT WINAPI
Inner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
444 FilterMapper3Impl
*This
= impl_from_IUnknown(iface
);
446 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
449 if (IsEqualIID(riid
, &IID_IUnknown
))
450 *ppv
= &This
->IUnknown_inner
;
451 else if (IsEqualIID(riid
, &IID_IFilterMapper2
) || IsEqualIID(riid
, &IID_IFilterMapper3
))
452 *ppv
= &This
->IFilterMapper3_iface
;
453 else if (IsEqualIID(riid
, &IID_IFilterMapper
))
454 *ppv
= &This
->IFilterMapper_iface
;
455 else if (IsEqualIID(riid
, &IID_IAMFilterData
))
456 *ppv
= &This
->IAMFilterData_iface
;
460 IUnknown_AddRef((IUnknown
*)*ppv
);
464 FIXME("No interface for %s\n", debugstr_guid(riid
));
465 return E_NOINTERFACE
;
468 static ULONG WINAPI
Inner_AddRef(IUnknown
*iface
)
470 FilterMapper3Impl
*mapper
= impl_from_IUnknown(iface
);
471 ULONG refcount
= InterlockedIncrement(&mapper
->ref
);
473 TRACE("%p increasing refcount to %lu.\n", mapper
, refcount
);
478 static ULONG WINAPI
Inner_Release(IUnknown
*iface
)
480 FilterMapper3Impl
*mapper
= impl_from_IUnknown(iface
);
481 ULONG refcount
= InterlockedDecrement(&mapper
->ref
);
483 TRACE("%p decreasing refcount to %lu.\n", mapper
, refcount
);
487 CoTaskMemFree(mapper
);
493 static const IUnknownVtbl IInner_VTable
=
495 Inner_QueryInterface
,
500 static HRESULT WINAPI
FilterMapper3_QueryInterface(IFilterMapper3
* iface
, REFIID riid
, LPVOID
*ppv
)
502 FilterMapper3Impl
*This
= impl_from_IFilterMapper3(iface
);
504 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
507 static ULONG WINAPI
FilterMapper3_AddRef(IFilterMapper3
* iface
)
509 FilterMapper3Impl
*This
= impl_from_IFilterMapper3(iface
);
511 return IUnknown_AddRef(This
->outer_unk
);
514 static ULONG WINAPI
FilterMapper3_Release(IFilterMapper3
* iface
)
516 FilterMapper3Impl
*This
= impl_from_IFilterMapper3(iface
);
518 return IUnknown_Release(This
->outer_unk
);
521 /*** IFilterMapper3 methods ***/
523 static HRESULT WINAPI
FilterMapper3_CreateCategory(IFilterMapper3
*iface
,
524 REFCLSID category
, DWORD merit
, const WCHAR
*description
)
526 WCHAR guidstr
[39], keypath
[93];
530 TRACE("iface %p, category %s, merit %#lx, description %s.\n", iface
,
531 debugstr_guid(category
), merit
, debugstr_w(description
));
533 StringFromGUID2(category
, guidstr
, ARRAY_SIZE(guidstr
));
534 wcscpy(keypath
, L
"CLSID\\{da4e3da0-d07d-11d0-bd50-00a0c911ce86}\\Instance\\");
535 wcscat(keypath
, guidstr
);
537 if ((ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
)))
538 return HRESULT_FROM_WIN32(ret
);
540 if ((ret
= RegSetValueExW(key
, L
"FriendlyName", 0, REG_SZ
,
541 (const BYTE
*)description
, (wcslen(description
) + 1) * sizeof(WCHAR
))))
544 return HRESULT_FROM_WIN32(ret
);
547 if ((ret
= RegSetValueExW(key
, L
"CLSID", 0, REG_SZ
, (const BYTE
*)guidstr
, sizeof(guidstr
))))
550 return HRESULT_FROM_WIN32(ret
);
553 if ((ret
= RegSetValueExW(key
, L
"Merit", 0, REG_DWORD
, (const BYTE
*)&merit
, sizeof(DWORD
))))
556 return HRESULT_FROM_WIN32(ret
);
563 static HRESULT WINAPI
FilterMapper3_UnregisterFilter(IFilterMapper3
*iface
,
564 const CLSID
*category
, const WCHAR
*instance
, REFCLSID clsid
)
568 TRACE("iface %p, category %s, instance %s, clsid %s.\n",
569 iface
, debugstr_guid(category
), debugstr_w(instance
), debugstr_guid(clsid
));
572 category
= &CLSID_LegacyAmFilterCategory
;
574 wcscpy(keypath
, L
"CLSID\\");
575 StringFromGUID2(category
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
576 wcscat(keypath
, L
"\\Instance\\");
578 wcscat(keypath
, instance
);
580 StringFromGUID2(clsid
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
582 return HRESULT_FROM_WIN32(RegDeleteKeyW(HKEY_CLASSES_ROOT
, keypath
));
585 static HRESULT
FM2_WriteFilterData(const REGFILTER2
* prf2
, BYTE
**ppData
, ULONG
*pcbData
)
587 int size
= sizeof(struct REG_RF
);
589 struct Vector mainStore
= {NULL
, 0, 0};
590 struct Vector clsidStore
= {NULL
, 0, 0};
594 rrf
.dwVersion
= prf2
->dwVersion
;
595 rrf
.dwMerit
= prf2
->dwMerit
;
596 rrf
.dwPins
= prf2
->cPins2
;
599 add_data(&mainStore
, &rrf
, sizeof(rrf
));
601 for (i
= 0; i
< prf2
->cPins2
; i
++)
603 size
+= sizeof(struct REG_RFP
);
604 if (prf2
->rgPins2
[i
].clsPinCategory
)
605 size
+= sizeof(DWORD
);
606 size
+= prf2
->rgPins2
[i
].nMediaTypes
* sizeof(struct REG_TYPE
);
607 size
+= prf2
->rgPins2
[i
].nMediums
* sizeof(DWORD
);
610 for (i
= 0; i
< prf2
->cPins2
; i
++)
613 REGFILTERPINS2 rgPin2
= prf2
->rgPins2
[i
];
616 rrfp
.signature
[0] = '0';
617 rrfp
.signature
[1] = 'p';
618 rrfp
.signature
[2] = 'i';
619 rrfp
.signature
[3] = '3';
620 rrfp
.signature
[0] += i
;
621 rrfp
.dwFlags
= rgPin2
.dwFlags
;
622 rrfp
.dwInstances
= rgPin2
.cInstances
;
623 rrfp
.dwMediaTypes
= rgPin2
.nMediaTypes
;
624 rrfp
.dwMediums
= rgPin2
.nMediums
;
625 rrfp
.bCategory
= rgPin2
.clsPinCategory
? 1 : 0;
627 add_data(&mainStore
, &rrfp
, sizeof(rrfp
));
630 DWORD index
= find_data(&clsidStore
, rgPin2
.clsPinCategory
, sizeof(CLSID
));
632 index
= add_data(&clsidStore
, rgPin2
.clsPinCategory
, sizeof(CLSID
));
635 add_data(&mainStore
, &index
, sizeof(index
));
638 for (j
= 0; j
< rgPin2
.nMediaTypes
; j
++)
641 const CLSID
* clsMinorType
= rgPin2
.lpMediaType
[j
].clsMinorType
? rgPin2
.lpMediaType
[j
].clsMinorType
: &MEDIASUBTYPE_NULL
;
642 rt
.signature
[0] = '0';
643 rt
.signature
[1] = 't';
644 rt
.signature
[2] = 'y';
645 rt
.signature
[3] = '3';
646 rt
.signature
[0] += j
;
648 rt
.dwOffsetMajor
= find_data(&clsidStore
, rgPin2
.lpMediaType
[j
].clsMajorType
, sizeof(CLSID
));
649 if (rt
.dwOffsetMajor
== -1)
650 rt
.dwOffsetMajor
= add_data(&clsidStore
, rgPin2
.lpMediaType
[j
].clsMajorType
, sizeof(CLSID
));
651 rt
.dwOffsetMajor
+= size
;
652 rt
.dwOffsetMinor
= find_data(&clsidStore
, clsMinorType
, sizeof(CLSID
));
653 if (rt
.dwOffsetMinor
== -1)
654 rt
.dwOffsetMinor
= add_data(&clsidStore
, clsMinorType
, sizeof(CLSID
));
655 rt
.dwOffsetMinor
+= size
;
657 add_data(&mainStore
, &rt
, sizeof(rt
));
660 for (j
= 0; j
< rgPin2
.nMediums
; j
++)
662 DWORD index
= find_data(&clsidStore
, rgPin2
.lpMedium
+ j
, sizeof(REGPINMEDIUM
));
664 index
= add_data(&clsidStore
, rgPin2
.lpMedium
+ j
, sizeof(REGPINMEDIUM
));
667 add_data(&mainStore
, &index
, sizeof(index
));
673 *pcbData
= mainStore
.current
+ clsidStore
.current
;
674 *ppData
= CoTaskMemAlloc(*pcbData
);
681 memcpy(*ppData
, mainStore
.pData
, mainStore
.current
);
682 memcpy((*ppData
) + mainStore
.current
, clsidStore
.pData
, clsidStore
.current
);
685 delete_vector(&mainStore
);
686 delete_vector(&clsidStore
);
690 static HRESULT
FM2_ReadFilterData(BYTE
*pData
, REGFILTER2
* prf2
)
693 struct REG_RF
* prrf
;
696 REGFILTERPINS2
* rgPins2
;
698 prrf
= (struct REG_RF
*)pData
;
701 if (prrf
->dwVersion
!= 2)
703 FIXME("Filter registry version %lu is not supported.\n", prrf
->dwVersion
);
704 ZeroMemory(prf2
, sizeof(*prf2
));
710 TRACE("dwVersion %lu, dwMerit %#lx, dwPins %lu, dwUnused %#lx.\n",
711 prrf
->dwVersion
, prrf
->dwMerit
, prrf
->dwPins
, prrf
->dwUnused
);
713 prf2
->dwVersion
= prrf
->dwVersion
;
714 prf2
->dwMerit
= prrf
->dwMerit
;
715 prf2
->cPins2
= prrf
->dwPins
;
716 rgPins2
= CoTaskMemAlloc(prrf
->dwPins
* sizeof(*rgPins2
));
717 prf2
->rgPins2
= rgPins2
;
718 pCurrent
+= sizeof(struct REG_RF
);
720 for (i
= 0; i
< prrf
->dwPins
; i
++)
722 struct REG_RFP
* prrfp
= (struct REG_RFP
*)pCurrent
;
723 REGPINTYPES
* lpMediaType
;
724 REGPINMEDIUM
* lpMedium
;
727 /* FIXME: check signature */
729 TRACE("\tsignature = %s\n", debugstr_an((const char*)prrfp
->signature
, 4));
731 TRACE("\tPin %lu: dwFlags %#lx, dwInstances %lu, dwMediaTypes %lu, dwMediums %lu.\n",
732 i
, prrfp
->dwFlags
, prrfp
->dwInstances
, prrfp
->dwMediaTypes
, prrfp
->dwMediums
);
734 rgPins2
[i
].dwFlags
= prrfp
->dwFlags
;
735 rgPins2
[i
].cInstances
= prrfp
->dwInstances
;
736 rgPins2
[i
].nMediaTypes
= prrfp
->dwMediaTypes
;
737 rgPins2
[i
].nMediums
= prrfp
->dwMediums
;
738 pCurrent
+= sizeof(struct REG_RFP
);
739 if (prrfp
->bCategory
)
741 CLSID
* clsCat
= CoTaskMemAlloc(sizeof(CLSID
));
742 memcpy(clsCat
, pData
+ *(DWORD
*)(pCurrent
), sizeof(CLSID
));
743 pCurrent
+= sizeof(DWORD
);
744 rgPins2
[i
].clsPinCategory
= clsCat
;
747 rgPins2
[i
].clsPinCategory
= NULL
;
749 if (rgPins2
[i
].nMediaTypes
> 0)
750 lpMediaType
= CoTaskMemAlloc(rgPins2
[i
].nMediaTypes
* sizeof(*lpMediaType
));
754 rgPins2
[i
].lpMediaType
= lpMediaType
;
756 for (j
= 0; j
< rgPins2
[i
].nMediaTypes
; j
++)
758 struct REG_TYPE
* prt
= (struct REG_TYPE
*)pCurrent
;
759 CLSID
* clsMajor
= CoTaskMemAlloc(sizeof(CLSID
));
760 CLSID
* clsMinor
= CoTaskMemAlloc(sizeof(CLSID
));
762 /* FIXME: check signature */
763 TRACE("\t\tsignature = %s\n", debugstr_an((const char*)prt
->signature
, 4));
765 memcpy(clsMajor
, pData
+ prt
->dwOffsetMajor
, sizeof(CLSID
));
766 memcpy(clsMinor
, pData
+ prt
->dwOffsetMinor
, sizeof(CLSID
));
768 lpMediaType
[j
].clsMajorType
= clsMajor
;
769 lpMediaType
[j
].clsMinorType
= clsMinor
;
771 pCurrent
+= sizeof(*prt
);
774 if (rgPins2
[i
].nMediums
> 0)
775 lpMedium
= CoTaskMemAlloc(rgPins2
[i
].nMediums
* sizeof(*lpMedium
));
779 rgPins2
[i
].lpMedium
= lpMedium
;
781 for (j
= 0; j
< rgPins2
[i
].nMediums
; j
++)
783 DWORD dwOffset
= *(DWORD
*)pCurrent
;
785 memcpy(lpMedium
+ j
, pData
+ dwOffset
, sizeof(REGPINMEDIUM
));
787 pCurrent
+= sizeof(dwOffset
);
796 static void FM2_DeleteRegFilter(REGFILTER2
* prf2
)
799 for (i
= 0; i
< prf2
->cPins2
; i
++)
802 CoTaskMemFree((void*)prf2
->rgPins2
[i
].clsPinCategory
);
804 for (j
= 0; j
< prf2
->rgPins2
[i
].nMediaTypes
; j
++)
806 CoTaskMemFree((LPVOID
)prf2
->rgPins2
[i
].lpMediaType
[j
].clsMajorType
);
807 CoTaskMemFree((LPVOID
)prf2
->rgPins2
[i
].lpMediaType
[j
].clsMinorType
);
809 CoTaskMemFree((LPVOID
)prf2
->rgPins2
[i
].lpMediaType
);
810 CoTaskMemFree((LPVOID
)prf2
->rgPins2
[i
].lpMedium
);
812 CoTaskMemFree((LPVOID
)prf2
->rgPins2
);
815 static HRESULT WINAPI
FilterMapper3_RegisterFilter(IFilterMapper3
*iface
,
816 REFCLSID clsid
, const WCHAR
*name
, IMoniker
**ret_moniker
,
817 const CLSID
*category
, const WCHAR
*instance
, const REGFILTER2
*prf2
)
819 WCHAR
*display_name
, clsid_string
[39];
820 IParseDisplayName
*parser
;
821 IPropertyBag
*prop_bag
;
822 ULONG filter_data_len
;
829 REGFILTER2 regfilter2
;
830 REGFILTERPINS2
* pregfp2
= NULL
;
832 TRACE("iface %p, clsid %s, name %s, ret_moniker %p, category %s, instance %s, prf2 %p.\n",
833 iface
, debugstr_guid(clsid
), debugstr_w(name
), ret_moniker
,
834 debugstr_guid(category
), debugstr_w(instance
), prf2
);
836 if (prf2
->dwVersion
== 2)
840 else if (prf2
->dwVersion
== 1)
844 /* REGFILTER2 structure is converted from version 1 to 2. Tested on Win2k. */
845 regfilter2
.dwVersion
= 2;
846 regfilter2
.dwMerit
= prf2
->dwMerit
;
847 regfilter2
.cPins2
= prf2
->cPins
;
848 pregfp2
= CoTaskMemAlloc(prf2
->cPins
* sizeof(REGFILTERPINS2
));
849 regfilter2
.rgPins2
= pregfp2
;
850 for (i
= 0; i
< prf2
->cPins
; i
++)
853 if (prf2
->rgPins
[i
].bRendered
)
854 flags
|= REG_PINFLAG_B_RENDERER
;
855 if (prf2
->rgPins
[i
].bOutput
)
856 flags
|= REG_PINFLAG_B_OUTPUT
;
857 if (prf2
->rgPins
[i
].bZero
)
858 flags
|= REG_PINFLAG_B_ZERO
;
859 if (prf2
->rgPins
[i
].bMany
)
860 flags
|= REG_PINFLAG_B_MANY
;
861 pregfp2
[i
].dwFlags
= flags
;
862 pregfp2
[i
].cInstances
= 1;
863 pregfp2
[i
].nMediaTypes
= prf2
->rgPins
[i
].nMediaTypes
;
864 pregfp2
[i
].lpMediaType
= prf2
->rgPins
[i
].lpMediaType
;
865 pregfp2
[i
].nMediums
= 0;
866 pregfp2
[i
].lpMedium
= NULL
;
867 pregfp2
[i
].clsPinCategory
= NULL
;
872 FIXME("dwVersion other that 1 or 2 not supported at the moment\n");
880 category
= &CLSID_LegacyAmFilterCategory
;
882 StringFromGUID2(clsid
, clsid_string
, ARRAY_SIZE(clsid_string
));
884 len
= 50 + (instance
? wcslen(instance
) : 38) + 1;
885 if (!(display_name
= malloc(len
* sizeof(WCHAR
))))
886 return E_OUTOFMEMORY
;
888 wcscpy(display_name
, L
"@device:sw:");
889 StringFromGUID2(category
, display_name
+ wcslen(display_name
), len
- wcslen(display_name
));
890 wcscat(display_name
, L
"\\");
891 wcscat(display_name
, instance
? instance
: clsid_string
);
893 if (FAILED(hr
= CoCreateInstance(&CLSID_CDeviceMoniker
, NULL
, CLSCTX_INPROC
,
894 &IID_IParseDisplayName
, (void **)&parser
)))
900 if (FAILED(hr
= IParseDisplayName_ParseDisplayName(parser
, NULL
, display_name
, &eaten
, &moniker
)))
902 ERR("Failed to parse display name, hr %#lx.\n", hr
);
903 IParseDisplayName_Release(parser
);
908 IParseDisplayName_Release(parser
);
910 if (FAILED(hr
= IMoniker_BindToStorage(moniker
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
)))
912 ERR("Failed to get property bag, hr %#lx.\n", hr
);
913 IMoniker_Release(moniker
);
918 V_VT(&var
) = VT_BSTR
;
919 V_BSTR(&var
) = SysAllocString(name
);
920 if (FAILED(hr
= IPropertyBag_Write(prop_bag
, L
"FriendlyName", &var
)))
921 ERR("Failed to write friendly name, hr %#lx.\n", hr
);
924 V_VT(&var
) = VT_BSTR
;
925 V_BSTR(&var
) = SysAllocString(clsid_string
);
926 if (FAILED(hr
= IPropertyBag_Write(prop_bag
, L
"CLSID", &var
)))
927 ERR("Failed to write class ID, hr %#lx.\n", hr
);
930 if (SUCCEEDED(FM2_WriteFilterData(®filter2
, &filter_data
, &filter_data_len
)))
932 V_VT(&var
) = VT_ARRAY
| VT_UI1
;
933 if ((V_ARRAY(&var
) = SafeArrayCreateVector(VT_UI1
, 0, filter_data_len
)))
935 memcpy(V_ARRAY(&var
)->pvData
, filter_data
, filter_data_len
);
936 if (FAILED(hr
= IPropertyBag_Write(prop_bag
, L
"FilterData", &var
)))
937 ERR("Failed to write filter data, hr %#lx.\n", hr
);
941 CoTaskMemFree(filter_data
);
944 IPropertyBag_Release(prop_bag
);
948 *ret_moniker
= moniker
;
950 IMoniker_Release(moniker
);
952 CoTaskMemFree(pregfp2
);
957 /* internal helper function */
958 static BOOL
MatchTypes(
961 const REGPINTYPES
* pPinTypes
,
963 const GUID
* pMatchTypes
)
968 if ((nMatchTypes
== 0) && (nPinTypes
> 0))
971 for (j
= 0; j
< nPinTypes
; j
++)
974 for (i
= 0; i
< nMatchTypes
*2; i
+=2)
976 if (((!bExactMatch
&& IsEqualGUID(pPinTypes
[j
].clsMajorType
, &GUID_NULL
)) || IsEqualGUID(&pMatchTypes
[i
], &GUID_NULL
) || IsEqualGUID(pPinTypes
[j
].clsMajorType
, &pMatchTypes
[i
])) &&
977 ((!bExactMatch
&& IsEqualGUID(pPinTypes
[j
].clsMinorType
, &GUID_NULL
)) || IsEqualGUID(&pMatchTypes
[i
+1], &GUID_NULL
) || IsEqualGUID(pPinTypes
[j
].clsMinorType
, &pMatchTypes
[i
+1])))
987 /* internal helper function for qsort of MONIKER_MERIT array */
988 static int __cdecl
mm_compare(const void * left
, const void * right
)
990 const struct MONIKER_MERIT
* mmLeft
= left
;
991 const struct MONIKER_MERIT
* mmRight
= right
;
993 if (mmLeft
->dwMerit
== mmRight
->dwMerit
)
995 if (mmLeft
->dwMerit
> mmRight
->dwMerit
)
1001 * Exact match means whether or not to treat GUID_NULL's in filter data as wild cards
1002 * (GUID_NULL's in input to function automatically treated as wild cards)
1003 * Input/Output needed means match only on criteria if TRUE (with zero input types
1004 * meaning match any input/output pin as long as one exists), otherwise match any
1005 * filter that meets the rest of the requirements.
1007 static HRESULT WINAPI
FilterMapper3_EnumMatchingFilters(
1008 IFilterMapper3
* iface
,
1009 IEnumMoniker
**ppEnum
,
1015 const GUID
*pInputTypes
,
1016 const REGPINMEDIUM
*pMedIn
,
1017 const CLSID
*pPinCategoryIn
,
1021 const GUID
*pOutputTypes
,
1022 const REGPINMEDIUM
*pMedOut
,
1023 const CLSID
*pPinCategoryOut
)
1025 ICreateDevEnum
* pCreateDevEnum
;
1026 IMoniker
* pMonikerCat
;
1027 IEnumMoniker
* pEnumCat
;
1029 struct Vector monikers
= {NULL
, 0, 0};
1031 TRACE("(%p, %#lx, %s, %#lx, %s, %lu, %p, %p, %p, %s, %s, %p, %p, %p)\n",
1034 bExactMatch
? "true" : "false",
1036 bInputNeeded
? "true" : "false",
1041 bRender
? "true" : "false",
1042 bOutputNeeded
? "true" : "false",
1048 FIXME("Ignoring flags %#lx.\n", dwFlags
);
1052 hr
= CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC
, &IID_ICreateDevEnum
, (LPVOID
*)&pCreateDevEnum
);
1056 hr
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &CLSID_ActiveMovieCategories
, &pEnumCat
, 0);
1058 ICreateDevEnum_Release(pCreateDevEnum
);
1062 while (IEnumMoniker_Next(pEnumCat
, 1, &pMonikerCat
, NULL
) == S_OK
)
1064 IPropertyBag
* pPropBagCat
= NULL
;
1066 HRESULT hrSub
; /* this is so that one buggy filter
1067 doesn't make the whole lot fail */
1071 hrSub
= IMoniker_BindToStorage(pMonikerCat
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBagCat
);
1073 if (SUCCEEDED(hrSub
))
1074 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"Merit", &var
, NULL
);
1076 if (SUCCEEDED(hrSub
) && (V_UI4(&var
) >= dwMerit
))
1079 IEnumMoniker
* pEnum
;
1080 IMoniker
* pMoniker
;
1084 if (TRACE_ON(quartz
))
1087 V_VT(&temp
) = VT_EMPTY
;
1088 IPropertyBag_Read(pPropBagCat
, L
"FriendlyName", &temp
, NULL
);
1089 TRACE("Considering category %s\n", debugstr_w(V_BSTR(&temp
)));
1090 VariantClear(&temp
);
1093 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"CLSID", &var
, NULL
);
1095 if (SUCCEEDED(hrSub
))
1096 hrSub
= CLSIDFromString(V_BSTR(&var
), &clsidCat
);
1098 if (SUCCEEDED(hrSub
))
1099 hrSub
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &clsidCat
, &pEnum
, 0);
1103 while (IEnumMoniker_Next(pEnum
, 1, &pMoniker
, NULL
) == S_OK
)
1105 IPropertyBag
* pPropBag
= NULL
;
1110 BOOL bInputMatch
= !bInputNeeded
;
1111 BOOL bOutputMatch
= !bOutputNeeded
;
1113 ZeroMemory(&rf2
, sizeof(rf2
));
1116 hrSub
= IMoniker_BindToStorage(pMoniker
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBag
);
1118 if (TRACE_ON(quartz
))
1121 V_VT(&temp
) = VT_EMPTY
;
1122 IPropertyBag_Read(pPropBag
, L
"FriendlyName", &temp
, NULL
);
1123 TRACE("Considering filter %s\n", debugstr_w(V_BSTR(&temp
)));
1124 VariantClear(&temp
);
1127 if (SUCCEEDED(hrSub
))
1129 hrSub
= IPropertyBag_Read(pPropBag
, L
"FilterData", &var
, NULL
);
1132 if (SUCCEEDED(hrSub
))
1133 hrSub
= SafeArrayAccessData(V_ARRAY(&var
), (LPVOID
*)&pData
);
1135 if (SUCCEEDED(hrSub
))
1136 hrSub
= FM2_ReadFilterData(pData
, &rf2
);
1139 SafeArrayUnaccessData(V_ARRAY(&var
));
1143 /* Logic used for bInputMatch expression:
1144 * There exists some pin such that bInputNeeded implies (pin is an input and
1145 * (bRender implies pin has render flag) and major/minor types members of
1147 * bOutputMatch is similar, but without the "bRender implies ..." part
1148 * and substituting variables names containing input for output
1151 /* determine whether filter meets requirements */
1152 if (SUCCEEDED(hrSub
) && (rf2
.dwMerit
>= dwMerit
))
1154 for (i
= 0; (i
< rf2
.cPins2
) && (!bInputMatch
|| !bOutputMatch
); i
++)
1156 const REGFILTERPINS2
* rfp2
= rf2
.rgPins2
+ i
;
1158 bInputMatch
= bInputMatch
|| (!(rfp2
->dwFlags
& REG_PINFLAG_B_OUTPUT
) &&
1159 (!bRender
|| (rfp2
->dwFlags
& REG_PINFLAG_B_RENDERER
)) &&
1160 MatchTypes(bExactMatch
, rfp2
->nMediaTypes
, rfp2
->lpMediaType
, cInputTypes
, pInputTypes
));
1161 bOutputMatch
= bOutputMatch
|| ((rfp2
->dwFlags
& REG_PINFLAG_B_OUTPUT
) &&
1162 MatchTypes(bExactMatch
, rfp2
->nMediaTypes
, rfp2
->lpMediaType
, cOutputTypes
, pOutputTypes
));
1165 if (bInputMatch
&& bOutputMatch
)
1167 struct MONIKER_MERIT mm
= {pMoniker
, rf2
.dwMerit
};
1168 IMoniker_AddRef(pMoniker
);
1169 add_data(&monikers
, &mm
, sizeof(mm
));
1173 FM2_DeleteRegFilter(&rf2
);
1175 IPropertyBag_Release(pPropBag
);
1176 IMoniker_Release(pMoniker
);
1178 IEnumMoniker_Release(pEnum
);
1184 IPropertyBag_Release(pPropBagCat
);
1185 IMoniker_Release(pMonikerCat
);
1190 IMoniker
** ppMoniker
;
1192 ULONG nMonikerCount
= monikers
.current
/ sizeof(struct MONIKER_MERIT
);
1194 /* sort the monikers in descending merit order */
1195 qsort(monikers
.pData
, nMonikerCount
,
1196 sizeof(struct MONIKER_MERIT
),
1199 /* construct an IEnumMoniker interface */
1200 ppMoniker
= CoTaskMemAlloc(nMonikerCount
* sizeof(IMoniker
*));
1201 for (i
= 0; i
< nMonikerCount
; i
++)
1203 /* no need to AddRef here as already AddRef'd above */
1204 ppMoniker
[i
] = ((struct MONIKER_MERIT
*)monikers
.pData
)[i
].pMoniker
;
1206 hr
= enum_moniker_create(ppMoniker
, nMonikerCount
, ppEnum
);
1207 CoTaskMemFree(ppMoniker
);
1210 delete_vector(&monikers
);
1211 IEnumMoniker_Release(pEnumCat
);
1212 ICreateDevEnum_Release(pCreateDevEnum
);
1217 static HRESULT WINAPI
FilterMapper3_GetICreateDevEnum(IFilterMapper3
*iface
, ICreateDevEnum
**ppEnum
)
1219 TRACE("(%p, %p)\n", iface
, ppEnum
);
1222 return CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC
, &IID_ICreateDevEnum
, (void**)ppEnum
);
1225 static const IFilterMapper3Vtbl fm3vtbl
=
1228 FilterMapper3_QueryInterface
,
1229 FilterMapper3_AddRef
,
1230 FilterMapper3_Release
,
1232 FilterMapper3_CreateCategory
,
1233 FilterMapper3_UnregisterFilter
,
1234 FilterMapper3_RegisterFilter
,
1235 FilterMapper3_EnumMatchingFilters
,
1236 FilterMapper3_GetICreateDevEnum
1239 /*** IUnknown methods ***/
1241 static HRESULT WINAPI
FilterMapper_QueryInterface(IFilterMapper
* iface
, REFIID riid
, LPVOID
*ppv
)
1243 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1245 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
1247 return FilterMapper3_QueryInterface(&This
->IFilterMapper3_iface
, riid
, ppv
);
1250 static ULONG WINAPI
FilterMapper_AddRef(IFilterMapper
* iface
)
1252 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1254 return IUnknown_AddRef(This
->outer_unk
);
1257 static ULONG WINAPI
FilterMapper_Release(IFilterMapper
* iface
)
1259 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1261 return IUnknown_Release(This
->outer_unk
);
1264 /*** IFilterMapper methods ***/
1266 static HRESULT WINAPI
FilterMapper_EnumMatchingFilters(
1267 IFilterMapper
* iface
,
1268 IEnumRegFilters
**ppEnum
,
1278 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1281 IEnumMoniker
* ppEnumMoniker
;
1284 ULONG idx
= 0, nb_mon
= 0;
1285 REGFILTER
* regfilters
;
1288 TRACE("(%p/%p)->(%p, %#lx, %s, %s, %s, %s, %s, %s, %s)\n",
1293 bInputNeeded
? "true" : "false",
1294 debugstr_guid(&clsInMaj
),
1295 debugstr_guid(&clsInSub
),
1296 bRender
? "true" : "false",
1297 bOutputNeeded
? "true" : "false",
1298 debugstr_guid(&clsOutMaj
),
1299 debugstr_guid(&clsOutSub
));
1301 InputType
[0] = clsInMaj
;
1302 InputType
[1] = clsInSub
;
1303 OutputType
[0] = clsOutMaj
;
1304 OutputType
[1] = clsOutSub
;
1308 hr
= IFilterMapper3_EnumMatchingFilters(&This
->IFilterMapper3_iface
, &ppEnumMoniker
, 0, TRUE
,
1309 dwMerit
, bInputNeeded
, 1, InputType
, NULL
, &GUID_NULL
, bRender
, bOutputNeeded
, 1,
1310 OutputType
, NULL
, &GUID_NULL
);
1315 while(IEnumMoniker_Next(ppEnumMoniker
, 1, &IMon
, &nb
) == S_OK
)
1317 IMoniker_Release(IMon
);
1323 IEnumMoniker_Release(ppEnumMoniker
);
1324 return enum_reg_filters_create(NULL
, 0, ppEnum
);
1327 regfilters
= CoTaskMemAlloc(nb_mon
* sizeof(REGFILTER
));
1330 IEnumMoniker_Release(ppEnumMoniker
);
1331 return E_OUTOFMEMORY
;
1333 ZeroMemory(regfilters
, nb_mon
* sizeof(REGFILTER
)); /* will prevent bad free of Name in case of error. */
1335 IEnumMoniker_Reset(ppEnumMoniker
);
1336 while(IEnumMoniker_Next(ppEnumMoniker
, 1, &IMon
, &nb
) == S_OK
)
1338 IPropertyBag
* pPropBagCat
= NULL
;
1346 hrSub
= IMoniker_BindToStorage(IMon
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBagCat
);
1348 if (SUCCEEDED(hrSub
))
1349 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"CLSID", &var
, NULL
);
1351 if (SUCCEEDED(hrSub
))
1352 hrSub
= CLSIDFromString(V_BSTR(&var
), &clsid
);
1356 if (SUCCEEDED(hrSub
))
1357 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"FriendlyName", &var
, NULL
);
1359 if (SUCCEEDED(hrSub
))
1361 len
= (wcslen(V_BSTR(&var
)) + 1) * sizeof(WCHAR
);
1362 if (!(regfilters
[idx
].Name
= CoTaskMemAlloc(len
*2)))
1366 if (SUCCEEDED(hrSub
) && regfilters
[idx
].Name
)
1368 memcpy(regfilters
[idx
].Name
, V_BSTR(&var
), len
);
1369 regfilters
[idx
].Clsid
= clsid
;
1374 IPropertyBag_Release(pPropBagCat
);
1375 IMoniker_Release(IMon
);
1381 hr
= enum_reg_filters_create(regfilters
, idx
, ppEnum
);
1384 for (idx
= 0; idx
< nb_mon
; idx
++)
1385 CoTaskMemFree(regfilters
[idx
].Name
);
1386 CoTaskMemFree(regfilters
);
1387 IEnumMoniker_Release(ppEnumMoniker
);
1393 static HRESULT WINAPI
FilterMapper_RegisterFilter(IFilterMapper
* iface
,
1394 CLSID clsid
, const WCHAR
*name
, DWORD merit
)
1396 WCHAR keypath
[46], guidstr
[39];
1400 TRACE("iface %p, clsid %s, name %s, merit %#lx.\n",
1401 iface
, debugstr_guid(&clsid
), debugstr_w(name
), merit
);
1403 StringFromGUID2(&clsid
, guidstr
, ARRAY_SIZE(guidstr
));
1405 wcscpy(keypath
, L
"Filter\\");
1406 wcscat(keypath
, guidstr
);
1407 if ((ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
)))
1408 return HRESULT_FROM_WIN32(ret
);
1410 if ((ret
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (const BYTE
*)name
, (wcslen(name
) + 1) * sizeof(WCHAR
))))
1411 ERR("Failed to set filter name, error %lu.\n", ret
);
1414 wcscpy(keypath
, L
"CLSID\\");
1415 wcscat(keypath
, guidstr
);
1416 if (!(ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
)))
1418 if ((ret
= RegSetValueExW(key
, L
"Merit", 0, REG_DWORD
, (const BYTE
*)&merit
, sizeof(DWORD
))))
1419 ERR("Failed to set merit, error %lu.\n", ret
);
1423 ERR("Failed to create CLSID key, error %lu.\n", ret
);
1428 static HRESULT WINAPI
FilterMapper_RegisterFilterInstance(IFilterMapper
* iface
, CLSID clsid
, LPCWSTR szName
, CLSID
*MRId
)
1430 TRACE("(%p)->(%s, %s, %p)\n", iface
, debugstr_guid(&clsid
), debugstr_w(szName
), MRId
);
1432 /* Not implemented in Windows (tested on Win2k) */
1437 static HRESULT WINAPI
FilterMapper_RegisterPin(IFilterMapper
*iface
, CLSID clsid
,
1438 const WCHAR
*name
, BOOL rendered
, BOOL output
, BOOL zero
, BOOL many
,
1439 CLSID external_filter
, const WCHAR
*external_pin
)
1441 WCHAR keypath
[6 + 38 + 1], *pin_keypath
;
1442 HKEY key
, pin_key
, type_key
;
1445 TRACE("iface %p, clsid %s, name %s, rendered %d, output %d, zero %d, "
1446 "many %d, external_filter %s, external_pin %s.\n",
1447 iface
, debugstr_guid(&clsid
), debugstr_w(name
), rendered
, output
,
1448 zero
, many
, debugstr_guid(&external_filter
), debugstr_w(external_pin
));
1450 wcscpy(keypath
, L
"CLSID\\");
1451 StringFromGUID2(&clsid
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
1452 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, KEY_WRITE
, &key
)))
1453 return HRESULT_FROM_WIN32(ret
);
1455 if (!(pin_keypath
= malloc((5 + wcslen(name
) + 1) * sizeof(WCHAR
))))
1458 return E_OUTOFMEMORY
;
1460 wcscpy(pin_keypath
, L
"Pins\\");
1461 wcscat(pin_keypath
, name
);
1463 if ((ret
= RegCreateKeyExW(key
, pin_keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &pin_key
, NULL
)))
1465 ERR("Failed to open pin key, error %lu.\n", ret
);
1468 return HRESULT_FROM_WIN32(ret
);
1472 if ((ret
= RegSetValueExW(pin_key
, L
"AllowedMany", 0, REG_DWORD
, (const BYTE
*)&many
, sizeof(DWORD
))))
1473 ERR("Failed to set AllowedMany value, error %lu.\n", ret
);
1474 if ((ret
= RegSetValueExW(pin_key
, L
"AllowedZero", 0, REG_DWORD
, (const BYTE
*)&zero
, sizeof(DWORD
))))
1475 ERR("Failed to set AllowedZero value, error %lu.\n", ret
);
1476 if ((ret
= RegSetValueExW(pin_key
, L
"Direction", 0, REG_DWORD
, (const BYTE
*)&output
, sizeof(DWORD
))))
1477 ERR("Failed to set Direction value, error %lu.\n", ret
);
1478 if ((ret
= RegSetValueExW(pin_key
, L
"IsRendered", 0, REG_DWORD
, (const BYTE
*)&rendered
, sizeof(DWORD
))))
1479 ERR("Failed to set IsRendered value, error %lu.\n", ret
);
1481 if (!(ret
= RegCreateKeyExW(pin_key
, L
"Types", 0, NULL
, 0, 0, NULL
, &type_key
, NULL
)))
1482 RegCloseKey(type_key
);
1484 ERR("Failed to create Types subkey, error %lu.\n", ret
);
1486 RegCloseKey(pin_key
);
1493 static HRESULT WINAPI
FilterMapper_RegisterPinType(IFilterMapper
*iface
,
1494 CLSID clsid
, const WCHAR
*pin
, CLSID majortype
, CLSID subtype
)
1496 WCHAR
*keypath
, type_keypath
[38 + 1 + 38 + 1];
1501 TRACE("iface %p, clsid %s, pin %s, majortype %s, subtype %s.\n", iface
,
1502 debugstr_guid(&clsid
), debugstr_w(pin
), debugstr_guid(&majortype
), debugstr_guid(&subtype
));
1504 len
= 6 + 38 + 6 + wcslen(pin
) + 6 + 1;
1505 if (!(keypath
= malloc(len
* sizeof(WCHAR
))))
1506 return E_OUTOFMEMORY
;
1508 wcscpy(keypath
, L
"CLSID\\");
1509 StringFromGUID2(&clsid
, keypath
+ wcslen(keypath
), len
- wcslen(keypath
));
1510 wcscat(keypath
, L
"\\Pins\\");
1511 wcscat(keypath
, pin
);
1512 wcscat(keypath
, L
"\\Types");
1513 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, KEY_CREATE_SUB_KEY
, &key
)))
1516 return HRESULT_FROM_WIN32(ret
);
1520 StringFromGUID2(&majortype
, type_keypath
, ARRAY_SIZE(type_keypath
));
1521 wcscat(type_keypath
, L
"\\");
1522 StringFromGUID2(&subtype
, type_keypath
+ wcslen(type_keypath
), ARRAY_SIZE(type_keypath
) - wcslen(type_keypath
));
1523 if (!(ret
= RegCreateKeyExW(key
, type_keypath
, 0, NULL
, 0, 0, NULL
, &type_key
, NULL
)))
1524 RegCloseKey(type_key
);
1526 ERR("Failed to create type key, error %lu.\n", ret
);
1529 return HRESULT_FROM_WIN32(ret
);
1532 static HRESULT WINAPI
FilterMapper_UnregisterFilter(IFilterMapper
*iface
, CLSID clsid
)
1534 WCHAR guidstr
[39], keypath
[6 + 38 + 1];
1538 TRACE("iface %p, clsid %s.\n", iface
, debugstr_guid(&clsid
));
1540 StringFromGUID2(&clsid
, guidstr
, ARRAY_SIZE(guidstr
));
1542 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"Filter", 0, 0, &key
)))
1543 return HRESULT_FROM_WIN32(ret
);
1544 if ((ret
= RegDeleteKeyW(key
, guidstr
)))
1545 ERR("Failed to delete filter key, error %lu.\n", ret
);
1548 wcscpy(keypath
, L
"CLSID\\");
1549 wcscat(keypath
, guidstr
);
1550 if (!(ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, KEY_WRITE
, &key
)))
1552 if ((ret
= RegDeleteValueW(key
, L
"Merit")))
1553 ERR("Failed to delete Merit value, error %lu.\n", ret
);
1554 if ((ret
= RegDeleteTreeW(key
, L
"Pins")))
1555 ERR("Failed to delete Pins key, error %lu.\n", ret
);
1559 ERR("Failed to open CLSID key, error %lu.\n", ret
);
1564 static HRESULT WINAPI
FilterMapper_UnregisterFilterInstance(IFilterMapper
* iface
, CLSID MRId
)
1566 TRACE("(%p)->(%s)\n", iface
, debugstr_guid(&MRId
));
1568 /* Not implemented in Windows (tested on Win2k) */
1573 static HRESULT WINAPI
FilterMapper_UnregisterPin(IFilterMapper
* iface
, CLSID clsid
, const WCHAR
*name
)
1575 WCHAR keypath
[6 + 38 + 5 + 1];
1579 TRACE("iface %p, clsid %s, name %s.\n", iface
, debugstr_guid(&clsid
), debugstr_w(name
));
1582 return E_INVALIDARG
;
1584 wcscpy(keypath
, L
"CLSID\\");
1585 StringFromGUID2(&clsid
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
1586 wcscat(keypath
, L
"\\Pins");
1587 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, 0, &key
)))
1588 return HRESULT_FROM_WIN32(ret
);
1590 if ((ret
= RegDeleteTreeW(key
, name
)))
1591 ERR("Failed to delete subkey, error %lu.\n", ret
);
1598 static const IFilterMapperVtbl fmvtbl
=
1601 FilterMapper_QueryInterface
,
1602 FilterMapper_AddRef
,
1603 FilterMapper_Release
,
1605 FilterMapper_RegisterFilter
,
1606 FilterMapper_RegisterFilterInstance
,
1607 FilterMapper_RegisterPin
,
1608 FilterMapper_RegisterPinType
,
1609 FilterMapper_UnregisterFilter
,
1610 FilterMapper_UnregisterFilterInstance
,
1611 FilterMapper_UnregisterPin
,
1612 FilterMapper_EnumMatchingFilters
1616 /*** IUnknown methods ***/
1617 static HRESULT WINAPI
AMFilterData_QueryInterface(IAMFilterData
* iface
, REFIID riid
, LPVOID
*ppv
)
1619 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1621 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
1624 static ULONG WINAPI
AMFilterData_AddRef(IAMFilterData
* iface
)
1626 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1628 return IUnknown_AddRef(This
->outer_unk
);
1631 static ULONG WINAPI
AMFilterData_Release(IAMFilterData
* iface
)
1633 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1635 return IUnknown_Release(This
->outer_unk
);
1638 /*** IAMFilterData methods ***/
1639 static HRESULT WINAPI
AMFilterData_ParseFilterData(IAMFilterData
* iface
,
1640 BYTE
*pData
, ULONG cb
,
1641 BYTE
**ppRegFilter2
)
1643 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1645 static REGFILTER2
*prf2
;
1647 TRACE("mapper %p, data %p, size %lu, parsed_data %p.\n", This
, pData
, cb
, ppRegFilter2
);
1649 prf2
= CoTaskMemAlloc(sizeof(*prf2
));
1651 return E_OUTOFMEMORY
;
1652 *ppRegFilter2
= (BYTE
*)&prf2
;
1654 hr
= FM2_ReadFilterData(pData
, prf2
);
1657 CoTaskMemFree(prf2
);
1658 *ppRegFilter2
= NULL
;
1664 static HRESULT WINAPI
AMFilterData_CreateFilterData(IAMFilterData
* iface
,
1666 BYTE
**pRegFilterData
,
1669 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1671 TRACE("(%p/%p)->(%p, %p, %p)\n", This
, iface
, prf2
, pRegFilterData
, pcb
);
1673 return FM2_WriteFilterData(prf2
, pRegFilterData
, pcb
);
1676 static const IAMFilterDataVtbl AMFilterDataVtbl
= {
1677 AMFilterData_QueryInterface
,
1678 AMFilterData_AddRef
,
1679 AMFilterData_Release
,
1680 AMFilterData_ParseFilterData
,
1681 AMFilterData_CreateFilterData
1684 HRESULT
filter_mapper_create(IUnknown
*pUnkOuter
, IUnknown
**out
)
1686 FilterMapper3Impl
* pFM2impl
;
1688 pFM2impl
= CoTaskMemAlloc(sizeof(*pFM2impl
));
1690 return E_OUTOFMEMORY
;
1692 pFM2impl
->IUnknown_inner
.lpVtbl
= &IInner_VTable
;
1693 pFM2impl
->IFilterMapper3_iface
.lpVtbl
= &fm3vtbl
;
1694 pFM2impl
->IFilterMapper_iface
.lpVtbl
= &fmvtbl
;
1695 pFM2impl
->IAMFilterData_iface
.lpVtbl
= &AMFilterDataVtbl
;
1699 pFM2impl
->outer_unk
= pUnkOuter
;
1701 pFM2impl
->outer_unk
= &pFM2impl
->IUnknown_inner
;
1703 TRACE("Created filter mapper %p.\n", pFM2impl
);
1704 *out
= &pFM2impl
->IUnknown_inner
;