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
);
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 %#x, 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 %d not supported\n", prrf
->dwVersion
);
706 ZeroMemory(prf2
, sizeof(*prf2
));
712 TRACE("version = %d, merit = %x, #pins = %d, unused = %x\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[%d]: flags = %x, instances = %d, media types = %d, mediums = %d\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
)))
899 if (FAILED(hr
= IParseDisplayName_ParseDisplayName(parser
, NULL
, display_name
, &eaten
, &moniker
)))
901 ERR("Failed to parse display name, hr %#x.\n", hr
);
902 IParseDisplayName_Release(parser
);
906 IParseDisplayName_Release(parser
);
908 if (FAILED(hr
= IMoniker_BindToStorage(moniker
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
)))
910 ERR("Failed to get property bag, hr %#x.\n", hr
);
911 IMoniker_Release(moniker
);
915 V_VT(&var
) = VT_BSTR
;
916 V_BSTR(&var
) = SysAllocString(name
);
917 if (FAILED(hr
= IPropertyBag_Write(prop_bag
, L
"FriendlyName", &var
)))
918 ERR("Failed to write friendly name, hr %#x.\n", hr
);
921 V_VT(&var
) = VT_BSTR
;
922 V_BSTR(&var
) = SysAllocString(clsid_string
);
923 if (FAILED(hr
= IPropertyBag_Write(prop_bag
, L
"CLSID", &var
)))
924 ERR("Failed to write class ID, hr %#x.\n", hr
);
927 if (SUCCEEDED(FM2_WriteFilterData(®filter2
, &filter_data
, &filter_data_len
)))
929 V_VT(&var
) = VT_ARRAY
| VT_UI1
;
930 if ((V_ARRAY(&var
) = SafeArrayCreateVector(VT_UI1
, 0, filter_data_len
)))
932 memcpy(V_ARRAY(&var
)->pvData
, filter_data
, filter_data_len
);
933 if (FAILED(hr
= IPropertyBag_Write(prop_bag
, L
"FilterData", &var
)))
934 ERR("Failed to write filter data, hr %#x.\n", hr
);
938 CoTaskMemFree(filter_data
);
941 IPropertyBag_Release(prop_bag
);
945 *ret_moniker
= moniker
;
947 IMoniker_Release(moniker
);
949 CoTaskMemFree(pregfp2
);
954 /* internal helper function */
955 static BOOL
MatchTypes(
958 const REGPINTYPES
* pPinTypes
,
960 const GUID
* pMatchTypes
)
965 if ((nMatchTypes
== 0) && (nPinTypes
> 0))
968 for (j
= 0; j
< nPinTypes
; j
++)
971 for (i
= 0; i
< nMatchTypes
*2; i
+=2)
973 if (((!bExactMatch
&& IsEqualGUID(pPinTypes
[j
].clsMajorType
, &GUID_NULL
)) || IsEqualGUID(&pMatchTypes
[i
], &GUID_NULL
) || IsEqualGUID(pPinTypes
[j
].clsMajorType
, &pMatchTypes
[i
])) &&
974 ((!bExactMatch
&& IsEqualGUID(pPinTypes
[j
].clsMinorType
, &GUID_NULL
)) || IsEqualGUID(&pMatchTypes
[i
+1], &GUID_NULL
) || IsEqualGUID(pPinTypes
[j
].clsMinorType
, &pMatchTypes
[i
+1])))
984 /* internal helper function for qsort of MONIKER_MERIT array */
985 static int __cdecl
mm_compare(const void * left
, const void * right
)
987 const struct MONIKER_MERIT
* mmLeft
= left
;
988 const struct MONIKER_MERIT
* mmRight
= right
;
990 if (mmLeft
->dwMerit
== mmRight
->dwMerit
)
992 if (mmLeft
->dwMerit
> mmRight
->dwMerit
)
998 * Exact match means whether or not to treat GUID_NULL's in filter data as wild cards
999 * (GUID_NULL's in input to function automatically treated as wild cards)
1000 * Input/Output needed means match only on criteria if TRUE (with zero input types
1001 * meaning match any input/output pin as long as one exists), otherwise match any
1002 * filter that meets the rest of the requirements.
1004 static HRESULT WINAPI
FilterMapper3_EnumMatchingFilters(
1005 IFilterMapper3
* iface
,
1006 IEnumMoniker
**ppEnum
,
1012 const GUID
*pInputTypes
,
1013 const REGPINMEDIUM
*pMedIn
,
1014 const CLSID
*pPinCategoryIn
,
1018 const GUID
*pOutputTypes
,
1019 const REGPINMEDIUM
*pMedOut
,
1020 const CLSID
*pPinCategoryOut
)
1022 ICreateDevEnum
* pCreateDevEnum
;
1023 IMoniker
* pMonikerCat
;
1024 IEnumMoniker
* pEnumCat
;
1026 struct Vector monikers
= {NULL
, 0, 0};
1028 TRACE("(%p, %x, %s, %x, %s, %d, %p, %p, %p, %s, %s, %p, %p, %p)\n",
1031 bExactMatch
? "true" : "false",
1033 bInputNeeded
? "true" : "false",
1038 bRender
? "true" : "false",
1039 bOutputNeeded
? "true" : "false",
1046 FIXME("dwFlags = %x not implemented\n", dwFlags
);
1051 hr
= CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC
, &IID_ICreateDevEnum
, (LPVOID
*)&pCreateDevEnum
);
1055 hr
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &CLSID_ActiveMovieCategories
, &pEnumCat
, 0);
1057 ICreateDevEnum_Release(pCreateDevEnum
);
1061 while (IEnumMoniker_Next(pEnumCat
, 1, &pMonikerCat
, NULL
) == S_OK
)
1063 IPropertyBag
* pPropBagCat
= NULL
;
1065 HRESULT hrSub
; /* this is so that one buggy filter
1066 doesn't make the whole lot fail */
1070 hrSub
= IMoniker_BindToStorage(pMonikerCat
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBagCat
);
1072 if (SUCCEEDED(hrSub
))
1073 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"Merit", &var
, NULL
);
1075 if (SUCCEEDED(hrSub
) && (V_UI4(&var
) >= dwMerit
))
1078 IEnumMoniker
* pEnum
;
1079 IMoniker
* pMoniker
;
1083 if (TRACE_ON(quartz
))
1086 V_VT(&temp
) = VT_EMPTY
;
1087 IPropertyBag_Read(pPropBagCat
, L
"FriendlyName", &temp
, NULL
);
1088 TRACE("Considering category %s\n", debugstr_w(V_BSTR(&temp
)));
1089 VariantClear(&temp
);
1092 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"CLSID", &var
, NULL
);
1094 if (SUCCEEDED(hrSub
))
1095 hrSub
= CLSIDFromString(V_BSTR(&var
), &clsidCat
);
1097 if (SUCCEEDED(hrSub
))
1098 hrSub
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &clsidCat
, &pEnum
, 0);
1102 while (IEnumMoniker_Next(pEnum
, 1, &pMoniker
, NULL
) == S_OK
)
1104 IPropertyBag
* pPropBag
= NULL
;
1109 BOOL bInputMatch
= !bInputNeeded
;
1110 BOOL bOutputMatch
= !bOutputNeeded
;
1112 ZeroMemory(&rf2
, sizeof(rf2
));
1115 hrSub
= IMoniker_BindToStorage(pMoniker
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBag
);
1117 if (TRACE_ON(quartz
))
1120 V_VT(&temp
) = VT_EMPTY
;
1121 IPropertyBag_Read(pPropBag
, L
"FriendlyName", &temp
, NULL
);
1122 TRACE("Considering filter %s\n", debugstr_w(V_BSTR(&temp
)));
1123 VariantClear(&temp
);
1126 if (SUCCEEDED(hrSub
))
1128 hrSub
= IPropertyBag_Read(pPropBag
, L
"FilterData", &var
, NULL
);
1131 if (SUCCEEDED(hrSub
))
1132 hrSub
= SafeArrayAccessData(V_ARRAY(&var
), (LPVOID
*)&pData
);
1134 if (SUCCEEDED(hrSub
))
1135 hrSub
= FM2_ReadFilterData(pData
, &rf2
);
1138 SafeArrayUnaccessData(V_ARRAY(&var
));
1142 /* Logic used for bInputMatch expression:
1143 * There exists some pin such that bInputNeeded implies (pin is an input and
1144 * (bRender implies pin has render flag) and major/minor types members of
1146 * bOutputMatch is similar, but without the "bRender implies ..." part
1147 * and substituting variables names containing input for output
1150 /* determine whether filter meets requirements */
1151 if (SUCCEEDED(hrSub
) && (rf2
.dwMerit
>= dwMerit
))
1153 for (i
= 0; (i
< rf2
.cPins2
) && (!bInputMatch
|| !bOutputMatch
); i
++)
1155 const REGFILTERPINS2
* rfp2
= rf2
.rgPins2
+ i
;
1157 bInputMatch
= bInputMatch
|| (!(rfp2
->dwFlags
& REG_PINFLAG_B_OUTPUT
) &&
1158 (!bRender
|| (rfp2
->dwFlags
& REG_PINFLAG_B_RENDERER
)) &&
1159 MatchTypes(bExactMatch
, rfp2
->nMediaTypes
, rfp2
->lpMediaType
, cInputTypes
, pInputTypes
));
1160 bOutputMatch
= bOutputMatch
|| ((rfp2
->dwFlags
& REG_PINFLAG_B_OUTPUT
) &&
1161 MatchTypes(bExactMatch
, rfp2
->nMediaTypes
, rfp2
->lpMediaType
, cOutputTypes
, pOutputTypes
));
1164 if (bInputMatch
&& bOutputMatch
)
1166 struct MONIKER_MERIT mm
= {pMoniker
, rf2
.dwMerit
};
1167 IMoniker_AddRef(pMoniker
);
1168 add_data(&monikers
, &mm
, sizeof(mm
));
1172 FM2_DeleteRegFilter(&rf2
);
1174 IPropertyBag_Release(pPropBag
);
1175 IMoniker_Release(pMoniker
);
1177 IEnumMoniker_Release(pEnum
);
1183 IPropertyBag_Release(pPropBagCat
);
1184 IMoniker_Release(pMonikerCat
);
1189 IMoniker
** ppMoniker
;
1191 ULONG nMonikerCount
= monikers
.current
/ sizeof(struct MONIKER_MERIT
);
1193 /* sort the monikers in descending merit order */
1194 qsort(monikers
.pData
, nMonikerCount
,
1195 sizeof(struct MONIKER_MERIT
),
1198 /* construct an IEnumMoniker interface */
1199 ppMoniker
= CoTaskMemAlloc(nMonikerCount
* sizeof(IMoniker
*));
1200 for (i
= 0; i
< nMonikerCount
; i
++)
1202 /* no need to AddRef here as already AddRef'd above */
1203 ppMoniker
[i
] = ((struct MONIKER_MERIT
*)monikers
.pData
)[i
].pMoniker
;
1205 hr
= enum_moniker_create(ppMoniker
, nMonikerCount
, ppEnum
);
1206 CoTaskMemFree(ppMoniker
);
1209 delete_vector(&monikers
);
1210 IEnumMoniker_Release(pEnumCat
);
1211 ICreateDevEnum_Release(pCreateDevEnum
);
1216 static HRESULT WINAPI
FilterMapper3_GetICreateDevEnum(IFilterMapper3
*iface
, ICreateDevEnum
**ppEnum
)
1218 TRACE("(%p, %p)\n", iface
, ppEnum
);
1221 return CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC
, &IID_ICreateDevEnum
, (void**)ppEnum
);
1224 static const IFilterMapper3Vtbl fm3vtbl
=
1227 FilterMapper3_QueryInterface
,
1228 FilterMapper3_AddRef
,
1229 FilterMapper3_Release
,
1231 FilterMapper3_CreateCategory
,
1232 FilterMapper3_UnregisterFilter
,
1233 FilterMapper3_RegisterFilter
,
1234 FilterMapper3_EnumMatchingFilters
,
1235 FilterMapper3_GetICreateDevEnum
1238 /*** IUnknown methods ***/
1240 static HRESULT WINAPI
FilterMapper_QueryInterface(IFilterMapper
* iface
, REFIID riid
, LPVOID
*ppv
)
1242 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1244 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
1246 return FilterMapper3_QueryInterface(&This
->IFilterMapper3_iface
, riid
, ppv
);
1249 static ULONG WINAPI
FilterMapper_AddRef(IFilterMapper
* iface
)
1251 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1253 return IUnknown_AddRef(This
->outer_unk
);
1256 static ULONG WINAPI
FilterMapper_Release(IFilterMapper
* iface
)
1258 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1260 return IUnknown_Release(This
->outer_unk
);
1263 /*** IFilterMapper methods ***/
1265 static HRESULT WINAPI
FilterMapper_EnumMatchingFilters(
1266 IFilterMapper
* iface
,
1267 IEnumRegFilters
**ppEnum
,
1277 FilterMapper3Impl
*This
= impl_from_IFilterMapper(iface
);
1280 IEnumMoniker
* ppEnumMoniker
;
1283 ULONG idx
= 0, nb_mon
= 0;
1284 REGFILTER
* regfilters
;
1287 TRACE("(%p/%p)->(%p, %x, %s, %s, %s, %s, %s, %s, %s)\n",
1292 bInputNeeded
? "true" : "false",
1293 debugstr_guid(&clsInMaj
),
1294 debugstr_guid(&clsInSub
),
1295 bRender
? "true" : "false",
1296 bOutputNeeded
? "true" : "false",
1297 debugstr_guid(&clsOutMaj
),
1298 debugstr_guid(&clsOutSub
));
1300 InputType
[0] = clsInMaj
;
1301 InputType
[1] = clsInSub
;
1302 OutputType
[0] = clsOutMaj
;
1303 OutputType
[1] = clsOutSub
;
1307 hr
= IFilterMapper3_EnumMatchingFilters(&This
->IFilterMapper3_iface
, &ppEnumMoniker
, 0, TRUE
,
1308 dwMerit
, bInputNeeded
, 1, InputType
, NULL
, &GUID_NULL
, bRender
, bOutputNeeded
, 1,
1309 OutputType
, NULL
, &GUID_NULL
);
1314 while(IEnumMoniker_Next(ppEnumMoniker
, 1, &IMon
, &nb
) == S_OK
)
1316 IMoniker_Release(IMon
);
1322 IEnumMoniker_Release(ppEnumMoniker
);
1323 return enum_reg_filters_create(NULL
, 0, ppEnum
);
1326 regfilters
= CoTaskMemAlloc(nb_mon
* sizeof(REGFILTER
));
1329 IEnumMoniker_Release(ppEnumMoniker
);
1330 return E_OUTOFMEMORY
;
1332 ZeroMemory(regfilters
, nb_mon
* sizeof(REGFILTER
)); /* will prevent bad free of Name in case of error. */
1334 IEnumMoniker_Reset(ppEnumMoniker
);
1335 while(IEnumMoniker_Next(ppEnumMoniker
, 1, &IMon
, &nb
) == S_OK
)
1337 IPropertyBag
* pPropBagCat
= NULL
;
1345 hrSub
= IMoniker_BindToStorage(IMon
, NULL
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&pPropBagCat
);
1347 if (SUCCEEDED(hrSub
))
1348 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"CLSID", &var
, NULL
);
1350 if (SUCCEEDED(hrSub
))
1351 hrSub
= CLSIDFromString(V_BSTR(&var
), &clsid
);
1355 if (SUCCEEDED(hrSub
))
1356 hrSub
= IPropertyBag_Read(pPropBagCat
, L
"FriendlyName", &var
, NULL
);
1358 if (SUCCEEDED(hrSub
))
1360 len
= (wcslen(V_BSTR(&var
)) + 1) * sizeof(WCHAR
);
1361 if (!(regfilters
[idx
].Name
= CoTaskMemAlloc(len
*2)))
1365 if (SUCCEEDED(hrSub
) && regfilters
[idx
].Name
)
1367 memcpy(regfilters
[idx
].Name
, V_BSTR(&var
), len
);
1368 regfilters
[idx
].Clsid
= clsid
;
1373 IPropertyBag_Release(pPropBagCat
);
1374 IMoniker_Release(IMon
);
1380 hr
= enum_reg_filters_create(regfilters
, idx
, ppEnum
);
1383 for (idx
= 0; idx
< nb_mon
; idx
++)
1384 CoTaskMemFree(regfilters
[idx
].Name
);
1385 CoTaskMemFree(regfilters
);
1386 IEnumMoniker_Release(ppEnumMoniker
);
1392 static HRESULT WINAPI
FilterMapper_RegisterFilter(IFilterMapper
* iface
,
1393 CLSID clsid
, const WCHAR
*name
, DWORD merit
)
1395 WCHAR keypath
[46], guidstr
[39];
1399 TRACE("iface %p, clsid %s, name %s, merit %#x.\n",
1400 iface
, debugstr_guid(&clsid
), debugstr_w(name
), merit
);
1402 StringFromGUID2(&clsid
, guidstr
, ARRAY_SIZE(guidstr
));
1404 wcscpy(keypath
, L
"Filter\\");
1405 wcscat(keypath
, guidstr
);
1406 if ((ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
)))
1407 return HRESULT_FROM_WIN32(ret
);
1409 if ((ret
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (const BYTE
*)name
, (wcslen(name
) + 1) * sizeof(WCHAR
))))
1410 ERR("Failed to set filter name, error %u.\n", ret
);
1413 wcscpy(keypath
, L
"CLSID\\");
1414 wcscat(keypath
, guidstr
);
1415 if (!(ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
)))
1417 if ((ret
= RegSetValueExW(key
, L
"Merit", 0, REG_DWORD
, (const BYTE
*)&merit
, sizeof(DWORD
))))
1418 ERR("Failed to set merit, error %u.\n", ret
);
1422 ERR("Failed to create CLSID key, error %u.\n", ret
);
1427 static HRESULT WINAPI
FilterMapper_RegisterFilterInstance(IFilterMapper
* iface
, CLSID clsid
, LPCWSTR szName
, CLSID
*MRId
)
1429 TRACE("(%p)->(%s, %s, %p)\n", iface
, debugstr_guid(&clsid
), debugstr_w(szName
), MRId
);
1431 /* Not implemented in Windows (tested on Win2k) */
1436 static HRESULT WINAPI
FilterMapper_RegisterPin(IFilterMapper
*iface
, CLSID clsid
,
1437 const WCHAR
*name
, BOOL rendered
, BOOL output
, BOOL zero
, BOOL many
,
1438 CLSID external_filter
, const WCHAR
*external_pin
)
1440 WCHAR keypath
[6 + 38 + 1], *pin_keypath
;
1441 HKEY key
, pin_key
, type_key
;
1444 TRACE("iface %p, clsid %s, name %s, rendered %d, output %d, zero %d, "
1445 "many %d, external_filter %s, external_pin %s.\n",
1446 iface
, debugstr_guid(&clsid
), debugstr_w(name
), rendered
, output
,
1447 zero
, many
, debugstr_guid(&external_filter
), debugstr_w(external_pin
));
1449 wcscpy(keypath
, L
"CLSID\\");
1450 StringFromGUID2(&clsid
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
1451 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, KEY_WRITE
, &key
)))
1452 return HRESULT_FROM_WIN32(ret
);
1454 if (!(pin_keypath
= malloc((5 + wcslen(name
) + 1) * sizeof(WCHAR
))))
1457 return E_OUTOFMEMORY
;
1459 wcscpy(pin_keypath
, L
"Pins\\");
1460 wcscat(pin_keypath
, name
);
1462 if ((ret
= RegCreateKeyExW(key
, pin_keypath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &pin_key
, NULL
)))
1464 ERR("Failed to open pin key, error %u.\n", ret
);
1467 return HRESULT_FROM_WIN32(ret
);
1471 if ((ret
= RegSetValueExW(pin_key
, L
"AllowedMany", 0, REG_DWORD
, (const BYTE
*)&many
, sizeof(DWORD
))))
1472 ERR("Failed to set AllowedMany value, error %u.\n", ret
);
1473 if ((ret
= RegSetValueExW(pin_key
, L
"AllowedZero", 0, REG_DWORD
, (const BYTE
*)&zero
, sizeof(DWORD
))))
1474 ERR("Failed to set AllowedZero value, error %u.\n", ret
);
1475 if ((ret
= RegSetValueExW(pin_key
, L
"Direction", 0, REG_DWORD
, (const BYTE
*)&output
, sizeof(DWORD
))))
1476 ERR("Failed to set Direction value, error %u.\n", ret
);
1477 if ((ret
= RegSetValueExW(pin_key
, L
"IsRendered", 0, REG_DWORD
, (const BYTE
*)&rendered
, sizeof(DWORD
))))
1478 ERR("Failed to set IsRendered value, error %u.\n", ret
);
1480 if (!(ret
= RegCreateKeyExW(pin_key
, L
"Types", 0, NULL
, 0, 0, NULL
, &type_key
, NULL
)))
1481 RegCloseKey(type_key
);
1483 ERR("Failed to create Types subkey, error %u.\n", ret
);
1485 RegCloseKey(pin_key
);
1492 static HRESULT WINAPI
FilterMapper_RegisterPinType(IFilterMapper
*iface
,
1493 CLSID clsid
, const WCHAR
*pin
, CLSID majortype
, CLSID subtype
)
1495 WCHAR
*keypath
, type_keypath
[38 + 1 + 38 + 1];
1500 TRACE("iface %p, clsid %s, pin %s, majortype %s, subtype %s.\n", iface
,
1501 debugstr_guid(&clsid
), debugstr_w(pin
), debugstr_guid(&majortype
), debugstr_guid(&subtype
));
1503 len
= 6 + 38 + 6 + wcslen(pin
) + 6 + 1;
1504 if (!(keypath
= malloc(len
* sizeof(WCHAR
))))
1505 return E_OUTOFMEMORY
;
1507 wcscpy(keypath
, L
"CLSID\\");
1508 StringFromGUID2(&clsid
, keypath
+ wcslen(keypath
), len
- wcslen(keypath
));
1509 wcscat(keypath
, L
"\\Pins\\");
1510 wcscat(keypath
, pin
);
1511 wcscat(keypath
, L
"\\Types");
1512 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, KEY_CREATE_SUB_KEY
, &key
)))
1515 return HRESULT_FROM_WIN32(ret
);
1519 StringFromGUID2(&majortype
, type_keypath
, ARRAY_SIZE(type_keypath
));
1520 wcscat(type_keypath
, L
"\\");
1521 StringFromGUID2(&subtype
, type_keypath
+ wcslen(type_keypath
), ARRAY_SIZE(type_keypath
) - wcslen(type_keypath
));
1522 if (!(ret
= RegCreateKeyExW(key
, type_keypath
, 0, NULL
, 0, 0, NULL
, &type_key
, NULL
)))
1523 RegCloseKey(type_key
);
1525 ERR("Failed to create type key, error %u.\n", ret
);
1528 return HRESULT_FROM_WIN32(ret
);
1531 static HRESULT WINAPI
FilterMapper_UnregisterFilter(IFilterMapper
*iface
, CLSID clsid
)
1533 WCHAR guidstr
[39], keypath
[6 + 38 + 1];
1537 TRACE("iface %p, clsid %s.\n", iface
, debugstr_guid(&clsid
));
1539 StringFromGUID2(&clsid
, guidstr
, ARRAY_SIZE(guidstr
));
1541 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"Filter", 0, 0, &key
)))
1542 return HRESULT_FROM_WIN32(ret
);
1543 if ((ret
= RegDeleteKeyW(key
, guidstr
)))
1544 ERR("Failed to delete filter key, error %u.\n", ret
);
1547 wcscpy(keypath
, L
"CLSID\\");
1548 wcscat(keypath
, guidstr
);
1549 if (!(ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, KEY_WRITE
, &key
)))
1551 if ((ret
= RegDeleteValueW(key
, L
"Merit")))
1552 ERR("Failed to delete Merit value, error %u.\n", ret
);
1553 if ((ret
= RegDeleteTreeW(key
, L
"Pins")))
1554 ERR("Failed to delete Pins key, error %u.\n", ret
);
1558 ERR("Failed to open CLSID key, error %u.\n", ret
);
1563 static HRESULT WINAPI
FilterMapper_UnregisterFilterInstance(IFilterMapper
* iface
, CLSID MRId
)
1565 TRACE("(%p)->(%s)\n", iface
, debugstr_guid(&MRId
));
1567 /* Not implemented in Windows (tested on Win2k) */
1572 static HRESULT WINAPI
FilterMapper_UnregisterPin(IFilterMapper
* iface
, CLSID clsid
, const WCHAR
*name
)
1574 WCHAR keypath
[6 + 38 + 5 + 1];
1578 TRACE("iface %p, clsid %s, name %s.\n", iface
, debugstr_guid(&clsid
), debugstr_w(name
));
1581 return E_INVALIDARG
;
1583 wcscpy(keypath
, L
"CLSID\\");
1584 StringFromGUID2(&clsid
, keypath
+ wcslen(keypath
), ARRAY_SIZE(keypath
) - wcslen(keypath
));
1585 wcscat(keypath
, L
"\\Pins");
1586 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, keypath
, 0, 0, &key
)))
1587 return HRESULT_FROM_WIN32(ret
);
1589 if ((ret
= RegDeleteTreeW(key
, name
)))
1590 ERR("Failed to delete subkey, error %u.\n", ret
);
1597 static const IFilterMapperVtbl fmvtbl
=
1600 FilterMapper_QueryInterface
,
1601 FilterMapper_AddRef
,
1602 FilterMapper_Release
,
1604 FilterMapper_RegisterFilter
,
1605 FilterMapper_RegisterFilterInstance
,
1606 FilterMapper_RegisterPin
,
1607 FilterMapper_RegisterPinType
,
1608 FilterMapper_UnregisterFilter
,
1609 FilterMapper_UnregisterFilterInstance
,
1610 FilterMapper_UnregisterPin
,
1611 FilterMapper_EnumMatchingFilters
1615 /*** IUnknown methods ***/
1616 static HRESULT WINAPI
AMFilterData_QueryInterface(IAMFilterData
* iface
, REFIID riid
, LPVOID
*ppv
)
1618 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1620 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
1623 static ULONG WINAPI
AMFilterData_AddRef(IAMFilterData
* iface
)
1625 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1627 return IUnknown_AddRef(This
->outer_unk
);
1630 static ULONG WINAPI
AMFilterData_Release(IAMFilterData
* iface
)
1632 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1634 return IUnknown_Release(This
->outer_unk
);
1637 /*** IAMFilterData methods ***/
1638 static HRESULT WINAPI
AMFilterData_ParseFilterData(IAMFilterData
* iface
,
1639 BYTE
*pData
, ULONG cb
,
1640 BYTE
**ppRegFilter2
)
1642 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1644 static REGFILTER2
*prf2
;
1646 TRACE("(%p/%p)->(%p, %d, %p)\n", This
, iface
, pData
, cb
, ppRegFilter2
);
1648 prf2
= CoTaskMemAlloc(sizeof(*prf2
));
1650 return E_OUTOFMEMORY
;
1651 *ppRegFilter2
= (BYTE
*)&prf2
;
1653 hr
= FM2_ReadFilterData(pData
, prf2
);
1656 CoTaskMemFree(prf2
);
1657 *ppRegFilter2
= NULL
;
1663 static HRESULT WINAPI
AMFilterData_CreateFilterData(IAMFilterData
* iface
,
1665 BYTE
**pRegFilterData
,
1668 FilterMapper3Impl
*This
= impl_from_IAMFilterData(iface
);
1670 TRACE("(%p/%p)->(%p, %p, %p)\n", This
, iface
, prf2
, pRegFilterData
, pcb
);
1672 return FM2_WriteFilterData(prf2
, pRegFilterData
, pcb
);
1675 static const IAMFilterDataVtbl AMFilterDataVtbl
= {
1676 AMFilterData_QueryInterface
,
1677 AMFilterData_AddRef
,
1678 AMFilterData_Release
,
1679 AMFilterData_ParseFilterData
,
1680 AMFilterData_CreateFilterData
1683 HRESULT
filter_mapper_create(IUnknown
*pUnkOuter
, IUnknown
**out
)
1685 FilterMapper3Impl
* pFM2impl
;
1687 pFM2impl
= CoTaskMemAlloc(sizeof(*pFM2impl
));
1689 return E_OUTOFMEMORY
;
1691 pFM2impl
->IUnknown_inner
.lpVtbl
= &IInner_VTable
;
1692 pFM2impl
->IFilterMapper3_iface
.lpVtbl
= &fm3vtbl
;
1693 pFM2impl
->IFilterMapper_iface
.lpVtbl
= &fmvtbl
;
1694 pFM2impl
->IAMFilterData_iface
.lpVtbl
= &AMFilterDataVtbl
;
1698 pFM2impl
->outer_unk
= pUnkOuter
;
1700 pFM2impl
->outer_unk
= &pFM2impl
->IUnknown_inner
;
1702 TRACE("Created filter mapper %p.\n", pFM2impl
);
1703 *out
= &pFM2impl
->IUnknown_inner
;