2 * IEnumMoniker implementation for DEVENUM.dll
4 * Copyright (C) 2002 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * - Implements IEnumMoniker interface which enumerates through moniker
22 * objects created from HKEY_CLASSES/CLSID/{DEVICE_CLSID}/Instance
25 #include "devenum_private.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(devenum
);
31 BOOL
array_reserve(void **elements
, unsigned int *capacity
, unsigned int count
, unsigned int size
)
33 unsigned int max_capacity
, new_capacity
;
36 if (count
<= *capacity
)
39 max_capacity
= ~0u / size
;
40 if (count
> max_capacity
)
43 new_capacity
= max(8, *capacity
);
44 while (new_capacity
< count
&& new_capacity
<= max_capacity
/ 2)
46 if (new_capacity
< count
)
49 if (!(new_elements
= realloc(*elements
, new_capacity
* size
)))
51 ERR("Failed to allocate memory.\n");
55 *elements
= new_elements
;
56 *capacity
= new_capacity
;
62 IEnumMoniker IEnumMoniker_iface
;
65 IEnumDMO
*dmo_enum
, *dmo_enum2
;
72 static inline struct moniker
*impl_from_IPropertyBag(IPropertyBag
*iface
)
74 return CONTAINING_RECORD(iface
, struct moniker
, IPropertyBag_iface
);
77 static HRESULT WINAPI
property_bag_QueryInterface(IPropertyBag
*iface
, REFIID iid
, void **out
)
79 struct moniker
*moniker
= impl_from_IPropertyBag(iface
);
81 TRACE("moniker %p, iid %s, out %p.\n", moniker
, debugstr_guid(iid
), out
);
86 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IPropertyBag
))
89 IPropertyBag_AddRef(iface
);
93 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
98 static ULONG WINAPI
property_bag_AddRef(IPropertyBag
*iface
)
100 struct moniker
*moniker
= impl_from_IPropertyBag(iface
);
101 return IMoniker_AddRef(&moniker
->IMoniker_iface
);
104 static ULONG WINAPI
property_bag_Release(IPropertyBag
*iface
)
106 struct moniker
*moniker
= impl_from_IPropertyBag(iface
);
107 return IMoniker_Release(&moniker
->IMoniker_iface
);
110 static HRESULT WINAPI
property_bag_Read(IPropertyBag
*iface
,
111 const WCHAR
*name
, VARIANT
*var
, IErrorLog
*errorlog
)
113 struct moniker
*moniker
= impl_from_IPropertyBag(iface
);
122 TRACE("moniker %p, name %s, var %p, errorlog %p.\n", moniker
, debugstr_w(name
), var
, errorlog
);
127 switch (moniker
->type
)
130 if (!wcscmp(name
, L
"FriendlyName"))
132 if (SUCCEEDED(hr
= DMOGetName(&moniker
->clsid
, dmo_name
)))
135 V_BSTR(var
) = SysAllocString(dmo_name
);
139 if (!wcscmp(name
, L
"FilterData"))
141 DMO_PARTIAL_MEDIATYPE
*types
= NULL
, *new_array
;
142 ULONG count
= 1, input_count
, output_count
, i
;
143 REGFILTERPINS2 reg_pins
[2] = {{0}};
144 REGFILTER2 reg_filter
= {0};
145 REGPINTYPES
*reg_types
;
151 if (!(new_array
= realloc(types
, 2 * count
* sizeof(*types
))))
154 return E_OUTOFMEMORY
;
158 if (FAILED(hr
= DMOGetTypes(&moniker
->clsid
, count
, &input_count
, types
,
159 count
, &output_count
, types
+ count
)))
164 } while (input_count
== count
|| output_count
== count
);
166 if (!(reg_types
= malloc(2 * count
* sizeof(*reg_types
))))
172 for (i
= 0; i
< input_count
; ++i
)
174 reg_types
[i
].clsMajorType
= &types
[i
].type
;
175 reg_types
[i
].clsMinorType
= &types
[i
].subtype
;
177 for (i
= 0; i
< output_count
; ++i
)
179 reg_types
[count
+ i
].clsMajorType
= &types
[count
+ i
].type
;
180 reg_types
[count
+ i
].clsMinorType
= &types
[count
+ i
].subtype
;
182 reg_pins
[0].cInstances
= 1;
183 reg_pins
[0].nMediaTypes
= input_count
;
184 reg_pins
[0].lpMediaType
= reg_types
;
185 reg_pins
[1].dwFlags
= REG_PINFLAG_B_OUTPUT
;
186 reg_pins
[1].cInstances
= 1;
187 reg_pins
[1].nMediaTypes
= output_count
;
188 reg_pins
[1].lpMediaType
= reg_types
+ count
;
189 reg_filter
.dwVersion
= 2;
190 reg_filter
.dwMerit
= MERIT_NORMAL
+ 0x800;
191 reg_filter
.cPins2
= 2;
192 reg_filter
.rgPins2
= reg_pins
;
194 hr
= create_filter_data(var
, ®_filter
);
199 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND
);
202 wcscpy(path
, L
"CLSID\\");
203 if (moniker
->has_class
)
205 StringFromGUID2(&moniker
->class, path
+ wcslen(path
), CHARS_IN_GUID
);
206 wcscat(path
, L
"\\Instance");
208 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, path
, 0, 0, &parent
)))
209 return HRESULT_FROM_WIN32(ret
);
213 wcscpy(path
, L
"Software\\Microsoft\\ActiveMovie\\devenum\\");
214 if (moniker
->has_class
)
215 StringFromGUID2(&moniker
->class, path
+ wcslen(path
), CHARS_IN_GUID
);
216 if ((ret
= RegOpenKeyExW(HKEY_CURRENT_USER
, path
, 0, 0, &parent
)))
217 return HRESULT_FROM_WIN32(ret
);
223 ret
= RegOpenKeyExW(parent
, moniker
->name
, 0, KEY_READ
, &key
);
226 return HRESULT_FROM_WIN32(ret
);
228 if ((ret
= RegQueryValueExW(key
, name
, NULL
, NULL
, NULL
, &size
)))
231 return HRESULT_FROM_WIN32(ret
);
235 if ((ret
= RegQueryValueExW(key
, name
, NULL
, &type
, data
, &size
)))
239 return HRESULT_FROM_WIN32(ret
);
246 if (V_VT(var
) == VT_EMPTY
)
248 if (V_VT(var
) != VT_BSTR
)
250 WARN("Invalid type %s.\n", debugstr_vt(V_VT(var
)));
253 V_BSTR(var
) = SysAllocStringLen(data
, size
/ sizeof(WCHAR
) - 1);
257 if (V_VT(var
) == VT_EMPTY
)
259 if (V_VT(var
) != VT_I4
)
261 WARN("Invalid type %s.\n", debugstr_vt(V_VT(var
)));
264 V_I4(var
) = *(DWORD
*)data
;
269 SAFEARRAYBOUND bound
= {.cElements
= size
};
272 if (V_VT(var
) == VT_EMPTY
)
273 V_VT(var
) = VT_ARRAY
| VT_UI1
;
274 if (V_VT(var
) != (VT_ARRAY
| VT_UI1
))
276 WARN("Invalid type %s.\n", debugstr_vt(V_VT(var
)));
280 if (!(V_ARRAY(var
) = SafeArrayCreate(VT_UI1
, 1, &bound
)))
283 return E_OUTOFMEMORY
;
286 SafeArrayAccessData(V_ARRAY(var
), &array_data
);
287 memcpy(array_data
, data
, size
);
288 SafeArrayUnaccessData(V_ARRAY(var
));
293 FIXME("Unhandled type %#lx.\n", type
);
299 static HRESULT WINAPI
property_bag_Write(IPropertyBag
*iface
, const WCHAR
*name
, VARIANT
*var
)
301 struct moniker
*moniker
= impl_from_IPropertyBag(iface
);
306 TRACE("moniker %p, name %s, var %s.\n", moniker
, debugstr_w(name
), debugstr_variant(var
));
308 switch (moniker
->type
)
311 return E_ACCESSDENIED
;
314 wcscpy(path
, L
"CLSID\\");
315 if (moniker
->has_class
)
317 StringFromGUID2(&moniker
->class, path
+ wcslen(path
), CHARS_IN_GUID
);
318 wcscat(path
, L
"\\Instance");
320 if ((ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, path
, 0, NULL
, 0, 0, NULL
, &parent
, NULL
)))
321 return HRESULT_FROM_WIN32(ret
);
325 wcscpy(path
, L
"Software\\Microsoft\\ActiveMovie\\devenum\\");
326 if (moniker
->has_class
)
327 StringFromGUID2(&moniker
->class, path
+ wcslen(path
), CHARS_IN_GUID
);
328 if ((ret
= RegCreateKeyExW(HKEY_CURRENT_USER
, path
, 0, NULL
, 0, 0, NULL
, &parent
, NULL
)))
329 return HRESULT_FROM_WIN32(ret
);
334 ret
= RegCreateKeyExW(parent
, moniker
->name
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
);
337 return HRESULT_FROM_WIN32(ret
);
342 ret
= RegSetValueExW(key
, name
, 0, REG_SZ
, (BYTE
*)V_BSTR(var
),
343 (wcslen(V_BSTR(var
)) + 1) * sizeof(WCHAR
));
346 ret
= RegSetValueExW(key
, name
, 0, REG_DWORD
, (BYTE
*)&V_I4(var
), sizeof(DWORD
));
348 case VT_ARRAY
| VT_UI1
:
352 SafeArrayGetLBound(V_ARRAY(var
), 1, &lbound
);
353 SafeArrayGetUBound(V_ARRAY(var
), 1, &ubound
);
354 SafeArrayAccessData(V_ARRAY(var
), &array_data
);
355 ret
= RegSetValueExW(key
, name
, 0, REG_BINARY
, array_data
, ubound
- lbound
+ 1);
356 SafeArrayUnaccessData(V_ARRAY(var
));
360 WARN("Unhandled type %s.\n", debugstr_vt(V_VT(var
)));
368 static const IPropertyBagVtbl IPropertyBag_Vtbl
=
370 property_bag_QueryInterface
,
372 property_bag_Release
,
377 static inline struct moniker
*impl_from_IMoniker(IMoniker
*iface
)
379 return CONTAINING_RECORD(iface
, struct moniker
, IMoniker_iface
);
382 static HRESULT WINAPI
moniker_QueryInterface(IMoniker
*iface
, REFIID riid
, void **ppv
)
384 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid
));
389 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
390 IsEqualGUID(riid
, &IID_IPersist
) ||
391 IsEqualGUID(riid
, &IID_IPersistStream
) ||
392 IsEqualGUID(riid
, &IID_IMoniker
))
395 IMoniker_AddRef(iface
);
399 FIXME("- no interface IID: %s\n", debugstr_guid(riid
));
401 return E_NOINTERFACE
;
404 static ULONG WINAPI
moniker_AddRef(IMoniker
*iface
)
406 struct moniker
*moniker
= impl_from_IMoniker(iface
);
407 ULONG refcount
= InterlockedIncrement(&moniker
->ref
);
409 TRACE("%p increasing refcount to %lu.\n", moniker
, refcount
);
414 static ULONG WINAPI
moniker_Release(IMoniker
*iface
)
416 struct moniker
*This
= impl_from_IMoniker(iface
);
417 ULONG refcount
= InterlockedDecrement(&This
->ref
);
419 TRACE("%p decreasing refcount to %lu.\n", This
, refcount
);
429 static HRESULT WINAPI
moniker_GetClassID(IMoniker
*iface
, CLSID
*pClassID
)
431 struct moniker
*This
= impl_from_IMoniker(iface
);
433 TRACE("(%p)->(%p)\n", This
, pClassID
);
435 if (pClassID
== NULL
)
438 *pClassID
= CLSID_CDeviceMoniker
;
443 static HRESULT WINAPI
moniker_IsDirty(IMoniker
*iface
)
445 FIXME("(%p)->(): stub\n", iface
);
450 static HRESULT WINAPI
moniker_Load(IMoniker
*iface
, IStream
*pStm
)
452 FIXME("(%p)->(%p): stub\n", iface
, pStm
);
457 static HRESULT WINAPI
moniker_Save(IMoniker
*iface
, IStream
*pStm
, BOOL fClearDirty
)
459 FIXME("(%p)->(%p, %s): stub\n", iface
, pStm
, fClearDirty
? "true" : "false");
461 return STG_E_CANTSAVE
;
464 static HRESULT WINAPI
moniker_GetSizeMax(IMoniker
*iface
, ULARGE_INTEGER
*pcbSize
)
466 FIXME("(%p)->(%p): stub\n", iface
, pcbSize
);
468 ZeroMemory(pcbSize
, sizeof(*pcbSize
));
473 static HRESULT WINAPI
moniker_BindToObject(IMoniker
*iface
, IBindCtx
*bind_ctx
,
474 IMoniker
*left
, REFIID iid
, void **out
)
476 struct moniker
*moniker
= impl_from_IMoniker(iface
);
477 IPersistPropertyBag
*persist_bag
;
483 TRACE("moniker %p, bind_ctx %p, left %p, iid %s, out %p.\n",
484 moniker
, bind_ctx
, left
, debugstr_guid(iid
), out
);
491 if (moniker
->type
== DEVICE_DMO
)
493 IDMOWrapperFilter
*wrapper
;
495 if (FAILED(hr
= CoCreateInstance(&CLSID_DMOWrapperFilter
, NULL
,
496 CLSCTX_INPROC_SERVER
, &IID_IDMOWrapperFilter
, (void **)&wrapper
)))
499 if (SUCCEEDED(hr
= IDMOWrapperFilter_Init(wrapper
, &moniker
->clsid
, &moniker
->class)))
501 hr
= IDMOWrapperFilter_QueryInterface(wrapper
, iid
, out
);
503 IDMOWrapperFilter_Release(wrapper
);
508 V_VT(&var
) = VT_BSTR
;
509 if (FAILED(hr
= IPropertyBag_Read(&moniker
->IPropertyBag_iface
, L
"CLSID", &var
, NULL
)))
512 hr
= CLSIDFromString(V_BSTR(&var
), &clsid
);
517 if (FAILED(hr
= CoCreateInstance(&clsid
, NULL
, CLSCTX_ALL
, &IID_IUnknown
, (void **)&unk
)))
520 if (SUCCEEDED(IUnknown_QueryInterface(unk
, &IID_IPersistPropertyBag
, (void **)&persist_bag
)))
522 hr
= IPersistPropertyBag_Load(persist_bag
, &moniker
->IPropertyBag_iface
, NULL
);
523 IPersistPropertyBag_Release(persist_bag
);
527 hr
= IUnknown_QueryInterface(unk
, iid
, out
);
529 IUnknown_Release(unk
);
534 static HRESULT WINAPI
moniker_BindToStorage(IMoniker
*iface
, IBindCtx
*pbc
,
535 IMoniker
*pmkToLeft
, REFIID riid
, void **out
)
537 struct moniker
*moniker
= impl_from_IMoniker(iface
);
539 TRACE("moniker %p, left %p, iid %s, out %p.\n", moniker
, pmkToLeft
, debugstr_guid(riid
), out
);
544 return MK_E_NOSTORAGE
;
548 static DWORD reported
;
551 FIXME("ignoring IBindCtx %p\n", pbc
);
556 if (IsEqualGUID(riid
, &IID_IPropertyBag
))
558 *out
= &moniker
->IPropertyBag_iface
;
559 IPropertyBag_AddRef(&moniker
->IPropertyBag_iface
);
563 return MK_E_NOSTORAGE
;
566 static HRESULT WINAPI
moniker_Reduce(IMoniker
*iface
, IBindCtx
*pbc
,
567 DWORD dwReduceHowFar
, IMoniker
**ppmkToLeft
, IMoniker
**ppmkReduced
)
569 struct moniker
*moniker
= impl_from_IMoniker(iface
);
571 TRACE("moniker %p, bind_ctx %p, how_far %#lx, left %p, reduced %p.\n",
572 moniker
, pbc
, dwReduceHowFar
, ppmkToLeft
, ppmkReduced
);
576 *ppmkReduced
= iface
;
578 return MK_S_REDUCED_TO_SELF
;
581 static HRESULT WINAPI
moniker_ComposeWith(IMoniker
*iface
, IMoniker
*pmkRight
,
582 BOOL fOnlyIfNotGeneric
, IMoniker
**ppmkComposite
)
584 FIXME("(%p)->(%p, %s, %p): stub\n", iface
, pmkRight
, fOnlyIfNotGeneric
? "true" : "false", ppmkComposite
);
586 /* FIXME: use CreateGenericComposite? */
587 *ppmkComposite
= NULL
;
592 static HRESULT WINAPI
moniker_Enum(IMoniker
*iface
, BOOL fForward
,
593 IEnumMoniker
**ppenumMoniker
)
595 FIXME("(%p)->(%s, %p): stub\n", iface
, fForward
? "true" : "false", ppenumMoniker
);
597 *ppenumMoniker
= NULL
;
602 static HRESULT WINAPI
moniker_IsEqual(IMoniker
*iface
, IMoniker
*pmkOtherMoniker
)
605 LPOLESTR this_name
, other_name
;
609 TRACE("(%p)->(%p)\n", iface
, pmkOtherMoniker
);
611 if (!pmkOtherMoniker
)
614 IMoniker_GetClassID(pmkOtherMoniker
, &clsid
);
615 if (!IsEqualCLSID(&clsid
, &CLSID_CDeviceMoniker
))
618 res
= CreateBindCtx(0, &bind
);
623 if (SUCCEEDED(IMoniker_GetDisplayName(iface
, bind
, NULL
, &this_name
)) &&
624 SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker
, bind
, NULL
, &other_name
)))
626 int result
= wcsicmp(this_name
, other_name
);
627 CoTaskMemFree(this_name
);
628 CoTaskMemFree(other_name
);
632 IBindCtx_Release(bind
);
636 static HRESULT WINAPI
moniker_Hash(IMoniker
*iface
, DWORD
*pdwHash
)
638 TRACE("(%p)->(%p)\n", iface
, pdwHash
);
645 static HRESULT WINAPI
moniker_IsRunning(IMoniker
*iface
, IBindCtx
*pbc
,
646 IMoniker
*pmkToLeft
, IMoniker
*pmkNewlyRunning
)
648 FIXME("(%p)->(%p, %p, %p): stub\n", iface
, pbc
, pmkToLeft
, pmkNewlyRunning
);
653 static HRESULT WINAPI
moniker_GetTimeOfLastChange(IMoniker
*iface
, IBindCtx
*pbc
,
654 IMoniker
*pmkToLeft
, FILETIME
*pFileTime
)
656 TRACE("(%p)->(%p, %p, %p)\n", iface
, pbc
, pmkToLeft
, pFileTime
);
658 pFileTime
->dwLowDateTime
= 0xFFFFFFFF;
659 pFileTime
->dwHighDateTime
= 0x7FFFFFFF;
661 return MK_E_UNAVAILABLE
;
664 static HRESULT WINAPI
moniker_Inverse(IMoniker
*iface
, IMoniker
**ppmk
)
666 TRACE("(%p)->(%p)\n", iface
, ppmk
);
670 return MK_E_NOINVERSE
;
673 static HRESULT WINAPI
moniker_CommonPrefixWith(IMoniker
*iface
,
674 IMoniker
*pmkOtherMoniker
, IMoniker
**ppmkPrefix
)
676 TRACE("(%p)->(%p, %p)\n", iface
, pmkOtherMoniker
, ppmkPrefix
);
680 return MK_E_NOPREFIX
;
683 static HRESULT WINAPI
moniker_RelativePathTo(IMoniker
*iface
, IMoniker
*pmkOther
,
684 IMoniker
**ppmkRelPath
)
686 TRACE("(%p)->(%p, %p)\n", iface
, pmkOther
, ppmkRelPath
);
688 *ppmkRelPath
= pmkOther
;
693 static HRESULT WINAPI
moniker_GetDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
694 IMoniker
*pmkToLeft
, LPOLESTR
*ppszDisplayName
)
696 struct moniker
*This
= impl_from_IMoniker(iface
);
699 TRACE("(%p)->(%p, %p, %p)\n", iface
, pbc
, pmkToLeft
, ppszDisplayName
);
701 *ppszDisplayName
= NULL
;
703 if (This
->type
== DEVICE_DMO
)
705 buffer
= CoTaskMemAlloc((12 + 2 * CHARS_IN_GUID
+ 1) * sizeof(WCHAR
));
706 if (!buffer
) return E_OUTOFMEMORY
;
708 wcscpy(buffer
, L
"@device:dmo:");
709 StringFromGUID2(&This
->clsid
, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
710 StringFromGUID2(&This
->class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
714 buffer
= CoTaskMemAlloc((11 + (This
->has_class
? CHARS_IN_GUID
: 0)
715 + wcslen(This
->name
) + 1) * sizeof(WCHAR
));
716 if (!buffer
) return E_OUTOFMEMORY
;
718 if (This
->type
== DEVICE_FILTER
)
719 wcscpy(buffer
, L
"@device:sw:");
720 else if (This
->type
== DEVICE_CODEC
)
721 wcscpy(buffer
, L
"@device:cm:");
725 StringFromGUID2(&This
->class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
726 wcscat(buffer
, L
"\\");
728 wcscat(buffer
, This
->name
);
731 *ppszDisplayName
= buffer
;
735 static HRESULT WINAPI
moniker_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
736 IMoniker
*pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
*pchEaten
, IMoniker
**ppmkOut
)
738 FIXME("(%p)->(%p, %p, %s, %p, %p)\n", iface
, pbc
, pmkToLeft
, debugstr_w(pszDisplayName
), pchEaten
, ppmkOut
);
746 static HRESULT WINAPI
moniker_IsSystemMoniker(IMoniker
*iface
, DWORD
*pdwMksys
)
748 TRACE("(%p)->(%p)\n", iface
, pdwMksys
);
753 static const IMonikerVtbl IMoniker_Vtbl
=
755 moniker_QueryInterface
,
763 moniker_BindToObject
,
764 moniker_BindToStorage
,
771 moniker_GetTimeOfLastChange
,
773 moniker_CommonPrefixWith
,
774 moniker_RelativePathTo
,
775 moniker_GetDisplayName
,
776 moniker_ParseDisplayName
,
777 moniker_IsSystemMoniker
,
780 struct moniker
*filter_moniker_create(const GUID
*class, const WCHAR
*name
)
782 struct moniker
*object
;
784 if (!(object
= calloc(1, sizeof(*object
))))
787 object
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
788 object
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
790 object
->type
= DEVICE_FILTER
;
792 object
->class = *class;
793 object
->has_class
= !!class;
794 object
->name
= wcsdup(name
);
799 struct moniker
*codec_moniker_create(const GUID
*class, const WCHAR
*name
)
801 struct moniker
*object
;
803 if (!(object
= calloc(1, sizeof(*object
))))
806 object
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
807 object
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
809 object
->type
= DEVICE_CODEC
;
811 object
->class = *class;
812 object
->has_class
= !!class;
813 object
->name
= wcsdup(name
);
818 struct moniker
*dmo_moniker_create(const GUID
class, const GUID clsid
)
820 struct moniker
*object
;
822 if (!(object
= calloc(1, sizeof(*object
))))
825 object
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
826 object
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
828 object
->type
= DEVICE_DMO
;
829 object
->class = class;
830 object
->clsid
= clsid
;
835 static inline EnumMonikerImpl
*impl_from_IEnumMoniker(IEnumMoniker
*iface
)
837 return CONTAINING_RECORD(iface
, EnumMonikerImpl
, IEnumMoniker_iface
);
840 static HRESULT WINAPI
enum_moniker_QueryInterface(IEnumMoniker
*iface
, REFIID riid
, void **ppv
)
842 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
847 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
848 IsEqualGUID(riid
, &IID_IEnumMoniker
))
851 IEnumMoniker_AddRef(iface
);
855 FIXME("- no interface IID: %s\n", debugstr_guid(riid
));
857 return E_NOINTERFACE
;
860 static ULONG WINAPI
enum_moniker_AddRef(IEnumMoniker
*iface
)
862 EnumMonikerImpl
*enumerator
= impl_from_IEnumMoniker(iface
);
863 ULONG refcount
= InterlockedIncrement(&enumerator
->ref
);
865 TRACE("%p increasing refcount to %lu.\n", enumerator
, refcount
);
870 static ULONG WINAPI
enum_moniker_Release(IEnumMoniker
*iface
)
872 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
873 ULONG refcount
= InterlockedDecrement(&This
->ref
);
875 TRACE("%p decreasing refcount to %lu.\n", This
, refcount
);
880 IEnumDMO_Release(This
->dmo_enum
);
882 IEnumDMO_Release(This
->dmo_enum2
);
883 RegCloseKey(This
->sw_key
);
884 RegCloseKey(This
->cm_key
);
891 static struct moniker
*get_dmo_moniker(EnumMonikerImpl
*enum_moniker
)
895 if (IsEqualGUID(&enum_moniker
->class, &CLSID_LegacyAmFilterCategory
))
897 if (enum_moniker
->dmo_enum
&& IEnumDMO_Next(enum_moniker
->dmo_enum
, 1, &clsid
, NULL
, NULL
) == S_OK
)
898 return dmo_moniker_create(DMOCATEGORY_AUDIO_DECODER
, clsid
);
899 if (enum_moniker
->dmo_enum2
&& IEnumDMO_Next(enum_moniker
->dmo_enum2
, 1, &clsid
, NULL
, NULL
) == S_OK
)
900 return dmo_moniker_create(DMOCATEGORY_VIDEO_DECODER
, clsid
);
904 if (enum_moniker
->dmo_enum
&& IEnumDMO_Next(enum_moniker
->dmo_enum
, 1, &clsid
, NULL
, NULL
) == S_OK
)
905 return dmo_moniker_create(enum_moniker
->class, clsid
);
911 static HRESULT WINAPI
enum_moniker_Next(IEnumMoniker
*iface
, ULONG celt
, IMoniker
**rgelt
,
914 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
915 WCHAR buffer
[MAX_PATH
+ 1];
916 struct moniker
*moniker
;
921 TRACE("enumerator %p, count %lu, monikers %p, ret_count %p.\n", This
, celt
, rgelt
, pceltFetched
);
923 while (fetched
< celt
)
925 /* FIXME: try PNP devices first */
928 if ((moniker
= get_dmo_moniker(This
)))
930 /* try DirectShow filters */
931 else if (!(res
= RegEnumKeyW(This
->sw_key
, This
->sw_index
, buffer
, ARRAY_SIZE(buffer
))))
934 if ((res
= RegOpenKeyExW(This
->sw_key
, buffer
, 0, KEY_QUERY_VALUE
, &hkey
)))
937 moniker
= filter_moniker_create(&This
->class, buffer
);
939 /* then try codecs */
940 else if (!(res
= RegEnumKeyW(This
->cm_key
, This
->cm_index
, buffer
, ARRAY_SIZE(buffer
))))
944 if ((res
= RegOpenKeyExW(This
->cm_key
, buffer
, 0, KEY_QUERY_VALUE
, &hkey
)))
947 moniker
= codec_moniker_create(&This
->class, buffer
);
953 return E_OUTOFMEMORY
;
955 rgelt
[fetched
++] = &moniker
->IMoniker_iface
;
958 TRACE("Returning %lu monikers.\n", fetched
);
961 *pceltFetched
= fetched
;
969 static HRESULT WINAPI
enum_moniker_Skip(IEnumMoniker
*iface
, ULONG celt
)
971 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
973 TRACE("enumerator %p, count %lu.\n", This
, celt
);
977 /* FIXME: try PNP devices first */
980 if (This
->dmo_enum
&& IEnumDMO_Skip(This
->dmo_enum
, 1) == S_OK
)
982 else if (This
->dmo_enum2
&& IEnumDMO_Skip(This
->dmo_enum2
, 1) == S_OK
)
984 /* try DirectShow filters */
985 else if (RegEnumKeyW(This
->sw_key
, This
->sw_index
, NULL
, 0) != ERROR_NO_MORE_ITEMS
)
989 /* then try codecs */
990 else if (RegEnumKeyW(This
->cm_key
, This
->cm_index
, NULL
, 0) != ERROR_NO_MORE_ITEMS
)
1001 static HRESULT WINAPI
enum_moniker_Reset(IEnumMoniker
*iface
)
1003 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1005 TRACE("(%p)->()\n", iface
);
1008 IEnumDMO_Reset(This
->dmo_enum
);
1009 if (This
->dmo_enum2
)
1010 IEnumDMO_Reset(This
->dmo_enum2
);
1017 static HRESULT WINAPI
enum_moniker_Clone(IEnumMoniker
*iface
, IEnumMoniker
**ppenum
)
1019 FIXME("(%p)->(%p): stub\n", iface
, ppenum
);
1024 /**********************************************************************
1027 static const IEnumMonikerVtbl IEnumMoniker_Vtbl
=
1029 enum_moniker_QueryInterface
,
1030 enum_moniker_AddRef
,
1031 enum_moniker_Release
,
1038 HRESULT
enum_moniker_create(REFCLSID
class, IEnumMoniker
**out
)
1040 EnumMonikerImpl
*object
;
1043 if (!(object
= calloc(1, sizeof(*object
))))
1044 return E_OUTOFMEMORY
;
1046 object
->IEnumMoniker_iface
.lpVtbl
= &IEnumMoniker_Vtbl
;
1048 object
->class = *class;
1050 wcscpy(buffer
, L
"CLSID\\");
1051 StringFromGUID2(class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
1052 wcscat(buffer
, L
"\\Instance");
1053 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, buffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &object
->sw_key
))
1054 object
->sw_key
= NULL
;
1056 wcscpy(buffer
, L
"Software\\Microsoft\\ActiveMovie\\devenum\\");
1057 StringFromGUID2(class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
1058 if (RegOpenKeyExW(HKEY_CURRENT_USER
, buffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &object
->cm_key
))
1059 object
->cm_key
= NULL
;
1061 if (IsEqualGUID(class, &CLSID_LegacyAmFilterCategory
))
1063 if (FAILED(DMOEnum(&DMOCATEGORY_AUDIO_DECODER
, 0, 0, NULL
, 0, NULL
, &object
->dmo_enum
)))
1064 object
->dmo_enum
= NULL
;
1065 if (FAILED(DMOEnum(&DMOCATEGORY_VIDEO_DECODER
, 0, 0, NULL
, 0, NULL
, &object
->dmo_enum2
)))
1066 object
->dmo_enum2
= NULL
;
1070 if (FAILED(DMOEnum(class, 0, 0, NULL
, 0, NULL
, &object
->dmo_enum
)))
1071 object
->dmo_enum
= NULL
;
1074 *out
= &object
->IEnumMoniker_iface
;