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 %lu.\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 %lu.\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 %lu, 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 %lu, 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 %lu.\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 %lu.\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 %lu, 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 %lu.\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
*mapper
= impl_from_IUnknown(iface
);
473 ULONG refcount
= InterlockedIncrement(&mapper
->ref
);
475 TRACE("%p increasing refcount to %lu.\n", mapper
, refcount
);
480 static ULONG WINAPI
Inner_Release(IUnknown
*iface
)
482 FilterMapper3Impl
*mapper
= impl_from_IUnknown(iface
);
483 ULONG refcount
= InterlockedDecrement(&mapper
->ref
);
485 TRACE("%p decreasing refcount to %lu.\n", mapper
, refcount
);
489 CoTaskMemFree(mapper
);
495 static const IUnknownVtbl IInner_VTable
=
497 Inner_QueryInterface
,
502 static HRESULT WINAPI
FilterMapper3_QueryInterface(IFilterMapper3
* iface
, REFIID riid
, LPVOID
*ppv
)
504 FilterMapper3Impl
*This
= impl_from_IFilterMapper3(iface
);
506 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
509 static ULONG WINAPI
FilterMapper3_AddRef(IFilterMapper3
* iface
)
511 FilterMapper3Impl
*This
= impl_from_IFilterMapper3(iface
);
513 return IUnknown_AddRef(This
->outer_unk
);
516 static ULONG WINAPI
FilterMapper3_Release(IFilterMapper3
* iface
)
518 FilterMapper3Impl
*This
= impl_from_IFilterMapper3(iface
);
520 return IUnknown_Release(This
->outer_unk
);
523 /*** IFilterMapper3 methods ***/
525 static HRESULT WINAPI
FilterMapper3_CreateCategory(IFilterMapper3
*iface
,
526 REFCLSID category
, DWORD merit
, const WCHAR
*description
)
528 WCHAR guidstr
[39], keypath
[93];
532 TRACE("iface %p, category %s, merit %#lx, description %s.\n", iface
,
533 debugstr_guid(category
), merit
, debugstr_w(description
));
535 StringFromGUID2(category
, guidstr
, ARRAY_SIZE(guidstr
));
536 wcscpy(keypath
, L
"CLSID\\{da4e3da0-d07d-11d0-bd50-00a0c911ce86}\\Instance\\");
537 wcscat(keypath
, guidstr
);
539 if ((ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
)))
540 return HRESULT_FROM_WIN32(ret
);
542 if ((ret
= RegSetValueExW(key
, L
"FriendlyName", 0, REG_SZ
,
543 (const BYTE
*)description
, (wcslen(description
) + 1) * sizeof(WCHAR
))))
546 return HRESULT_FROM_WIN32(ret
);
549 if ((ret
= RegSetValueExW(key
, L
"CLSID", 0, REG_SZ
, (const BYTE
*)guidstr
, sizeof(guidstr
))))
552 return HRESULT_FROM_WIN32(ret
);
555 if ((ret
= RegSetValueExW(key
, L
"Merit", 0, REG_DWORD
, (const BYTE
*)&merit
, sizeof(DWORD
))))
558 return HRESULT_FROM_WIN32(ret
);
565 static HRESULT WINAPI
FilterMapper3_UnregisterFilter(IFilterMapper3
*iface
,
566 const CLSID
*category
, const WCHAR
*instance
, REFCLSID clsid
)
570 TRACE("iface %p, category %s, instance %s, clsid %s.\n",
571 iface
, debugstr_guid(category
), debugstr_w(instance
), debugstr_guid(clsid
));
574 category
= &CLSID_LegacyAmFilterCategory
;
576 wcscpy(keypath
, L
"CLSID\\");
577 StringFromGUID2(category
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
578 wcscat(keypath
, L
"\\Instance\\");
580 wcscat(keypath
, instance
);
582 StringFromGUID2(clsid
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
584 return HRESULT_FROM_WIN32(RegDeleteKeyW(HKEY_CLASSES_ROOT
, keypath
));
587 static HRESULT
FM2_WriteFilterData(const REGFILTER2
* prf2
, BYTE
**ppData
, ULONG
*pcbData
)
589 int size
= sizeof(struct REG_RF
);
591 struct Vector mainStore
= {NULL
, 0, 0};
592 struct Vector clsidStore
= {NULL
, 0, 0};
596 rrf
.dwVersion
= prf2
->dwVersion
;
597 rrf
.dwMerit
= prf2
->dwMerit
;
598 rrf
.dwPins
= prf2
->cPins2
;
601 add_data(&mainStore
, &rrf
, sizeof(rrf
));
603 for (i
= 0; i
< prf2
->cPins2
; i
++)
605 size
+= sizeof(struct REG_RFP
);
606 if (prf2
->rgPins2
[i
].clsPinCategory
)
607 size
+= sizeof(DWORD
);
608 size
+= prf2
->rgPins2
[i
].nMediaTypes
* sizeof(struct REG_TYPE
);
609 size
+= prf2
->rgPins2
[i
].nMediums
* sizeof(DWORD
);
612 for (i
= 0; i
< prf2
->cPins2
; i
++)
615 REGFILTERPINS2 rgPin2
= prf2
->rgPins2
[i
];
618 rrfp
.signature
[0] = '0';
619 rrfp
.signature
[1] = 'p';
620 rrfp
.signature
[2] = 'i';
621 rrfp
.signature
[3] = '3';
622 rrfp
.signature
[0] += i
;
623 rrfp
.dwFlags
= rgPin2
.dwFlags
;
624 rrfp
.dwInstances
= rgPin2
.cInstances
;
625 rrfp
.dwMediaTypes
= rgPin2
.nMediaTypes
;
626 rrfp
.dwMediums
= rgPin2
.nMediums
;
627 rrfp
.bCategory
= rgPin2
.clsPinCategory
? 1 : 0;
629 add_data(&mainStore
, &rrfp
, sizeof(rrfp
));
632 DWORD index
= find_data(&clsidStore
, rgPin2
.clsPinCategory
, sizeof(CLSID
));
634 index
= add_data(&clsidStore
, rgPin2
.clsPinCategory
, sizeof(CLSID
));
637 add_data(&mainStore
, &index
, sizeof(index
));
640 for (j
= 0; j
< rgPin2
.nMediaTypes
; j
++)
643 const CLSID
* clsMinorType
= rgPin2
.lpMediaType
[j
].clsMinorType
? rgPin2
.lpMediaType
[j
].clsMinorType
: &MEDIASUBTYPE_NULL
;
644 rt
.signature
[0] = '0';
645 rt
.signature
[1] = 't';
646 rt
.signature
[2] = 'y';
647 rt
.signature
[3] = '3';
648 rt
.signature
[0] += j
;
650 rt
.dwOffsetMajor
= find_data(&clsidStore
, rgPin2
.lpMediaType
[j
].clsMajorType
, sizeof(CLSID
));
651 if (rt
.dwOffsetMajor
== -1)
652 rt
.dwOffsetMajor
= add_data(&clsidStore
, rgPin2
.lpMediaType
[j
].clsMajorType
, sizeof(CLSID
));
653 rt
.dwOffsetMajor
+= size
;
654 rt
.dwOffsetMinor
= find_data(&clsidStore
, clsMinorType
, sizeof(CLSID
));
655 if (rt
.dwOffsetMinor
== -1)
656 rt
.dwOffsetMinor
= add_data(&clsidStore
, clsMinorType
, sizeof(CLSID
));
657 rt
.dwOffsetMinor
+= size
;
659 add_data(&mainStore
, &rt
, sizeof(rt
));
662 for (j
= 0; j
< rgPin2
.nMediums
; j
++)
664 DWORD index
= find_data(&clsidStore
, rgPin2
.lpMedium
+ j
, sizeof(REGPINMEDIUM
));
666 index
= add_data(&clsidStore
, rgPin2
.lpMedium
+ j
, sizeof(REGPINMEDIUM
));
669 add_data(&mainStore
, &index
, sizeof(index
));
675 *pcbData
= mainStore
.current
+ clsidStore
.current
;
676 *ppData
= CoTaskMemAlloc(*pcbData
);
683 memcpy(*ppData
, mainStore
.pData
, mainStore
.current
);
684 memcpy((*ppData
) + mainStore
.current
, clsidStore
.pData
, clsidStore
.current
);
687 delete_vector(&mainStore
);
688 delete_vector(&clsidStore
);
692 static HRESULT
FM2_ReadFilterData(BYTE
*pData
, REGFILTER2
* prf2
)
695 struct REG_RF
* prrf
;
698 REGFILTERPINS2
* rgPins2
;
700 prrf
= (struct REG_RF
*)pData
;
703 if (prrf
->dwVersion
!= 2)
705 FIXME("Filter registry version %lu is not supported.\n", prrf
->dwVersion
);
706 ZeroMemory(prf2
, sizeof(*prf2
));
712 TRACE("dwVersion %lu, dwMerit %#lx, dwPins %lu, dwUnused %#lx.\n",
713 prrf
->dwVersion
, prrf
->dwMerit
, prrf
->dwPins
, prrf
->dwUnused
);
715 prf2
->dwVersion
= prrf
->dwVersion
;
716 prf2
->dwMerit
= prrf
->dwMerit
;
717 prf2
->cPins2
= prrf
->dwPins
;
718 rgPins2
= CoTaskMemAlloc(prrf
->dwPins
* sizeof(*rgPins2
));
719 prf2
->rgPins2
= rgPins2
;
720 pCurrent
+= sizeof(struct REG_RF
);
722 for (i
= 0; i
< prrf
->dwPins
; i
++)
724 struct REG_RFP
* prrfp
= (struct REG_RFP
*)pCurrent
;
725 REGPINTYPES
* lpMediaType
;
726 REGPINMEDIUM
* lpMedium
;
729 /* FIXME: check signature */
731 TRACE("\tsignature = %s\n", debugstr_an((const char*)prrfp
->signature
, 4));
733 TRACE("\tPin %lu: dwFlags %#lx, dwInstances %lu, dwMediaTypes %lu, dwMediums %lu.\n",
734 i
, prrfp
->dwFlags
, prrfp
->dwInstances
, prrfp
->dwMediaTypes
, prrfp
->dwMediums
);
736 rgPins2
[i
].dwFlags
= prrfp
->dwFlags
;
737 rgPins2
[i
].cInstances
= prrfp
->dwInstances
;
738 rgPins2
[i
].nMediaTypes
= prrfp
->dwMediaTypes
;
739 rgPins2
[i
].nMediums
= prrfp
->dwMediums
;
740 pCurrent
+= sizeof(struct REG_RFP
);
741 if (prrfp
->bCategory
)
743 CLSID
* clsCat
= CoTaskMemAlloc(sizeof(CLSID
));
744 memcpy(clsCat
, pData
+ *(DWORD
*)(pCurrent
), sizeof(CLSID
));
745 pCurrent
+= sizeof(DWORD
);
746 rgPins2
[i
].clsPinCategory
= clsCat
;
749 rgPins2
[i
].clsPinCategory
= NULL
;
751 if (rgPins2
[i
].nMediaTypes
> 0)
752 lpMediaType
= CoTaskMemAlloc(rgPins2
[i
].nMediaTypes
* sizeof(*lpMediaType
));
756 rgPins2
[i
].lpMediaType
= lpMediaType
;
758 for (j
= 0; j
< rgPins2
[i
].nMediaTypes
; j
++)
760 struct REG_TYPE
* prt
= (struct REG_TYPE
*)pCurrent
;
761 CLSID
* clsMajor
= CoTaskMemAlloc(sizeof(CLSID
));
762 CLSID
* clsMinor
= CoTaskMemAlloc(sizeof(CLSID
));
764 /* FIXME: check signature */
765 TRACE("\t\tsignature = %s\n", debugstr_an((const char*)prt
->signature
, 4));
767 memcpy(clsMajor
, pData
+ prt
->dwOffsetMajor
, sizeof(CLSID
));
768 memcpy(clsMinor
, pData
+ prt
->dwOffsetMinor
, sizeof(CLSID
));
770 lpMediaType
[j
].clsMajorType
= clsMajor
;
771 lpMediaType
[j
].clsMinorType
= clsMinor
;
773 pCurrent
+= sizeof(*prt
);
776 if (rgPins2
[i
].nMediums
> 0)
777 lpMedium
= CoTaskMemAlloc(rgPins2
[i
].nMediums
* sizeof(*lpMedium
));
781 rgPins2
[i
].lpMedium
= lpMedium
;
783 for (j
= 0; j
< rgPins2
[i
].nMediums
; j
++)
785 DWORD dwOffset
= *(DWORD
*)pCurrent
;
787 memcpy(lpMedium
+ j
, pData
+ dwOffset
, sizeof(REGPINMEDIUM
));
789 pCurrent
+= sizeof(dwOffset
);
798 static void FM2_DeleteRegFilter(REGFILTER2
* prf2
)
801 for (i
= 0; i
< prf2
->cPins2
; i
++)
804 CoTaskMemFree((void*)prf2
->rgPins2
[i
].clsPinCategory
);
806 for (j
= 0; j
< prf2
->rgPins2
[i
].nMediaTypes
; j
++)
808 CoTaskMemFree((LPVOID
)prf2
->rgPins2
[i
].lpMediaType
[j
].clsMajorType
);
809 CoTaskMemFree((LPVOID
)prf2
->rgPins2
[i
].lpMediaType
[j
].clsMinorType
);
811 CoTaskMemFree((LPVOID
)prf2
->rgPins2
[i
].lpMediaType
);
812 CoTaskMemFree((LPVOID
)prf2
->rgPins2
[i
].lpMedium
);
814 CoTaskMemFree((LPVOID
)prf2
->rgPins2
);
817 static HRESULT WINAPI
FilterMapper3_RegisterFilter(IFilterMapper3
*iface
,
818 REFCLSID clsid
, const WCHAR
*name
, IMoniker
**ret_moniker
,
819 const CLSID
*category
, const WCHAR
*instance
, const REGFILTER2
*prf2
)
821 WCHAR
*display_name
, clsid_string
[39];
822 IParseDisplayName
*parser
;
823 IPropertyBag
*prop_bag
;
824 ULONG filter_data_len
;
831 REGFILTER2 regfilter2
;
832 REGFILTERPINS2
* pregfp2
= NULL
;
834 TRACE("iface %p, clsid %s, name %s, ret_moniker %p, category %s, instance %s, prf2 %p.\n",
835 iface
, debugstr_guid(clsid
), debugstr_w(name
), ret_moniker
,
836 debugstr_guid(category
), debugstr_w(instance
), prf2
);
838 if (prf2
->dwVersion
== 2)
842 else if (prf2
->dwVersion
== 1)
846 /* REGFILTER2 structure is converted from version 1 to 2. Tested on Win2k. */
847 regfilter2
.dwVersion
= 2;
848 regfilter2
.dwMerit
= prf2
->dwMerit
;
849 regfilter2
.cPins2
= prf2
->cPins
;
850 pregfp2
= CoTaskMemAlloc(prf2
->cPins
* sizeof(REGFILTERPINS2
));
851 regfilter2
.rgPins2
= pregfp2
;
852 for (i
= 0; i
< prf2
->cPins
; i
++)
855 if (prf2
->rgPins
[i
].bRendered
)
856 flags
|= REG_PINFLAG_B_RENDERER
;
857 if (prf2
->rgPins
[i
].bOutput
)
858 flags
|= REG_PINFLAG_B_OUTPUT
;
859 if (prf2
->rgPins
[i
].bZero
)
860 flags
|= REG_PINFLAG_B_ZERO
;
861 if (prf2
->rgPins
[i
].bMany
)
862 flags
|= REG_PINFLAG_B_MANY
;
863 pregfp2
[i
].dwFlags
= flags
;
864 pregfp2
[i
].cInstances
= 1;
865 pregfp2
[i
].nMediaTypes
= prf2
->rgPins
[i
].nMediaTypes
;
866 pregfp2
[i
].lpMediaType
= prf2
->rgPins
[i
].lpMediaType
;
867 pregfp2
[i
].nMediums
= 0;
868 pregfp2
[i
].lpMedium
= NULL
;
869 pregfp2
[i
].clsPinCategory
= NULL
;
874 FIXME("dwVersion other that 1 or 2 not supported at the moment\n");
882 category
= &CLSID_LegacyAmFilterCategory
;
884 StringFromGUID2(clsid
, clsid_string
, ARRAY_SIZE(clsid_string
));
886 len
= 50 + (instance
? wcslen(instance
) : 38) + 1;
887 if (!(display_name
= malloc(len
* sizeof(WCHAR
))))
888 return E_OUTOFMEMORY
;
890 wcscpy(display_name
, L
"@device:sw:");
891 StringFromGUID2(category
, display_name
+ wcslen(display_name
), len
- wcslen(display_name
));
892 wcscat(display_name
, L
"\\");
893 wcscat(display_name
, instance
? instance
: clsid_string
);
895 if (FAILED(hr
= CoCreateInstance(&CLSID_CDeviceMoniker
, NULL
, CLSCTX_INPROC
,
896 &IID_IParseDisplayName
, (void **)&parser
)))
902 if (FAILED(hr
= IParseDisplayName_ParseDisplayName(parser
, NULL
, display_name
, &eaten
, &moniker
)))
904 ERR("Failed to parse display name, hr %#lx.\n", hr
);
905 IParseDisplayName_Release(parser
);
910 IParseDisplayName_Release(parser
);
912 if (FAILED(hr
= IMoniker_BindToStorage(moniker
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
)))
914 ERR("Failed to get property bag, hr %#lx.\n", hr
);
915 IMoniker_Release(moniker
);
920 V_VT(&var
) = VT_BSTR
;
921 V_BSTR(&var
) = SysAllocString(name
);
922 if (FAILED(hr
= IPropertyBag_Write(prop_bag
, L
"FriendlyName", &var
)))
923 ERR("Failed to write friendly name, hr %#lx.\n", hr
);
926 V_VT(&var
) = VT_BSTR
;
927 V_BSTR(&var
) = SysAllocString(clsid_string
);
928 if (FAILED(hr
= IPropertyBag_Write(prop_bag
, L
"CLSID", &var
)))
929 ERR("Failed to write class ID, hr %#lx.\n", hr
);
932 if (SUCCEEDED(FM2_WriteFilterData(®filter2
, &filter_data
, &filter_data_len
)))
934 V_VT(&var
) = VT_ARRAY
| VT_UI1
;
935 if ((V_ARRAY(&var
) = SafeArrayCreateVector(VT_UI1
, 0, filter_data_len
)))
937 memcpy(V_ARRAY(&var
)->pvData
, filter_data
, filter_data_len
);
938 if (FAILED(hr
= IPropertyBag_Write(prop_bag
, L
"FilterData", &var
)))
939 ERR("Failed to write filter data, hr %#lx.\n", hr
);
943 CoTaskMemFree(filter_data
);
946 IPropertyBag_Release(prop_bag
);
950 *ret_moniker
= moniker
;
952 IMoniker_Release(moniker
);
954 CoTaskMemFree(pregfp2
);
959 /* internal helper function */
960 static BOOL
MatchTypes(
963 const REGPINTYPES
* pPinTypes
,
965 const GUID
* pMatchTypes
)
970 if ((nMatchTypes
== 0) && (nPinTypes
> 0))
973 for (j
= 0; j
< nPinTypes
; j
++)
976 for (i
= 0; i
< nMatchTypes
*2; i
+=2)
978 if (((!bExactMatch
&& IsEqualGUID(pPinTypes
[j
].clsMajorType
, &GUID_NULL
)) || IsEqualGUID(&pMatchTypes
[i
], &GUID_NULL
) || IsEqualGUID(pPinTypes
[j
].clsMajorType
, &pMatchTypes
[i
])) &&
979 ((!bExactMatch
&& IsEqualGUID(pPinTypes
[j
].clsMinorType
, &GUID_NULL
)) || IsEqualGUID(&pMatchTypes
[i
+1], &GUID_NULL
) || IsEqualGUID(pPinTypes
[j
].clsMinorType
, &pMatchTypes
[i
+1])))
989 /* internal helper function for qsort of MONIKER_MERIT array */
990 static int __cdecl
mm_compare(const void * left
, const void * right
)
992 const struct MONIKER_MERIT
* mmLeft
= left
;
993 const struct MONIKER_MERIT
* mmRight
= right
;
995 if (mmLeft
->dwMerit
== mmRight
->dwMerit
)
997 if (mmLeft
->dwMerit
> mmRight
->dwMerit
)
1003 * Exact match means whether or not to treat GUID_NULL's in filter data as wild cards
1004 * (GUID_NULL's in input to function automatically treated as wild cards)
1005 * Input/Output needed means match only on criteria if TRUE (with zero input types
1006 * meaning match any input/output pin as long as one exists), otherwise match any
1007 * filter that meets the rest of the requirements.
1009 static HRESULT WINAPI
FilterMapper3_EnumMatchingFilters(
1010 IFilterMapper3
* iface
,
1011 IEnumMoniker
**ppEnum
,
1017 const GUID
*pInputTypes
,
1018 const REGPINMEDIUM
*pMedIn
,
1019 const CLSID
*pPinCategoryIn
,
1023 const GUID
*pOutputTypes
,
1024 const REGPINMEDIUM
*pMedOut
,
1025 const CLSID
*pPinCategoryOut
)
1027 ICreateDevEnum
* pCreateDevEnum
;
1028 IMoniker
* pMonikerCat
;
1029 IEnumMoniker
* pEnumCat
;
1031 struct Vector monikers
= {NULL
, 0, 0};
1033 TRACE("(%p, %#lx, %s, %#lx, %s, %lu, %p, %p, %p, %s, %s, %p, %p, %p)\n",
1036 bExactMatch
? "true" : "false",
1038 bInputNeeded
? "true" : "false",
1043 bRender
? "true" : "false",
1044 bOutputNeeded
? "true" : "false",
1050 FIXME("Ignoring flags %#lx.\n", dwFlags
);
1054 hr
= CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC
, &IID_ICreateDevEnum
, (LPVOID
*)&pCreateDevEnum
);
1058 hr
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &CLSID_ActiveMovieCategories
, &pEnumCat
, 0);
1060 ICreateDevEnum_Release(pCreateDevEnum
);
1064 while (IEnumMoniker_Next(pEnumCat
, 1, &pMonikerCat
, NULL
) == S_OK
)
1066 IPropertyBag
* pPropBagCat
= NULL
;
1068 HRESULT hrSub
; /* this is so that one buggy filter
1069 doesn't make the whole lot fail */
1073 hrSub
= IMoniker_BindToStorage(pMonikerCat
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBagCat
);
1075 if (SUCCEEDED(hrSub
))
1076 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"Merit", &var
, NULL
);
1078 if (SUCCEEDED(hrSub
) && (V_UI4(&var
) >= dwMerit
))
1081 IEnumMoniker
* pEnum
;
1082 IMoniker
* pMoniker
;
1086 if (TRACE_ON(quartz
))
1089 V_VT(&temp
) = VT_EMPTY
;
1090 IPropertyBag_Read(pPropBagCat
, L
"FriendlyName", &temp
, NULL
);
1091 TRACE("Considering category %s\n", debugstr_w(V_BSTR(&temp
)));
1092 VariantClear(&temp
);
1095 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"CLSID", &var
, NULL
);
1097 if (SUCCEEDED(hrSub
))
1098 hrSub
= CLSIDFromString(V_BSTR(&var
), &clsidCat
);
1100 if (SUCCEEDED(hrSub
))
1101 hrSub
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &clsidCat
, &pEnum
, 0);
1105 while (IEnumMoniker_Next(pEnum
, 1, &pMoniker
, NULL
) == S_OK
)
1107 IPropertyBag
* pPropBag
= NULL
;
1112 BOOL bInputMatch
= !bInputNeeded
;
1113 BOOL bOutputMatch
= !bOutputNeeded
;
1115 ZeroMemory(&rf2
, sizeof(rf2
));
1118 hrSub
= IMoniker_BindToStorage(pMoniker
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBag
);
1120 if (TRACE_ON(quartz
))
1123 V_VT(&temp
) = VT_EMPTY
;
1124 IPropertyBag_Read(pPropBag
, L
"FriendlyName", &temp
, NULL
);
1125 TRACE("Considering filter %s\n", debugstr_w(V_BSTR(&temp
)));
1126 VariantClear(&temp
);
1129 if (SUCCEEDED(hrSub
))
1131 hrSub
= IPropertyBag_Read(pPropBag
, L
"FilterData", &var
, NULL
);
1134 if (SUCCEEDED(hrSub
))
1135 hrSub
= SafeArrayAccessData(V_ARRAY(&var
), (LPVOID
*)&pData
);
1137 if (SUCCEEDED(hrSub
))
1138 hrSub
= FM2_ReadFilterData(pData
, &rf2
);
1141 SafeArrayUnaccessData(V_ARRAY(&var
));
1145 /* Logic used for bInputMatch expression:
1146 * There exists some pin such that bInputNeeded implies (pin is an input and
1147 * (bRender implies pin has render flag) and major/minor types members of
1149 * bOutputMatch is similar, but without the "bRender implies ..." part
1150 * and substituting variables names containing input for output
1153 /* determine whether filter meets requirements */
1154 if (SUCCEEDED(hrSub
) && (rf2
.dwMerit
>= dwMerit
))
1156 for (i
= 0; (i
< rf2
.cPins2
) && (!bInputMatch
|| !bOutputMatch
); i
++)
1158 const REGFILTERPINS2
* rfp2
= rf2
.rgPins2
+ i
;
1160 bInputMatch
= bInputMatch
|| (!(rfp2
->dwFlags
& REG_PINFLAG_B_OUTPUT
) &&
1161 (!bRender
|| (rfp2
->dwFlags
& REG_PINFLAG_B_RENDERER
)) &&
1162 MatchTypes(bExactMatch
, rfp2
->nMediaTypes
, rfp2
->lpMediaType
, cInputTypes
, pInputTypes
));
1163 bOutputMatch
= bOutputMatch
|| ((rfp2
->dwFlags
& REG_PINFLAG_B_OUTPUT
) &&
1164 MatchTypes(bExactMatch
, rfp2
->nMediaTypes
, rfp2
->lpMediaType
, cOutputTypes
, pOutputTypes
));
1167 if (bInputMatch
&& bOutputMatch
)
1169 struct MONIKER_MERIT mm
= {pMoniker
, rf2
.dwMerit
};
1170 IMoniker_AddRef(pMoniker
);
1171 add_data(&monikers
, &mm
, sizeof(mm
));
1175 FM2_DeleteRegFilter(&rf2
);
1177 IPropertyBag_Release(pPropBag
);
1178 IMoniker_Release(pMoniker
);
1180 IEnumMoniker_Release(pEnum
);
1186 IPropertyBag_Release(pPropBagCat
);
1187 IMoniker_Release(pMonikerCat
);
1192 IMoniker
** ppMoniker
;
1194 ULONG nMonikerCount
= monikers
.current
/ sizeof(struct MONIKER_MERIT
);
1196 /* sort the monikers in descending merit order */
1197 qsort(monikers
.pData
, nMonikerCount
,
1198 sizeof(struct MONIKER_MERIT
),
1201 /* construct an IEnumMoniker interface */
1202 ppMoniker
= CoTaskMemAlloc(nMonikerCount
* sizeof(IMoniker
*));
1203 for (i
= 0; i
< nMonikerCount
; i
++)
1205 /* no need to AddRef here as already AddRef'd above */
1206 ppMoniker
[i
] = ((struct MONIKER_MERIT
*)monikers
.pData
)[i
].pMoniker
;
1208 hr
= enum_moniker_create(ppMoniker
, nMonikerCount
, ppEnum
);
1209 CoTaskMemFree(ppMoniker
);
1212 delete_vector(&monikers
);
1213 IEnumMoniker_Release(pEnumCat
);
1214 ICreateDevEnum_Release(pCreateDevEnum
);
1219 static HRESULT WINAPI
FilterMapper3_GetICreateDevEnum(IFilterMapper3
*iface
, ICreateDevEnum
**ppEnum
)
1221 TRACE("(%p, %p)\n", iface
, ppEnum
);
1224 return CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC
, &IID_ICreateDevEnum
, (void**)ppEnum
);
1227 static const IFilterMapper3Vtbl fm3vtbl
=
1230 FilterMapper3_QueryInterface
,
1231 FilterMapper3_AddRef
,
1232 FilterMapper3_Release
,
1234 FilterMapper3_CreateCategory
,
1235 FilterMapper3_UnregisterFilter
,
1236 FilterMapper3_RegisterFilter
,
1237 FilterMapper3_EnumMatchingFilters
,
1238 FilterMapper3_GetICreateDevEnum
1241 /*** IUnknown methods ***/
1243 static HRESULT WINAPI
FilterMapper_QueryInterface(IFilterMapper
* iface
, REFIID riid
, LPVOID
*ppv
)
1245 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1247 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
1249 return FilterMapper3_QueryInterface(&This
->IFilterMapper3_iface
, riid
, ppv
);
1252 static ULONG WINAPI
FilterMapper_AddRef(IFilterMapper
* iface
)
1254 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1256 return IUnknown_AddRef(This
->outer_unk
);
1259 static ULONG WINAPI
FilterMapper_Release(IFilterMapper
* iface
)
1261 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1263 return IUnknown_Release(This
->outer_unk
);
1266 /*** IFilterMapper methods ***/
1268 static HRESULT WINAPI
FilterMapper_EnumMatchingFilters(
1269 IFilterMapper
* iface
,
1270 IEnumRegFilters
**ppEnum
,
1280 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1283 IEnumMoniker
* ppEnumMoniker
;
1286 ULONG idx
= 0, nb_mon
= 0;
1287 REGFILTER
* regfilters
;
1290 TRACE("(%p/%p)->(%p, %#lx, %s, %s, %s, %s, %s, %s, %s)\n",
1295 bInputNeeded
? "true" : "false",
1296 debugstr_guid(&clsInMaj
),
1297 debugstr_guid(&clsInSub
),
1298 bRender
? "true" : "false",
1299 bOutputNeeded
? "true" : "false",
1300 debugstr_guid(&clsOutMaj
),
1301 debugstr_guid(&clsOutSub
));
1303 InputType
[0] = clsInMaj
;
1304 InputType
[1] = clsInSub
;
1305 OutputType
[0] = clsOutMaj
;
1306 OutputType
[1] = clsOutSub
;
1310 hr
= IFilterMapper3_EnumMatchingFilters(&This
->IFilterMapper3_iface
, &ppEnumMoniker
, 0, TRUE
,
1311 dwMerit
, bInputNeeded
, 1, InputType
, NULL
, &GUID_NULL
, bRender
, bOutputNeeded
, 1,
1312 OutputType
, NULL
, &GUID_NULL
);
1317 while(IEnumMoniker_Next(ppEnumMoniker
, 1, &IMon
, &nb
) == S_OK
)
1319 IMoniker_Release(IMon
);
1325 IEnumMoniker_Release(ppEnumMoniker
);
1326 return enum_reg_filters_create(NULL
, 0, ppEnum
);
1329 regfilters
= CoTaskMemAlloc(nb_mon
* sizeof(REGFILTER
));
1332 IEnumMoniker_Release(ppEnumMoniker
);
1333 return E_OUTOFMEMORY
;
1335 ZeroMemory(regfilters
, nb_mon
* sizeof(REGFILTER
)); /* will prevent bad free of Name in case of error. */
1337 IEnumMoniker_Reset(ppEnumMoniker
);
1338 while(IEnumMoniker_Next(ppEnumMoniker
, 1, &IMon
, &nb
) == S_OK
)
1340 IPropertyBag
* pPropBagCat
= NULL
;
1348 hrSub
= IMoniker_BindToStorage(IMon
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBagCat
);
1350 if (SUCCEEDED(hrSub
))
1351 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"CLSID", &var
, NULL
);
1353 if (SUCCEEDED(hrSub
))
1354 hrSub
= CLSIDFromString(V_BSTR(&var
), &clsid
);
1358 if (SUCCEEDED(hrSub
))
1359 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"FriendlyName", &var
, NULL
);
1361 if (SUCCEEDED(hrSub
))
1363 len
= (wcslen(V_BSTR(&var
)) + 1) * sizeof(WCHAR
);
1364 if (!(regfilters
[idx
].Name
= CoTaskMemAlloc(len
*2)))
1368 if (SUCCEEDED(hrSub
) && regfilters
[idx
].Name
)
1370 memcpy(regfilters
[idx
].Name
, V_BSTR(&var
), len
);
1371 regfilters
[idx
].Clsid
= clsid
;
1376 IPropertyBag_Release(pPropBagCat
);
1377 IMoniker_Release(IMon
);
1383 hr
= enum_reg_filters_create(regfilters
, idx
, ppEnum
);
1386 for (idx
= 0; idx
< nb_mon
; idx
++)
1387 CoTaskMemFree(regfilters
[idx
].Name
);
1388 CoTaskMemFree(regfilters
);
1389 IEnumMoniker_Release(ppEnumMoniker
);
1395 static HRESULT WINAPI
FilterMapper_RegisterFilter(IFilterMapper
* iface
,
1396 CLSID clsid
, const WCHAR
*name
, DWORD merit
)
1398 WCHAR keypath
[46], guidstr
[39];
1402 TRACE("iface %p, clsid %s, name %s, merit %#lx.\n",
1403 iface
, debugstr_guid(&clsid
), debugstr_w(name
), merit
);
1405 StringFromGUID2(&clsid
, guidstr
, ARRAY_SIZE(guidstr
));
1407 wcscpy(keypath
, L
"Filter\\");
1408 wcscat(keypath
, guidstr
);
1409 if ((ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
)))
1410 return HRESULT_FROM_WIN32(ret
);
1412 if ((ret
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (const BYTE
*)name
, (wcslen(name
) + 1) * sizeof(WCHAR
))))
1413 ERR("Failed to set filter name, error %lu.\n", ret
);
1416 wcscpy(keypath
, L
"CLSID\\");
1417 wcscat(keypath
, guidstr
);
1418 if (!(ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
)))
1420 if ((ret
= RegSetValueExW(key
, L
"Merit", 0, REG_DWORD
, (const BYTE
*)&merit
, sizeof(DWORD
))))
1421 ERR("Failed to set merit, error %lu.\n", ret
);
1425 ERR("Failed to create CLSID key, error %lu.\n", ret
);
1430 static HRESULT WINAPI
FilterMapper_RegisterFilterInstance(IFilterMapper
* iface
, CLSID clsid
, LPCWSTR szName
, CLSID
*MRId
)
1432 TRACE("(%p)->(%s, %s, %p)\n", iface
, debugstr_guid(&clsid
), debugstr_w(szName
), MRId
);
1434 /* Not implemented in Windows (tested on Win2k) */
1439 static HRESULT WINAPI
FilterMapper_RegisterPin(IFilterMapper
*iface
, CLSID clsid
,
1440 const WCHAR
*name
, BOOL rendered
, BOOL output
, BOOL zero
, BOOL many
,
1441 CLSID external_filter
, const WCHAR
*external_pin
)
1443 WCHAR keypath
[6 + 38 + 1], *pin_keypath
;
1444 HKEY key
, pin_key
, type_key
;
1447 TRACE("iface %p, clsid %s, name %s, rendered %d, output %d, zero %d, "
1448 "many %d, external_filter %s, external_pin %s.\n",
1449 iface
, debugstr_guid(&clsid
), debugstr_w(name
), rendered
, output
,
1450 zero
, many
, debugstr_guid(&external_filter
), debugstr_w(external_pin
));
1452 wcscpy(keypath
, L
"CLSID\\");
1453 StringFromGUID2(&clsid
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
1454 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, KEY_WRITE
, &key
)))
1455 return HRESULT_FROM_WIN32(ret
);
1457 if (!(pin_keypath
= malloc((5 + wcslen(name
) + 1) * sizeof(WCHAR
))))
1460 return E_OUTOFMEMORY
;
1462 wcscpy(pin_keypath
, L
"Pins\\");
1463 wcscat(pin_keypath
, name
);
1465 if ((ret
= RegCreateKeyExW(key
, pin_keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &pin_key
, NULL
)))
1467 ERR("Failed to open pin key, error %lu.\n", ret
);
1470 return HRESULT_FROM_WIN32(ret
);
1474 if ((ret
= RegSetValueExW(pin_key
, L
"AllowedMany", 0, REG_DWORD
, (const BYTE
*)&many
, sizeof(DWORD
))))
1475 ERR("Failed to set AllowedMany value, error %lu.\n", ret
);
1476 if ((ret
= RegSetValueExW(pin_key
, L
"AllowedZero", 0, REG_DWORD
, (const BYTE
*)&zero
, sizeof(DWORD
))))
1477 ERR("Failed to set AllowedZero value, error %lu.\n", ret
);
1478 if ((ret
= RegSetValueExW(pin_key
, L
"Direction", 0, REG_DWORD
, (const BYTE
*)&output
, sizeof(DWORD
))))
1479 ERR("Failed to set Direction value, error %lu.\n", ret
);
1480 if ((ret
= RegSetValueExW(pin_key
, L
"IsRendered", 0, REG_DWORD
, (const BYTE
*)&rendered
, sizeof(DWORD
))))
1481 ERR("Failed to set IsRendered value, error %lu.\n", ret
);
1483 if (!(ret
= RegCreateKeyExW(pin_key
, L
"Types", 0, NULL
, 0, 0, NULL
, &type_key
, NULL
)))
1484 RegCloseKey(type_key
);
1486 ERR("Failed to create Types subkey, error %lu.\n", ret
);
1488 RegCloseKey(pin_key
);
1495 static HRESULT WINAPI
FilterMapper_RegisterPinType(IFilterMapper
*iface
,
1496 CLSID clsid
, const WCHAR
*pin
, CLSID majortype
, CLSID subtype
)
1498 WCHAR
*keypath
, type_keypath
[38 + 1 + 38 + 1];
1503 TRACE("iface %p, clsid %s, pin %s, majortype %s, subtype %s.\n", iface
,
1504 debugstr_guid(&clsid
), debugstr_w(pin
), debugstr_guid(&majortype
), debugstr_guid(&subtype
));
1506 len
= 6 + 38 + 6 + wcslen(pin
) + 6 + 1;
1507 if (!(keypath
= malloc(len
* sizeof(WCHAR
))))
1508 return E_OUTOFMEMORY
;
1510 wcscpy(keypath
, L
"CLSID\\");
1511 StringFromGUID2(&clsid
, keypath
+ wcslen(keypath
), len
- wcslen(keypath
));
1512 wcscat(keypath
, L
"\\Pins\\");
1513 wcscat(keypath
, pin
);
1514 wcscat(keypath
, L
"\\Types");
1515 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, KEY_CREATE_SUB_KEY
, &key
)))
1518 return HRESULT_FROM_WIN32(ret
);
1522 StringFromGUID2(&majortype
, type_keypath
, ARRAY_SIZE(type_keypath
));
1523 wcscat(type_keypath
, L
"\\");
1524 StringFromGUID2(&subtype
, type_keypath
+ wcslen(type_keypath
), ARRAY_SIZE(type_keypath
) - wcslen(type_keypath
));
1525 if (!(ret
= RegCreateKeyExW(key
, type_keypath
, 0, NULL
, 0, 0, NULL
, &type_key
, NULL
)))
1526 RegCloseKey(type_key
);
1528 ERR("Failed to create type key, error %lu.\n", ret
);
1531 return HRESULT_FROM_WIN32(ret
);
1534 static HRESULT WINAPI
FilterMapper_UnregisterFilter(IFilterMapper
*iface
, CLSID clsid
)
1536 WCHAR guidstr
[39], keypath
[6 + 38 + 1];
1540 TRACE("iface %p, clsid %s.\n", iface
, debugstr_guid(&clsid
));
1542 StringFromGUID2(&clsid
, guidstr
, ARRAY_SIZE(guidstr
));
1544 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"Filter", 0, 0, &key
)))
1545 return HRESULT_FROM_WIN32(ret
);
1546 if ((ret
= RegDeleteKeyW(key
, guidstr
)))
1547 ERR("Failed to delete filter key, error %lu.\n", ret
);
1550 wcscpy(keypath
, L
"CLSID\\");
1551 wcscat(keypath
, guidstr
);
1552 if (!(ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, KEY_WRITE
, &key
)))
1554 if ((ret
= RegDeleteValueW(key
, L
"Merit")))
1555 ERR("Failed to delete Merit value, error %lu.\n", ret
);
1556 if ((ret
= RegDeleteTreeW(key
, L
"Pins")))
1557 ERR("Failed to delete Pins key, error %lu.\n", ret
);
1561 ERR("Failed to open CLSID key, error %lu.\n", ret
);
1566 static HRESULT WINAPI
FilterMapper_UnregisterFilterInstance(IFilterMapper
* iface
, CLSID MRId
)
1568 TRACE("(%p)->(%s)\n", iface
, debugstr_guid(&MRId
));
1570 /* Not implemented in Windows (tested on Win2k) */
1575 static HRESULT WINAPI
FilterMapper_UnregisterPin(IFilterMapper
* iface
, CLSID clsid
, const WCHAR
*name
)
1577 WCHAR keypath
[6 + 38 + 5 + 1];
1581 TRACE("iface %p, clsid %s, name %s.\n", iface
, debugstr_guid(&clsid
), debugstr_w(name
));
1584 return E_INVALIDARG
;
1586 wcscpy(keypath
, L
"CLSID\\");
1587 StringFromGUID2(&clsid
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
1588 wcscat(keypath
, L
"\\Pins");
1589 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, 0, &key
)))
1590 return HRESULT_FROM_WIN32(ret
);
1592 if ((ret
= RegDeleteTreeW(key
, name
)))
1593 ERR("Failed to delete subkey, error %lu.\n", ret
);
1600 static const IFilterMapperVtbl fmvtbl
=
1603 FilterMapper_QueryInterface
,
1604 FilterMapper_AddRef
,
1605 FilterMapper_Release
,
1607 FilterMapper_RegisterFilter
,
1608 FilterMapper_RegisterFilterInstance
,
1609 FilterMapper_RegisterPin
,
1610 FilterMapper_RegisterPinType
,
1611 FilterMapper_UnregisterFilter
,
1612 FilterMapper_UnregisterFilterInstance
,
1613 FilterMapper_UnregisterPin
,
1614 FilterMapper_EnumMatchingFilters
1618 /*** IUnknown methods ***/
1619 static HRESULT WINAPI
AMFilterData_QueryInterface(IAMFilterData
* iface
, REFIID riid
, LPVOID
*ppv
)
1621 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1623 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
1626 static ULONG WINAPI
AMFilterData_AddRef(IAMFilterData
* iface
)
1628 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1630 return IUnknown_AddRef(This
->outer_unk
);
1633 static ULONG WINAPI
AMFilterData_Release(IAMFilterData
* iface
)
1635 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1637 return IUnknown_Release(This
->outer_unk
);
1640 /*** IAMFilterData methods ***/
1641 static HRESULT WINAPI
AMFilterData_ParseFilterData(IAMFilterData
* iface
,
1642 BYTE
*pData
, ULONG cb
,
1643 BYTE
**ppRegFilter2
)
1645 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1647 static REGFILTER2
*prf2
;
1649 TRACE("mapper %p, data %p, size %lu, parsed_data %p.\n", This
, pData
, cb
, ppRegFilter2
);
1651 prf2
= CoTaskMemAlloc(sizeof(*prf2
));
1653 return E_OUTOFMEMORY
;
1654 *ppRegFilter2
= (BYTE
*)&prf2
;
1656 hr
= FM2_ReadFilterData(pData
, prf2
);
1659 CoTaskMemFree(prf2
);
1660 *ppRegFilter2
= NULL
;
1666 static HRESULT WINAPI
AMFilterData_CreateFilterData(IAMFilterData
* iface
,
1668 BYTE
**pRegFilterData
,
1671 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1673 TRACE("(%p/%p)->(%p, %p, %p)\n", This
, iface
, prf2
, pRegFilterData
, pcb
);
1675 return FM2_WriteFilterData(prf2
, pRegFilterData
, pcb
);
1678 static const IAMFilterDataVtbl AMFilterDataVtbl
= {
1679 AMFilterData_QueryInterface
,
1680 AMFilterData_AddRef
,
1681 AMFilterData_Release
,
1682 AMFilterData_ParseFilterData
,
1683 AMFilterData_CreateFilterData
1686 HRESULT
filter_mapper_create(IUnknown
*pUnkOuter
, IUnknown
**out
)
1688 FilterMapper3Impl
* pFM2impl
;
1690 pFM2impl
= CoTaskMemAlloc(sizeof(*pFM2impl
));
1692 return E_OUTOFMEMORY
;
1694 pFM2impl
->IUnknown_inner
.lpVtbl
= &IInner_VTable
;
1695 pFM2impl
->IFilterMapper3_iface
.lpVtbl
= &fm3vtbl
;
1696 pFM2impl
->IFilterMapper_iface
.lpVtbl
= &fmvtbl
;
1697 pFM2impl
->IAMFilterData_iface
.lpVtbl
= &AMFilterDataVtbl
;
1701 pFM2impl
->outer_unk
= pUnkOuter
;
1703 pFM2impl
->outer_unk
= &pFM2impl
->IUnknown_inner
;
1705 TRACE("Created filter mapper %p.\n", pFM2impl
);
1706 *out
= &pFM2impl
->IUnknown_inner
;