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
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
32 #include "quartz_private.h"
39 #include "wine/fil_data.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
45 struct enum_reg_filters
47 IEnumRegFilters IEnumRegFilters_iface
;
50 unsigned int index
, count
;
54 static struct enum_reg_filters
*impl_from_IEnumRegFilters(IEnumRegFilters
*iface
)
56 return CONTAINING_RECORD(iface
, struct enum_reg_filters
, IEnumRegFilters_iface
);
59 static HRESULT WINAPI
enum_reg_filters_QueryInterface(IEnumRegFilters
*iface
, REFIID iid
, void **out
)
61 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
63 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumRegFilters
))
65 IEnumRegFilters_AddRef(iface
);
70 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
75 static ULONG WINAPI
enum_reg_filters_AddRef(IEnumRegFilters
*iface
)
77 struct enum_reg_filters
*enumerator
= impl_from_IEnumRegFilters(iface
);
78 ULONG refcount
= InterlockedIncrement(&enumerator
->refcount
);
79 TRACE("%p increasing refcount to %u.\n", enumerator
, refcount
);
83 static ULONG WINAPI
enum_reg_filters_Release(IEnumRegFilters
*iface
)
85 struct enum_reg_filters
*enumerator
= impl_from_IEnumRegFilters(iface
);
86 ULONG refcount
= InterlockedDecrement(&enumerator
->refcount
);
89 TRACE("%p decreasing refcount to %u.\n", enumerator
, refcount
);
92 for (i
= 0; i
< enumerator
->count
; ++i
)
93 free(enumerator
->filters
[i
].Name
);
94 free(enumerator
->filters
);
100 static HRESULT WINAPI
enum_reg_filters_Next(IEnumRegFilters
*iface
, ULONG count
,
101 REGFILTER
**filters
, ULONG
*ret_count
)
103 struct enum_reg_filters
*enumerator
= impl_from_IEnumRegFilters(iface
);
106 TRACE("iface %p, count %u, filters %p, ret_count %p.\n", iface
, count
, filters
, ret_count
);
108 for (i
= 0; i
< count
&& enumerator
->index
+ i
< enumerator
->count
; ++i
)
110 REGFILTER
*filter
= &enumerator
->filters
[enumerator
->index
+ i
];
112 if (!(filters
[i
] = CoTaskMemAlloc(sizeof(REGFILTER
) + (wcslen(filter
->Name
) + 1) * sizeof(WCHAR
))))
115 CoTaskMemFree(filters
[i
]);
116 memset(filters
, 0, count
* sizeof(*filters
));
118 return E_OUTOFMEMORY
;
121 filters
[i
]->Clsid
= filter
->Clsid
;
122 filters
[i
]->Name
= (WCHAR
*)(filters
[i
] + 1);
123 wcscpy(filters
[i
]->Name
, filter
->Name
);
126 enumerator
->index
+= i
;
129 return i
? S_OK
: S_FALSE
;
132 static HRESULT WINAPI
enum_reg_filters_Skip(IEnumRegFilters
*iface
, ULONG count
)
134 TRACE("iface %p, count %u, unimplemented.\n", iface
, count
);
138 static HRESULT WINAPI
enum_reg_filters_Reset(IEnumRegFilters
*iface
)
140 struct enum_reg_filters
*enumerator
= impl_from_IEnumRegFilters(iface
);
142 TRACE("iface %p.\n", iface
);
144 enumerator
->index
= 0;
148 static HRESULT WINAPI
enum_reg_filters_Clone(IEnumRegFilters
*iface
, IEnumRegFilters
**out
)
150 TRACE("iface %p, out %p, unimplemented.\n", iface
, out
);
154 static const IEnumRegFiltersVtbl enum_reg_filters_vtbl
=
156 enum_reg_filters_QueryInterface
,
157 enum_reg_filters_AddRef
,
158 enum_reg_filters_Release
,
159 enum_reg_filters_Next
,
160 enum_reg_filters_Skip
,
161 enum_reg_filters_Reset
,
162 enum_reg_filters_Clone
,
165 static HRESULT
enum_reg_filters_create(REGFILTER
*filters
, unsigned int count
, IEnumRegFilters
**out
)
167 struct enum_reg_filters
*object
;
172 if (!(object
= calloc(1, sizeof(*object
))))
173 return E_OUTOFMEMORY
;
175 if (!(object
->filters
= malloc(count
* sizeof(*object
->filters
))))
178 return E_OUTOFMEMORY
;
181 for (i
= 0; i
< count
; ++i
)
183 object
->filters
[i
].Clsid
= filters
[i
].Clsid
;
184 if (!(object
->filters
[i
].Name
= wcsdup(filters
[i
].Name
)))
187 free(object
->filters
[i
].Name
);
188 free(object
->filters
);
190 return E_OUTOFMEMORY
;
194 object
->IEnumRegFilters_iface
.lpVtbl
= &enum_reg_filters_vtbl
;
195 object
->refcount
= 1;
196 object
->count
= count
;
198 TRACE("Created enumerator %p.\n", object
);
199 *out
= &object
->IEnumRegFilters_iface
;
205 IEnumMoniker IEnumMoniker_iface
;
208 unsigned int index
, count
;
212 static struct enum_moniker
*impl_from_IEnumMoniker(IEnumMoniker
*iface
)
214 return CONTAINING_RECORD(iface
, struct enum_moniker
, IEnumMoniker_iface
);
217 static HRESULT WINAPI
enum_moniker_QueryInterface(IEnumMoniker
*iface
, REFIID iid
, void **out
)
219 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
221 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumMoniker
))
223 IEnumMoniker_AddRef(iface
);
228 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
230 return E_NOINTERFACE
;
233 static ULONG WINAPI
enum_moniker_AddRef(IEnumMoniker
*iface
)
235 struct enum_moniker
*enumerator
= impl_from_IEnumMoniker(iface
);
236 ULONG refcount
= InterlockedIncrement(&enumerator
->refcount
);
237 TRACE("%p increasing refcount to %u.\n", enumerator
, refcount
);
241 static ULONG WINAPI
enum_moniker_Release(IEnumMoniker
*iface
)
243 struct enum_moniker
*enumerator
= impl_from_IEnumMoniker(iface
);
244 ULONG refcount
= InterlockedDecrement(&enumerator
->refcount
);
247 TRACE("%p decreasing refcount to %u.\n", enumerator
, refcount
);
250 for (i
= 0; i
< enumerator
->count
; ++i
)
251 IMoniker_Release(enumerator
->filters
[i
]);
252 free(enumerator
->filters
);
258 static HRESULT WINAPI
enum_moniker_Next(IEnumMoniker
*iface
, ULONG count
,
259 IMoniker
**filters
, ULONG
*ret_count
)
261 struct enum_moniker
*enumerator
= impl_from_IEnumMoniker(iface
);
264 TRACE("iface %p, count %u, filters %p, ret_count %p.\n", iface
, count
, filters
, ret_count
);
266 for (i
= 0; i
< count
&& enumerator
->index
+ i
< enumerator
->count
; ++i
)
267 IMoniker_AddRef(filters
[i
] = enumerator
->filters
[enumerator
->index
+ i
]);
269 enumerator
->index
+= i
;
272 return i
? S_OK
: S_FALSE
;
275 static HRESULT WINAPI
enum_moniker_Skip(IEnumMoniker
*iface
, ULONG count
)
277 struct enum_moniker
*enumerator
= impl_from_IEnumMoniker(iface
);
279 TRACE("iface %p, count %u.\n", iface
, count
);
281 enumerator
->index
+= count
;
285 static HRESULT WINAPI
enum_moniker_Reset(IEnumMoniker
*iface
)
287 struct enum_moniker
*enumerator
= impl_from_IEnumMoniker(iface
);
289 TRACE("iface %p.\n", iface
);
291 enumerator
->index
= 0;
295 static HRESULT WINAPI
enum_moniker_Clone(IEnumMoniker
*iface
, IEnumMoniker
**out
)
297 TRACE("iface %p, out %p, unimplemented.\n", iface
, out
);
301 static const IEnumMonikerVtbl enum_moniker_vtbl
=
303 enum_moniker_QueryInterface
,
305 enum_moniker_Release
,
312 static HRESULT
enum_moniker_create(IMoniker
**filters
, unsigned int count
, IEnumMoniker
**out
)
314 struct enum_moniker
*object
;
318 if (!(object
= calloc(1, sizeof(*object
))))
319 return E_OUTOFMEMORY
;
321 if (!(object
->filters
= malloc(count
* sizeof(*object
->filters
))))
324 return E_OUTOFMEMORY
;
326 memcpy(object
->filters
, filters
, count
* sizeof(*filters
));
328 object
->IEnumMoniker_iface
.lpVtbl
= &enum_moniker_vtbl
;
329 object
->refcount
= 1;
330 object
->count
= count
;
332 TRACE("Created enumerator %p.\n", object
);
333 *out
= &object
->IEnumMoniker_iface
;
337 typedef struct FilterMapper3Impl
339 IUnknown IUnknown_inner
;
340 IFilterMapper3 IFilterMapper3_iface
;
341 IFilterMapper IFilterMapper_iface
;
342 IAMFilterData IAMFilterData_iface
;
347 static inline FilterMapper3Impl
*impl_from_IFilterMapper3( IFilterMapper3
*iface
)
349 return CONTAINING_RECORD(iface
, FilterMapper3Impl
, IFilterMapper3_iface
);
352 static inline FilterMapper3Impl
*impl_from_IFilterMapper( IFilterMapper
*iface
)
354 return CONTAINING_RECORD(iface
, FilterMapper3Impl
, IFilterMapper_iface
);
357 static inline FilterMapper3Impl
*impl_from_IAMFilterData( IAMFilterData
*iface
)
359 return CONTAINING_RECORD(iface
, FilterMapper3Impl
, IAMFilterData_iface
);
362 static inline FilterMapper3Impl
*impl_from_IUnknown( IUnknown
*iface
)
364 return CONTAINING_RECORD(iface
, FilterMapper3Impl
, IUnknown_inner
);
367 /* registry format for REGFILTER2 */
378 BYTE signature
[4]; /* e.g. "0pi3" */
383 DWORD bCategory
; /* is there a category clsid? */
384 /* optional: dwOffsetCategoryClsid */
389 BYTE signature
[4]; /* e.g. "0ty3" */
404 int capacity
; /* in bytes */
405 int current
; /* pointer to next free byte */
408 /* returns the position it was added at */
409 static int add_data(struct Vector
*v
, const void *pData
, int size
)
411 int index
= v
->current
;
412 if (v
->current
+ size
> v
->capacity
)
414 int new_capacity
= (v
->capacity
+ size
) * 2;
415 BYTE
*new_data
= CoTaskMemRealloc(v
->pData
, new_capacity
);
416 if (!new_data
) return -1;
417 v
->capacity
= new_capacity
;
420 memcpy(v
->pData
+ v
->current
, pData
, size
);
425 static int find_data(const struct Vector
*v
, const void *pData
, int size
)
428 for (index
= 0; index
< v
->current
; index
++)
429 if (!memcmp(v
->pData
+ index
, pData
, size
))
435 static void delete_vector(struct Vector
* v
)
437 CoTaskMemFree(v
->pData
);
442 /*** IUnknown (inner) methods ***/
444 static HRESULT WINAPI
Inner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
446 FilterMapper3Impl
*This
= impl_from_IUnknown(iface
);
448 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
451 if (IsEqualIID(riid
, &IID_IUnknown
))
452 *ppv
= &This
->IUnknown_inner
;
453 else if (IsEqualIID(riid
, &IID_IFilterMapper2
) || IsEqualIID(riid
, &IID_IFilterMapper3
))
454 *ppv
= &This
->IFilterMapper3_iface
;
455 else if (IsEqualIID(riid
, &IID_IFilterMapper
))
456 *ppv
= &This
->IFilterMapper_iface
;
457 else if (IsEqualIID(riid
, &IID_IAMFilterData
))
458 *ppv
= &This
->IAMFilterData_iface
;
462 IUnknown_AddRef((IUnknown
*)*ppv
);
466 FIXME("No interface for %s\n", debugstr_guid(riid
));
467 return E_NOINTERFACE
;
470 static ULONG WINAPI
Inner_AddRef(IUnknown
*iface
)
472 FilterMapper3Impl
*This
= impl_from_IUnknown(iface
);
473 ULONG ref
= InterlockedIncrement(&This
->ref
);
475 TRACE("(%p)->(): new ref = %d\n", This
, ref
);
480 static ULONG WINAPI
Inner_Release(IUnknown
*iface
)
482 FilterMapper3Impl
*This
= impl_from_IUnknown(iface
);
483 ULONG ref
= InterlockedDecrement(&This
->ref
);
485 TRACE("(%p)->(): new ref = %d\n", This
, ref
);
491 InterlockedDecrement(&object_locks
);
497 static const IUnknownVtbl IInner_VTable
=
499 Inner_QueryInterface
,
504 static HRESULT WINAPI
FilterMapper3_QueryInterface(IFilterMapper3
* iface
, REFIID riid
, LPVOID
*ppv
)
506 FilterMapper3Impl
*This
= impl_from_IFilterMapper3(iface
);
508 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
511 static ULONG WINAPI
FilterMapper3_AddRef(IFilterMapper3
* iface
)
513 FilterMapper3Impl
*This
= impl_from_IFilterMapper3(iface
);
515 return IUnknown_AddRef(This
->outer_unk
);
518 static ULONG WINAPI
FilterMapper3_Release(IFilterMapper3
* iface
)
520 FilterMapper3Impl
*This
= impl_from_IFilterMapper3(iface
);
522 return IUnknown_Release(This
->outer_unk
);
525 /*** IFilterMapper3 methods ***/
527 static HRESULT WINAPI
FilterMapper3_CreateCategory(IFilterMapper3
*iface
,
528 REFCLSID category
, DWORD merit
, const WCHAR
*description
)
530 WCHAR guidstr
[39], keypath
[93];
534 TRACE("iface %p, category %s, merit %#x, description %s.\n", iface
,
535 debugstr_guid(category
), merit
, debugstr_w(description
));
537 StringFromGUID2(category
, guidstr
, ARRAY_SIZE(guidstr
));
538 wcscpy(keypath
, L
"CLSID\\{da4e3da0-d07d-11d0-bd50-00a0c911ce86}\\Instance\\");
539 wcscat(keypath
, guidstr
);
541 if ((ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
)))
542 return HRESULT_FROM_WIN32(ret
);
544 if ((ret
= RegSetValueExW(key
, L
"FriendlyName", 0, REG_SZ
,
545 (const BYTE
*)description
, (wcslen(description
) + 1) * sizeof(WCHAR
))))
548 return HRESULT_FROM_WIN32(ret
);
551 if ((ret
= RegSetValueExW(key
, L
"CLSID", 0, REG_SZ
, (const BYTE
*)guidstr
, sizeof(guidstr
))))
554 return HRESULT_FROM_WIN32(ret
);
557 if ((ret
= RegSetValueExW(key
, L
"Merit", 0, REG_DWORD
, (const BYTE
*)&merit
, sizeof(DWORD
))))
560 return HRESULT_FROM_WIN32(ret
);
567 static HRESULT WINAPI
FilterMapper3_UnregisterFilter(IFilterMapper3
*iface
,
568 const CLSID
*category
, const WCHAR
*instance
, REFCLSID clsid
)
572 TRACE("iface %p, category %s, instance %s, clsid %s.\n",
573 iface
, debugstr_guid(category
), debugstr_w(instance
), debugstr_guid(clsid
));
576 category
= &CLSID_LegacyAmFilterCategory
;
578 wcscpy(keypath
, L
"CLSID\\");
579 StringFromGUID2(category
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
580 wcscat(keypath
, L
"\\Instance\\");
582 wcscat(keypath
, instance
);
584 StringFromGUID2(clsid
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
586 return HRESULT_FROM_WIN32(RegDeleteKeyW(HKEY_CLASSES_ROOT
, keypath
));
589 static HRESULT
FM2_WriteFilterData(const REGFILTER2
* prf2
, BYTE
**ppData
, ULONG
*pcbData
)
591 int size
= sizeof(struct REG_RF
);
593 struct Vector mainStore
= {NULL
, 0, 0};
594 struct Vector clsidStore
= {NULL
, 0, 0};
598 rrf
.dwVersion
= prf2
->dwVersion
;
599 rrf
.dwMerit
= prf2
->dwMerit
;
600 rrf
.dwPins
= prf2
->cPins2
;
603 add_data(&mainStore
, &rrf
, sizeof(rrf
));
605 for (i
= 0; i
< prf2
->cPins2
; i
++)
607 size
+= sizeof(struct REG_RFP
);
608 if (prf2
->rgPins2
[i
].clsPinCategory
)
609 size
+= sizeof(DWORD
);
610 size
+= prf2
->rgPins2
[i
].nMediaTypes
* sizeof(struct REG_TYPE
);
611 size
+= prf2
->rgPins2
[i
].nMediums
* sizeof(DWORD
);
614 for (i
= 0; i
< prf2
->cPins2
; i
++)
617 REGFILTERPINS2 rgPin2
= prf2
->rgPins2
[i
];
620 rrfp
.signature
[0] = '0';
621 rrfp
.signature
[1] = 'p';
622 rrfp
.signature
[2] = 'i';
623 rrfp
.signature
[3] = '3';
624 rrfp
.signature
[0] += i
;
625 rrfp
.dwFlags
= rgPin2
.dwFlags
;
626 rrfp
.dwInstances
= rgPin2
.cInstances
;
627 rrfp
.dwMediaTypes
= rgPin2
.nMediaTypes
;
628 rrfp
.dwMediums
= rgPin2
.nMediums
;
629 rrfp
.bCategory
= rgPin2
.clsPinCategory
? 1 : 0;
631 add_data(&mainStore
, &rrfp
, sizeof(rrfp
));
634 DWORD index
= find_data(&clsidStore
, rgPin2
.clsPinCategory
, sizeof(CLSID
));
636 index
= add_data(&clsidStore
, rgPin2
.clsPinCategory
, sizeof(CLSID
));
639 add_data(&mainStore
, &index
, sizeof(index
));
642 for (j
= 0; j
< rgPin2
.nMediaTypes
; j
++)
645 const CLSID
* clsMinorType
= rgPin2
.lpMediaType
[j
].clsMinorType
? rgPin2
.lpMediaType
[j
].clsMinorType
: &MEDIASUBTYPE_NULL
;
646 rt
.signature
[0] = '0';
647 rt
.signature
[1] = 't';
648 rt
.signature
[2] = 'y';
649 rt
.signature
[3] = '3';
650 rt
.signature
[0] += j
;
652 rt
.dwOffsetMajor
= find_data(&clsidStore
, rgPin2
.lpMediaType
[j
].clsMajorType
, sizeof(CLSID
));
653 if (rt
.dwOffsetMajor
== -1)
654 rt
.dwOffsetMajor
= add_data(&clsidStore
, rgPin2
.lpMediaType
[j
].clsMajorType
, sizeof(CLSID
));
655 rt
.dwOffsetMajor
+= size
;
656 rt
.dwOffsetMinor
= find_data(&clsidStore
, clsMinorType
, sizeof(CLSID
));
657 if (rt
.dwOffsetMinor
== -1)
658 rt
.dwOffsetMinor
= add_data(&clsidStore
, clsMinorType
, sizeof(CLSID
));
659 rt
.dwOffsetMinor
+= size
;
661 add_data(&mainStore
, &rt
, sizeof(rt
));
664 for (j
= 0; j
< rgPin2
.nMediums
; j
++)
666 DWORD index
= find_data(&clsidStore
, rgPin2
.lpMedium
+ j
, sizeof(REGPINMEDIUM
));
668 index
= add_data(&clsidStore
, rgPin2
.lpMedium
+ j
, sizeof(REGPINMEDIUM
));
671 add_data(&mainStore
, &index
, sizeof(index
));
677 *pcbData
= mainStore
.current
+ clsidStore
.current
;
678 *ppData
= CoTaskMemAlloc(*pcbData
);
685 memcpy(*ppData
, mainStore
.pData
, mainStore
.current
);
686 memcpy((*ppData
) + mainStore
.current
, clsidStore
.pData
, clsidStore
.current
);
689 delete_vector(&mainStore
);
690 delete_vector(&clsidStore
);
694 static HRESULT
FM2_ReadFilterData(BYTE
*pData
, REGFILTER2
* prf2
)
697 struct REG_RF
* prrf
;
700 REGFILTERPINS2
* rgPins2
;
702 prrf
= (struct REG_RF
*)pData
;
705 if (prrf
->dwVersion
!= 2)
707 FIXME("Filter registry version %d not supported\n", prrf
->dwVersion
);
708 ZeroMemory(prf2
, sizeof(*prf2
));
714 TRACE("version = %d, merit = %x, #pins = %d, unused = %x\n",
715 prrf
->dwVersion
, prrf
->dwMerit
, prrf
->dwPins
, prrf
->dwUnused
);
717 prf2
->dwVersion
= prrf
->dwVersion
;
718 prf2
->dwMerit
= prrf
->dwMerit
;
719 prf2
->cPins2
= prrf
->dwPins
;
720 rgPins2
= CoTaskMemAlloc(prrf
->dwPins
* sizeof(*rgPins2
));
721 prf2
->rgPins2
= rgPins2
;
722 pCurrent
+= sizeof(struct REG_RF
);
724 for (i
= 0; i
< prrf
->dwPins
; i
++)
726 struct REG_RFP
* prrfp
= (struct REG_RFP
*)pCurrent
;
727 REGPINTYPES
* lpMediaType
;
728 REGPINMEDIUM
* lpMedium
;
731 /* FIXME: check signature */
733 TRACE("\tsignature = %s\n", debugstr_an((const char*)prrfp
->signature
, 4));
735 TRACE("\tpin[%d]: flags = %x, instances = %d, media types = %d, mediums = %d\n",
736 i
, prrfp
->dwFlags
, prrfp
->dwInstances
, prrfp
->dwMediaTypes
, prrfp
->dwMediums
);
738 rgPins2
[i
].dwFlags
= prrfp
->dwFlags
;
739 rgPins2
[i
].cInstances
= prrfp
->dwInstances
;
740 rgPins2
[i
].nMediaTypes
= prrfp
->dwMediaTypes
;
741 rgPins2
[i
].nMediums
= prrfp
->dwMediums
;
742 pCurrent
+= sizeof(struct REG_RFP
);
743 if (prrfp
->bCategory
)
745 CLSID
* clsCat
= CoTaskMemAlloc(sizeof(CLSID
));
746 memcpy(clsCat
, pData
+ *(DWORD
*)(pCurrent
), sizeof(CLSID
));
747 pCurrent
+= sizeof(DWORD
);
748 rgPins2
[i
].clsPinCategory
= clsCat
;
751 rgPins2
[i
].clsPinCategory
= NULL
;
753 if (rgPins2
[i
].nMediaTypes
> 0)
754 lpMediaType
= CoTaskMemAlloc(rgPins2
[i
].nMediaTypes
* sizeof(*lpMediaType
));
758 rgPins2
[i
].lpMediaType
= lpMediaType
;
760 for (j
= 0; j
< rgPins2
[i
].nMediaTypes
; j
++)
762 struct REG_TYPE
* prt
= (struct REG_TYPE
*)pCurrent
;
763 CLSID
* clsMajor
= CoTaskMemAlloc(sizeof(CLSID
));
764 CLSID
* clsMinor
= CoTaskMemAlloc(sizeof(CLSID
));
766 /* FIXME: check signature */
767 TRACE("\t\tsignature = %s\n", debugstr_an((const char*)prt
->signature
, 4));
769 memcpy(clsMajor
, pData
+ prt
->dwOffsetMajor
, sizeof(CLSID
));
770 memcpy(clsMinor
, pData
+ prt
->dwOffsetMinor
, sizeof(CLSID
));
772 lpMediaType
[j
].clsMajorType
= clsMajor
;
773 lpMediaType
[j
].clsMinorType
= clsMinor
;
775 pCurrent
+= sizeof(*prt
);
778 if (rgPins2
[i
].nMediums
> 0)
779 lpMedium
= CoTaskMemAlloc(rgPins2
[i
].nMediums
* sizeof(*lpMedium
));
783 rgPins2
[i
].lpMedium
= lpMedium
;
785 for (j
= 0; j
< rgPins2
[i
].nMediums
; j
++)
787 DWORD dwOffset
= *(DWORD
*)pCurrent
;
789 memcpy(lpMedium
+ j
, pData
+ dwOffset
, sizeof(REGPINMEDIUM
));
791 pCurrent
+= sizeof(dwOffset
);
800 static void FM2_DeleteRegFilter(REGFILTER2
* prf2
)
803 for (i
= 0; i
< prf2
->cPins2
; i
++)
806 CoTaskMemFree((void*)prf2
->rgPins2
[i
].clsPinCategory
);
808 for (j
= 0; j
< prf2
->rgPins2
[i
].nMediaTypes
; j
++)
810 CoTaskMemFree((LPVOID
)prf2
->rgPins2
[i
].lpMediaType
[j
].clsMajorType
);
811 CoTaskMemFree((LPVOID
)prf2
->rgPins2
[i
].lpMediaType
[j
].clsMinorType
);
813 CoTaskMemFree((LPVOID
)prf2
->rgPins2
[i
].lpMediaType
);
814 CoTaskMemFree((LPVOID
)prf2
->rgPins2
[i
].lpMedium
);
816 CoTaskMemFree((LPVOID
)prf2
->rgPins2
);
819 static HRESULT WINAPI
FilterMapper3_RegisterFilter(IFilterMapper3
*iface
,
820 REFCLSID clsid
, const WCHAR
*name
, IMoniker
**ret_moniker
,
821 const CLSID
*category
, const WCHAR
*instance
, const REGFILTER2
*prf2
)
823 WCHAR
*display_name
, clsid_string
[39];
824 IParseDisplayName
*parser
;
825 IPropertyBag
*prop_bag
;
826 ULONG filter_data_len
;
833 REGFILTER2 regfilter2
;
834 REGFILTERPINS2
* pregfp2
= NULL
;
836 TRACE("iface %p, clsid %s, name %s, ret_moniker %p, category %s, instance %s, prf2 %p.\n",
837 iface
, debugstr_guid(clsid
), debugstr_w(name
), ret_moniker
,
838 debugstr_guid(category
), debugstr_w(instance
), prf2
);
840 if (prf2
->dwVersion
== 2)
844 else if (prf2
->dwVersion
== 1)
848 /* REGFILTER2 structure is converted from version 1 to 2. Tested on Win2k. */
849 regfilter2
.dwVersion
= 2;
850 regfilter2
.dwMerit
= prf2
->dwMerit
;
851 regfilter2
.cPins2
= prf2
->cPins
;
852 pregfp2
= CoTaskMemAlloc(prf2
->cPins
* sizeof(REGFILTERPINS2
));
853 regfilter2
.rgPins2
= pregfp2
;
854 for (i
= 0; i
< prf2
->cPins
; i
++)
857 if (prf2
->rgPins
[i
].bRendered
)
858 flags
|= REG_PINFLAG_B_RENDERER
;
859 if (prf2
->rgPins
[i
].bOutput
)
860 flags
|= REG_PINFLAG_B_OUTPUT
;
861 if (prf2
->rgPins
[i
].bZero
)
862 flags
|= REG_PINFLAG_B_ZERO
;
863 if (prf2
->rgPins
[i
].bMany
)
864 flags
|= REG_PINFLAG_B_MANY
;
865 pregfp2
[i
].dwFlags
= flags
;
866 pregfp2
[i
].cInstances
= 1;
867 pregfp2
[i
].nMediaTypes
= prf2
->rgPins
[i
].nMediaTypes
;
868 pregfp2
[i
].lpMediaType
= prf2
->rgPins
[i
].lpMediaType
;
869 pregfp2
[i
].nMediums
= 0;
870 pregfp2
[i
].lpMedium
= NULL
;
871 pregfp2
[i
].clsPinCategory
= NULL
;
876 FIXME("dwVersion other that 1 or 2 not supported at the moment\n");
884 category
= &CLSID_LegacyAmFilterCategory
;
886 StringFromGUID2(clsid
, clsid_string
, ARRAY_SIZE(clsid_string
));
888 len
= 50 + (instance
? wcslen(instance
) : 38) + 1;
889 if (!(display_name
= malloc(len
* sizeof(WCHAR
))))
890 return E_OUTOFMEMORY
;
892 wcscpy(display_name
, L
"@device:sw:");
893 StringFromGUID2(category
, display_name
+ wcslen(display_name
), len
- wcslen(display_name
));
894 wcscat(display_name
, L
"\\");
895 wcscat(display_name
, instance
? instance
: clsid_string
);
897 if (FAILED(hr
= CoCreateInstance(&CLSID_CDeviceMoniker
, NULL
, CLSCTX_INPROC
,
898 &IID_IParseDisplayName
, (void **)&parser
)))
901 if (FAILED(hr
= IParseDisplayName_ParseDisplayName(parser
, NULL
, display_name
, &eaten
, &moniker
)))
903 ERR("Failed to parse display name, hr %#x.\n", hr
);
904 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 %#x.\n", hr
);
913 IMoniker_Release(moniker
);
917 V_VT(&var
) = VT_BSTR
;
918 V_BSTR(&var
) = SysAllocString(name
);
919 if (FAILED(hr
= IPropertyBag_Write(prop_bag
, L
"FriendlyName", &var
)))
920 ERR("Failed to write friendly name, hr %#x.\n", hr
);
923 V_VT(&var
) = VT_BSTR
;
924 V_BSTR(&var
) = SysAllocString(clsid_string
);
925 if (FAILED(hr
= IPropertyBag_Write(prop_bag
, L
"CLSID", &var
)))
926 ERR("Failed to write class ID, hr %#x.\n", hr
);
929 if (SUCCEEDED(FM2_WriteFilterData(®filter2
, &filter_data
, &filter_data_len
)))
931 V_VT(&var
) = VT_ARRAY
| VT_UI1
;
932 if ((V_ARRAY(&var
) = SafeArrayCreateVector(VT_UI1
, 0, filter_data_len
)))
934 memcpy(V_ARRAY(&var
)->pvData
, filter_data
, filter_data_len
);
935 if (FAILED(hr
= IPropertyBag_Write(prop_bag
, L
"FilterData", &var
)))
936 ERR("Failed to write filter data, hr %#x.\n", hr
);
940 CoTaskMemFree(filter_data
);
943 IPropertyBag_Release(prop_bag
);
947 *ret_moniker
= moniker
;
949 IMoniker_Release(moniker
);
951 CoTaskMemFree(pregfp2
);
956 /* internal helper function */
957 static BOOL
MatchTypes(
960 const REGPINTYPES
* pPinTypes
,
962 const GUID
* pMatchTypes
)
967 if ((nMatchTypes
== 0) && (nPinTypes
> 0))
970 for (j
= 0; j
< nPinTypes
; j
++)
973 for (i
= 0; i
< nMatchTypes
*2; i
+=2)
975 if (((!bExactMatch
&& IsEqualGUID(pPinTypes
[j
].clsMajorType
, &GUID_NULL
)) || IsEqualGUID(&pMatchTypes
[i
], &GUID_NULL
) || IsEqualGUID(pPinTypes
[j
].clsMajorType
, &pMatchTypes
[i
])) &&
976 ((!bExactMatch
&& IsEqualGUID(pPinTypes
[j
].clsMinorType
, &GUID_NULL
)) || IsEqualGUID(&pMatchTypes
[i
+1], &GUID_NULL
) || IsEqualGUID(pPinTypes
[j
].clsMinorType
, &pMatchTypes
[i
+1])))
986 /* internal helper function for qsort of MONIKER_MERIT array */
987 static int __cdecl
mm_compare(const void * left
, const void * right
)
989 const struct MONIKER_MERIT
* mmLeft
= left
;
990 const struct MONIKER_MERIT
* mmRight
= right
;
992 if (mmLeft
->dwMerit
== mmRight
->dwMerit
)
994 if (mmLeft
->dwMerit
> mmRight
->dwMerit
)
1000 * Exact match means whether or not to treat GUID_NULL's in filter data as wild cards
1001 * (GUID_NULL's in input to function automatically treated as wild cards)
1002 * Input/Output needed means match only on criteria if TRUE (with zero input types
1003 * meaning match any input/output pin as long as one exists), otherwise match any
1004 * filter that meets the rest of the requirements.
1006 static HRESULT WINAPI
FilterMapper3_EnumMatchingFilters(
1007 IFilterMapper3
* iface
,
1008 IEnumMoniker
**ppEnum
,
1014 const GUID
*pInputTypes
,
1015 const REGPINMEDIUM
*pMedIn
,
1016 const CLSID
*pPinCategoryIn
,
1020 const GUID
*pOutputTypes
,
1021 const REGPINMEDIUM
*pMedOut
,
1022 const CLSID
*pPinCategoryOut
)
1024 ICreateDevEnum
* pCreateDevEnum
;
1025 IMoniker
* pMonikerCat
;
1026 IEnumMoniker
* pEnumCat
;
1028 struct Vector monikers
= {NULL
, 0, 0};
1030 TRACE("(%p, %x, %s, %x, %s, %d, %p, %p, %p, %s, %s, %p, %p, %p)\n",
1033 bExactMatch
? "true" : "false",
1035 bInputNeeded
? "true" : "false",
1040 bRender
? "true" : "false",
1041 bOutputNeeded
? "true" : "false",
1048 FIXME("dwFlags = %x not implemented\n", dwFlags
);
1053 hr
= CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC
, &IID_ICreateDevEnum
, (LPVOID
*)&pCreateDevEnum
);
1057 hr
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &CLSID_ActiveMovieCategories
, &pEnumCat
, 0);
1059 ICreateDevEnum_Release(pCreateDevEnum
);
1063 while (IEnumMoniker_Next(pEnumCat
, 1, &pMonikerCat
, NULL
) == S_OK
)
1065 IPropertyBag
* pPropBagCat
= NULL
;
1067 HRESULT hrSub
; /* this is so that one buggy filter
1068 doesn't make the whole lot fail */
1072 hrSub
= IMoniker_BindToStorage(pMonikerCat
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBagCat
);
1074 if (SUCCEEDED(hrSub
))
1075 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"Merit", &var
, NULL
);
1077 if (SUCCEEDED(hrSub
) && (V_UI4(&var
) >= dwMerit
))
1080 IEnumMoniker
* pEnum
;
1081 IMoniker
* pMoniker
;
1085 if (TRACE_ON(quartz
))
1088 V_VT(&temp
) = VT_EMPTY
;
1089 IPropertyBag_Read(pPropBagCat
, L
"FriendlyName", &temp
, NULL
);
1090 TRACE("Considering category %s\n", debugstr_w(V_BSTR(&temp
)));
1091 VariantClear(&temp
);
1094 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"CLSID", &var
, NULL
);
1096 if (SUCCEEDED(hrSub
))
1097 hrSub
= CLSIDFromString(V_BSTR(&var
), &clsidCat
);
1099 if (SUCCEEDED(hrSub
))
1100 hrSub
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &clsidCat
, &pEnum
, 0);
1104 while (IEnumMoniker_Next(pEnum
, 1, &pMoniker
, NULL
) == S_OK
)
1106 IPropertyBag
* pPropBag
= NULL
;
1111 BOOL bInputMatch
= !bInputNeeded
;
1112 BOOL bOutputMatch
= !bOutputNeeded
;
1114 ZeroMemory(&rf2
, sizeof(rf2
));
1117 hrSub
= IMoniker_BindToStorage(pMoniker
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBag
);
1119 if (TRACE_ON(quartz
))
1122 V_VT(&temp
) = VT_EMPTY
;
1123 IPropertyBag_Read(pPropBag
, L
"FriendlyName", &temp
, NULL
);
1124 TRACE("Considering filter %s\n", debugstr_w(V_BSTR(&temp
)));
1125 VariantClear(&temp
);
1128 if (SUCCEEDED(hrSub
))
1130 hrSub
= IPropertyBag_Read(pPropBag
, L
"FilterData", &var
, NULL
);
1133 if (SUCCEEDED(hrSub
))
1134 hrSub
= SafeArrayAccessData(V_ARRAY(&var
), (LPVOID
*)&pData
);
1136 if (SUCCEEDED(hrSub
))
1137 hrSub
= FM2_ReadFilterData(pData
, &rf2
);
1140 SafeArrayUnaccessData(V_ARRAY(&var
));
1144 /* Logic used for bInputMatch expression:
1145 * There exists some pin such that bInputNeeded implies (pin is an input and
1146 * (bRender implies pin has render flag) and major/minor types members of
1148 * bOutputMatch is similar, but without the "bRender implies ..." part
1149 * and substituting variables names containing input for output
1152 /* determine whether filter meets requirements */
1153 if (SUCCEEDED(hrSub
) && (rf2
.dwMerit
>= dwMerit
))
1155 for (i
= 0; (i
< rf2
.cPins2
) && (!bInputMatch
|| !bOutputMatch
); i
++)
1157 const REGFILTERPINS2
* rfp2
= rf2
.rgPins2
+ i
;
1159 bInputMatch
= bInputMatch
|| (!(rfp2
->dwFlags
& REG_PINFLAG_B_OUTPUT
) &&
1160 (!bRender
|| (rfp2
->dwFlags
& REG_PINFLAG_B_RENDERER
)) &&
1161 MatchTypes(bExactMatch
, rfp2
->nMediaTypes
, rfp2
->lpMediaType
, cInputTypes
, pInputTypes
));
1162 bOutputMatch
= bOutputMatch
|| ((rfp2
->dwFlags
& REG_PINFLAG_B_OUTPUT
) &&
1163 MatchTypes(bExactMatch
, rfp2
->nMediaTypes
, rfp2
->lpMediaType
, cOutputTypes
, pOutputTypes
));
1166 if (bInputMatch
&& bOutputMatch
)
1168 struct MONIKER_MERIT mm
= {pMoniker
, rf2
.dwMerit
};
1169 IMoniker_AddRef(pMoniker
);
1170 add_data(&monikers
, &mm
, sizeof(mm
));
1174 FM2_DeleteRegFilter(&rf2
);
1176 IPropertyBag_Release(pPropBag
);
1177 IMoniker_Release(pMoniker
);
1179 IEnumMoniker_Release(pEnum
);
1185 IPropertyBag_Release(pPropBagCat
);
1186 IMoniker_Release(pMonikerCat
);
1191 IMoniker
** ppMoniker
;
1193 ULONG nMonikerCount
= monikers
.current
/ sizeof(struct MONIKER_MERIT
);
1195 /* sort the monikers in descending merit order */
1196 qsort(monikers
.pData
, nMonikerCount
,
1197 sizeof(struct MONIKER_MERIT
),
1200 /* construct an IEnumMoniker interface */
1201 ppMoniker
= CoTaskMemAlloc(nMonikerCount
* sizeof(IMoniker
*));
1202 for (i
= 0; i
< nMonikerCount
; i
++)
1204 /* no need to AddRef here as already AddRef'd above */
1205 ppMoniker
[i
] = ((struct MONIKER_MERIT
*)monikers
.pData
)[i
].pMoniker
;
1207 hr
= enum_moniker_create(ppMoniker
, nMonikerCount
, ppEnum
);
1208 CoTaskMemFree(ppMoniker
);
1211 delete_vector(&monikers
);
1212 IEnumMoniker_Release(pEnumCat
);
1213 ICreateDevEnum_Release(pCreateDevEnum
);
1218 static HRESULT WINAPI
FilterMapper3_GetICreateDevEnum(IFilterMapper3
*iface
, ICreateDevEnum
**ppEnum
)
1220 TRACE("(%p, %p)\n", iface
, ppEnum
);
1223 return CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC
, &IID_ICreateDevEnum
, (void**)ppEnum
);
1226 static const IFilterMapper3Vtbl fm3vtbl
=
1229 FilterMapper3_QueryInterface
,
1230 FilterMapper3_AddRef
,
1231 FilterMapper3_Release
,
1233 FilterMapper3_CreateCategory
,
1234 FilterMapper3_UnregisterFilter
,
1235 FilterMapper3_RegisterFilter
,
1236 FilterMapper3_EnumMatchingFilters
,
1237 FilterMapper3_GetICreateDevEnum
1240 /*** IUnknown methods ***/
1242 static HRESULT WINAPI
FilterMapper_QueryInterface(IFilterMapper
* iface
, REFIID riid
, LPVOID
*ppv
)
1244 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1246 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
1248 return FilterMapper3_QueryInterface(&This
->IFilterMapper3_iface
, riid
, ppv
);
1251 static ULONG WINAPI
FilterMapper_AddRef(IFilterMapper
* iface
)
1253 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1255 return IUnknown_AddRef(This
->outer_unk
);
1258 static ULONG WINAPI
FilterMapper_Release(IFilterMapper
* iface
)
1260 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1262 return IUnknown_Release(This
->outer_unk
);
1265 /*** IFilterMapper methods ***/
1267 static HRESULT WINAPI
FilterMapper_EnumMatchingFilters(
1268 IFilterMapper
* iface
,
1269 IEnumRegFilters
**ppEnum
,
1279 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1282 IEnumMoniker
* ppEnumMoniker
;
1285 ULONG idx
= 0, nb_mon
= 0;
1286 REGFILTER
* regfilters
;
1289 TRACE("(%p/%p)->(%p, %x, %s, %s, %s, %s, %s, %s, %s)\n",
1294 bInputNeeded
? "true" : "false",
1295 debugstr_guid(&clsInMaj
),
1296 debugstr_guid(&clsInSub
),
1297 bRender
? "true" : "false",
1298 bOutputNeeded
? "true" : "false",
1299 debugstr_guid(&clsOutMaj
),
1300 debugstr_guid(&clsOutSub
));
1302 InputType
[0] = clsInMaj
;
1303 InputType
[1] = clsInSub
;
1304 OutputType
[0] = clsOutMaj
;
1305 OutputType
[1] = clsOutSub
;
1309 hr
= IFilterMapper3_EnumMatchingFilters(&This
->IFilterMapper3_iface
, &ppEnumMoniker
, 0, TRUE
,
1310 dwMerit
, bInputNeeded
, 1, InputType
, NULL
, &GUID_NULL
, bRender
, bOutputNeeded
, 1,
1311 OutputType
, NULL
, &GUID_NULL
);
1316 while(IEnumMoniker_Next(ppEnumMoniker
, 1, &IMon
, &nb
) == S_OK
)
1318 IMoniker_Release(IMon
);
1324 IEnumMoniker_Release(ppEnumMoniker
);
1325 return enum_reg_filters_create(NULL
, 0, ppEnum
);
1328 regfilters
= CoTaskMemAlloc(nb_mon
* sizeof(REGFILTER
));
1331 IEnumMoniker_Release(ppEnumMoniker
);
1332 return E_OUTOFMEMORY
;
1334 ZeroMemory(regfilters
, nb_mon
* sizeof(REGFILTER
)); /* will prevent bad free of Name in case of error. */
1336 IEnumMoniker_Reset(ppEnumMoniker
);
1337 while(IEnumMoniker_Next(ppEnumMoniker
, 1, &IMon
, &nb
) == S_OK
)
1339 IPropertyBag
* pPropBagCat
= NULL
;
1347 hrSub
= IMoniker_BindToStorage(IMon
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBagCat
);
1349 if (SUCCEEDED(hrSub
))
1350 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"CLSID", &var
, NULL
);
1352 if (SUCCEEDED(hrSub
))
1353 hrSub
= CLSIDFromString(V_BSTR(&var
), &clsid
);
1357 if (SUCCEEDED(hrSub
))
1358 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"FriendlyName", &var
, NULL
);
1360 if (SUCCEEDED(hrSub
))
1362 len
= (wcslen(V_BSTR(&var
)) + 1) * sizeof(WCHAR
);
1363 if (!(regfilters
[idx
].Name
= CoTaskMemAlloc(len
*2)))
1367 if (SUCCEEDED(hrSub
) && regfilters
[idx
].Name
)
1369 memcpy(regfilters
[idx
].Name
, V_BSTR(&var
), len
);
1370 regfilters
[idx
].Clsid
= clsid
;
1375 IPropertyBag_Release(pPropBagCat
);
1376 IMoniker_Release(IMon
);
1382 hr
= enum_reg_filters_create(regfilters
, idx
, ppEnum
);
1385 for (idx
= 0; idx
< nb_mon
; idx
++)
1386 CoTaskMemFree(regfilters
[idx
].Name
);
1387 CoTaskMemFree(regfilters
);
1388 IEnumMoniker_Release(ppEnumMoniker
);
1394 static HRESULT WINAPI
FilterMapper_RegisterFilter(IFilterMapper
* iface
,
1395 CLSID clsid
, const WCHAR
*name
, DWORD merit
)
1397 WCHAR keypath
[46], guidstr
[39];
1401 TRACE("iface %p, clsid %s, name %s, merit %#x.\n",
1402 iface
, debugstr_guid(&clsid
), debugstr_w(name
), merit
);
1404 StringFromGUID2(&clsid
, guidstr
, ARRAY_SIZE(guidstr
));
1406 wcscpy(keypath
, L
"Filter\\");
1407 wcscat(keypath
, guidstr
);
1408 if ((ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
)))
1409 return HRESULT_FROM_WIN32(ret
);
1411 if ((ret
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (const BYTE
*)name
, (wcslen(name
) + 1) * sizeof(WCHAR
))))
1412 ERR("Failed to set filter name, error %u.\n", ret
);
1415 wcscpy(keypath
, L
"CLSID\\");
1416 wcscat(keypath
, guidstr
);
1417 if (!(ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
)))
1419 if ((ret
= RegSetValueExW(key
, L
"Merit", 0, REG_DWORD
, (const BYTE
*)&merit
, sizeof(DWORD
))))
1420 ERR("Failed to set merit, error %u.\n", ret
);
1424 ERR("Failed to create CLSID key, error %u.\n", ret
);
1429 static HRESULT WINAPI
FilterMapper_RegisterFilterInstance(IFilterMapper
* iface
, CLSID clsid
, LPCWSTR szName
, CLSID
*MRId
)
1431 TRACE("(%p)->(%s, %s, %p)\n", iface
, debugstr_guid(&clsid
), debugstr_w(szName
), MRId
);
1433 /* Not implemented in Windows (tested on Win2k) */
1438 static HRESULT WINAPI
FilterMapper_RegisterPin(IFilterMapper
*iface
, CLSID clsid
,
1439 const WCHAR
*name
, BOOL rendered
, BOOL output
, BOOL zero
, BOOL many
,
1440 CLSID external_filter
, const WCHAR
*external_pin
)
1442 WCHAR keypath
[6 + 38 + 1], *pin_keypath
;
1443 HKEY key
, pin_key
, type_key
;
1446 TRACE("iface %p, clsid %s, name %s, rendered %d, output %d, zero %d, "
1447 "many %d, external_filter %s, external_pin %s.\n",
1448 iface
, debugstr_guid(&clsid
), debugstr_w(name
), rendered
, output
,
1449 zero
, many
, debugstr_guid(&external_filter
), debugstr_w(external_pin
));
1451 wcscpy(keypath
, L
"CLSID\\");
1452 StringFromGUID2(&clsid
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
1453 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, KEY_WRITE
, &key
)))
1454 return HRESULT_FROM_WIN32(ret
);
1456 if (!(pin_keypath
= malloc((5 + wcslen(name
) + 1) * sizeof(WCHAR
))))
1459 return E_OUTOFMEMORY
;
1461 wcscpy(pin_keypath
, L
"Pins\\");
1462 wcscat(pin_keypath
, name
);
1464 if ((ret
= RegCreateKeyExW(key
, pin_keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &pin_key
, NULL
)))
1466 ERR("Failed to open pin key, error %u.\n", ret
);
1469 return HRESULT_FROM_WIN32(ret
);
1473 if ((ret
= RegSetValueExW(pin_key
, L
"AllowedMany", 0, REG_DWORD
, (const BYTE
*)&many
, sizeof(DWORD
))))
1474 ERR("Failed to set AllowedMany value, error %u.\n", ret
);
1475 if ((ret
= RegSetValueExW(pin_key
, L
"AllowedZero", 0, REG_DWORD
, (const BYTE
*)&zero
, sizeof(DWORD
))))
1476 ERR("Failed to set AllowedZero value, error %u.\n", ret
);
1477 if ((ret
= RegSetValueExW(pin_key
, L
"Direction", 0, REG_DWORD
, (const BYTE
*)&output
, sizeof(DWORD
))))
1478 ERR("Failed to set Direction value, error %u.\n", ret
);
1479 if ((ret
= RegSetValueExW(pin_key
, L
"IsRendered", 0, REG_DWORD
, (const BYTE
*)&rendered
, sizeof(DWORD
))))
1480 ERR("Failed to set IsRendered value, error %u.\n", ret
);
1482 if (!(ret
= RegCreateKeyExW(pin_key
, L
"Types", 0, NULL
, 0, 0, NULL
, &type_key
, NULL
)))
1483 RegCloseKey(type_key
);
1485 ERR("Failed to create Types subkey, error %u.\n", ret
);
1487 RegCloseKey(pin_key
);
1494 static HRESULT WINAPI
FilterMapper_RegisterPinType(IFilterMapper
*iface
,
1495 CLSID clsid
, const WCHAR
*pin
, CLSID majortype
, CLSID subtype
)
1497 WCHAR
*keypath
, type_keypath
[38 + 1 + 38 + 1];
1502 TRACE("iface %p, clsid %s, pin %s, majortype %s, subtype %s.\n", iface
,
1503 debugstr_guid(&clsid
), debugstr_w(pin
), debugstr_guid(&majortype
), debugstr_guid(&subtype
));
1505 len
= 6 + 38 + 6 + wcslen(pin
) + 6 + 1;
1506 if (!(keypath
= malloc(len
* sizeof(WCHAR
))))
1507 return E_OUTOFMEMORY
;
1509 wcscpy(keypath
, L
"CLSID\\");
1510 StringFromGUID2(&clsid
, keypath
+ wcslen(keypath
), len
- wcslen(keypath
));
1511 wcscat(keypath
, L
"\\Pins\\");
1512 wcscat(keypath
, pin
);
1513 wcscat(keypath
, L
"\\Types");
1514 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, KEY_CREATE_SUB_KEY
, &key
)))
1517 return HRESULT_FROM_WIN32(ret
);
1521 StringFromGUID2(&majortype
, type_keypath
, ARRAY_SIZE(type_keypath
));
1522 wcscat(type_keypath
, L
"\\");
1523 StringFromGUID2(&subtype
, type_keypath
+ wcslen(type_keypath
), ARRAY_SIZE(type_keypath
) - wcslen(type_keypath
));
1524 if (!(ret
= RegCreateKeyExW(key
, type_keypath
, 0, NULL
, 0, 0, NULL
, &type_key
, NULL
)))
1525 RegCloseKey(type_key
);
1527 ERR("Failed to create type key, error %u.\n", ret
);
1530 return HRESULT_FROM_WIN32(ret
);
1533 static HRESULT WINAPI
FilterMapper_UnregisterFilter(IFilterMapper
*iface
, CLSID clsid
)
1535 WCHAR guidstr
[39], keypath
[6 + 38 + 1];
1539 TRACE("iface %p, clsid %s.\n", iface
, debugstr_guid(&clsid
));
1541 StringFromGUID2(&clsid
, guidstr
, ARRAY_SIZE(guidstr
));
1543 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"Filter", 0, 0, &key
)))
1544 return HRESULT_FROM_WIN32(ret
);
1545 if ((ret
= RegDeleteKeyW(key
, guidstr
)))
1546 ERR("Failed to delete filter key, error %u.\n", ret
);
1549 wcscpy(keypath
, L
"CLSID\\");
1550 wcscat(keypath
, guidstr
);
1551 if (!(ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, KEY_WRITE
, &key
)))
1553 if ((ret
= RegDeleteValueW(key
, L
"Merit")))
1554 ERR("Failed to delete Merit value, error %u.\n", ret
);
1555 if ((ret
= RegDeleteTreeW(key
, L
"Pins")))
1556 ERR("Failed to delete Pins key, error %u.\n", ret
);
1560 ERR("Failed to open CLSID key, error %u.\n", ret
);
1565 static HRESULT WINAPI
FilterMapper_UnregisterFilterInstance(IFilterMapper
* iface
, CLSID MRId
)
1567 TRACE("(%p)->(%s)\n", iface
, debugstr_guid(&MRId
));
1569 /* Not implemented in Windows (tested on Win2k) */
1574 static HRESULT WINAPI
FilterMapper_UnregisterPin(IFilterMapper
* iface
, CLSID clsid
, const WCHAR
*name
)
1576 WCHAR keypath
[6 + 38 + 5 + 1];
1580 TRACE("iface %p, clsid %s, name %s.\n", iface
, debugstr_guid(&clsid
), debugstr_w(name
));
1583 return E_INVALIDARG
;
1585 wcscpy(keypath
, L
"CLSID\\");
1586 StringFromGUID2(&clsid
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
1587 wcscat(keypath
, L
"\\Pins");
1588 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, 0, &key
)))
1589 return HRESULT_FROM_WIN32(ret
);
1591 if ((ret
= RegDeleteTreeW(key
, name
)))
1592 ERR("Failed to delete subkey, error %u.\n", ret
);
1599 static const IFilterMapperVtbl fmvtbl
=
1602 FilterMapper_QueryInterface
,
1603 FilterMapper_AddRef
,
1604 FilterMapper_Release
,
1606 FilterMapper_RegisterFilter
,
1607 FilterMapper_RegisterFilterInstance
,
1608 FilterMapper_RegisterPin
,
1609 FilterMapper_RegisterPinType
,
1610 FilterMapper_UnregisterFilter
,
1611 FilterMapper_UnregisterFilterInstance
,
1612 FilterMapper_UnregisterPin
,
1613 FilterMapper_EnumMatchingFilters
1617 /*** IUnknown methods ***/
1618 static HRESULT WINAPI
AMFilterData_QueryInterface(IAMFilterData
* iface
, REFIID riid
, LPVOID
*ppv
)
1620 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1622 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
1625 static ULONG WINAPI
AMFilterData_AddRef(IAMFilterData
* iface
)
1627 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1629 return IUnknown_AddRef(This
->outer_unk
);
1632 static ULONG WINAPI
AMFilterData_Release(IAMFilterData
* iface
)
1634 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1636 return IUnknown_Release(This
->outer_unk
);
1639 /*** IAMFilterData methods ***/
1640 static HRESULT WINAPI
AMFilterData_ParseFilterData(IAMFilterData
* iface
,
1641 BYTE
*pData
, ULONG cb
,
1642 BYTE
**ppRegFilter2
)
1644 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1646 static REGFILTER2
*prf2
;
1648 TRACE("(%p/%p)->(%p, %d, %p)\n", This
, iface
, pData
, cb
, ppRegFilter2
);
1650 prf2
= CoTaskMemAlloc(sizeof(*prf2
));
1652 return E_OUTOFMEMORY
;
1653 *ppRegFilter2
= (BYTE
*)&prf2
;
1655 hr
= FM2_ReadFilterData(pData
, prf2
);
1658 CoTaskMemFree(prf2
);
1659 *ppRegFilter2
= NULL
;
1665 static HRESULT WINAPI
AMFilterData_CreateFilterData(IAMFilterData
* iface
,
1667 BYTE
**pRegFilterData
,
1670 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1672 TRACE("(%p/%p)->(%p, %p, %p)\n", This
, iface
, prf2
, pRegFilterData
, pcb
);
1674 return FM2_WriteFilterData(prf2
, pRegFilterData
, pcb
);
1677 static const IAMFilterDataVtbl AMFilterDataVtbl
= {
1678 AMFilterData_QueryInterface
,
1679 AMFilterData_AddRef
,
1680 AMFilterData_Release
,
1681 AMFilterData_ParseFilterData
,
1682 AMFilterData_CreateFilterData
1685 HRESULT
filter_mapper_create(IUnknown
*pUnkOuter
, IUnknown
**out
)
1687 FilterMapper3Impl
* pFM2impl
;
1689 pFM2impl
= CoTaskMemAlloc(sizeof(*pFM2impl
));
1691 return E_OUTOFMEMORY
;
1693 pFM2impl
->IUnknown_inner
.lpVtbl
= &IInner_VTable
;
1694 pFM2impl
->IFilterMapper3_iface
.lpVtbl
= &fm3vtbl
;
1695 pFM2impl
->IFilterMapper_iface
.lpVtbl
= &fmvtbl
;
1696 pFM2impl
->IAMFilterData_iface
.lpVtbl
= &AMFilterDataVtbl
;
1700 pFM2impl
->outer_unk
= pUnkOuter
;
1702 pFM2impl
->outer_unk
= &pFM2impl
->IUnknown_inner
;
1704 TRACE("Created filter mapper %p.\n", pFM2impl
);
1705 *out
= &pFM2impl
->IUnknown_inner
;