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 if (moniker
->type
== DEVICE_DMO
)
129 if (!wcscmp(name
, L
"FriendlyName"))
131 if (SUCCEEDED(hr
= DMOGetName(&moniker
->clsid
, dmo_name
)))
134 V_BSTR(var
) = SysAllocString(dmo_name
);
138 else if (!wcscmp(name
, L
"FilterData"))
140 DMO_PARTIAL_MEDIATYPE
*types
= NULL
, *new_array
;
141 ULONG count
= 1, input_count
, output_count
, i
;
142 REGFILTERPINS2 reg_pins
[2] = {{0}};
143 REGFILTER2 reg_filter
= {0};
144 REGPINTYPES
*reg_types
;
150 if (!(new_array
= realloc(types
, 2 * count
* sizeof(*types
))))
153 return E_OUTOFMEMORY
;
157 if (FAILED(hr
= DMOGetTypes(&moniker
->clsid
, count
, &input_count
, types
,
158 count
, &output_count
, types
+ count
)))
163 } while (input_count
== count
|| output_count
== count
);
165 if (!(reg_types
= malloc(2 * count
* sizeof(*reg_types
))))
171 for (i
= 0; i
< input_count
; ++i
)
173 reg_types
[i
].clsMajorType
= &types
[i
].type
;
174 reg_types
[i
].clsMinorType
= &types
[i
].subtype
;
176 for (i
= 0; i
< output_count
; ++i
)
178 reg_types
[count
+ i
].clsMajorType
= &types
[count
+ i
].type
;
179 reg_types
[count
+ i
].clsMinorType
= &types
[count
+ i
].subtype
;
181 reg_pins
[0].cInstances
= 1;
182 reg_pins
[0].nMediaTypes
= input_count
;
183 reg_pins
[0].lpMediaType
= reg_types
;
184 reg_pins
[1].dwFlags
= REG_PINFLAG_B_OUTPUT
;
185 reg_pins
[1].cInstances
= 1;
186 reg_pins
[1].nMediaTypes
= output_count
;
187 reg_pins
[1].lpMediaType
= reg_types
+ count
;
188 reg_filter
.dwVersion
= 2;
189 reg_filter
.dwMerit
= MERIT_NORMAL
+ 0x800;
190 reg_filter
.cPins2
= 2;
191 reg_filter
.rgPins2
= reg_pins
;
193 hr
= create_filter_data(var
, ®_filter
);
198 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND
);
201 if (moniker
->type
== DEVICE_FILTER
)
203 wcscpy(path
, L
"CLSID\\");
204 if (moniker
->has_class
)
206 StringFromGUID2(&moniker
->class, path
+ wcslen(path
), CHARS_IN_GUID
);
207 wcscat(path
, L
"\\Instance");
209 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, path
, 0, 0, &parent
)))
210 return HRESULT_FROM_WIN32(ret
);
212 else if (moniker
->type
== DEVICE_CODEC
)
214 wcscpy(path
, L
"Software\\Microsoft\\ActiveMovie\\devenum\\");
215 if (moniker
->has_class
)
216 StringFromGUID2(&moniker
->class, path
+ wcslen(path
), CHARS_IN_GUID
);
217 if ((ret
= RegOpenKeyExW(HKEY_CURRENT_USER
, path
, 0, 0, &parent
)))
218 return HRESULT_FROM_WIN32(ret
);
220 ret
= RegOpenKeyExW(parent
, moniker
->name
, 0, KEY_READ
, &key
);
223 return HRESULT_FROM_WIN32(ret
);
225 if ((ret
= RegQueryValueExW(key
, name
, NULL
, NULL
, NULL
, &size
)))
228 return HRESULT_FROM_WIN32(ret
);
232 if ((ret
= RegQueryValueExW(key
, name
, NULL
, &type
, data
, &size
)))
236 return HRESULT_FROM_WIN32(ret
);
243 if (V_VT(var
) == VT_EMPTY
)
245 if (V_VT(var
) != VT_BSTR
)
247 WARN("Invalid type %s.\n", debugstr_vt(V_VT(var
)));
250 V_BSTR(var
) = SysAllocStringLen(data
, size
/ sizeof(WCHAR
) - 1);
254 if (V_VT(var
) == VT_EMPTY
)
256 if (V_VT(var
) != VT_I4
)
258 WARN("Invalid type %s.\n", debugstr_vt(V_VT(var
)));
261 V_I4(var
) = *(DWORD
*)data
;
266 SAFEARRAYBOUND bound
= {.cElements
= size
};
269 if (V_VT(var
) == VT_EMPTY
)
270 V_VT(var
) = VT_ARRAY
| VT_UI1
;
271 if (V_VT(var
) != (VT_ARRAY
| VT_UI1
))
273 WARN("Invalid type %s.\n", debugstr_vt(V_VT(var
)));
277 if (!(V_ARRAY(var
) = SafeArrayCreate(VT_UI1
, 1, &bound
)))
280 return E_OUTOFMEMORY
;
283 SafeArrayAccessData(V_ARRAY(var
), &array_data
);
284 memcpy(array_data
, data
, size
);
285 SafeArrayUnaccessData(V_ARRAY(var
));
290 FIXME("Unhandled type %#lx.\n", type
);
296 static HRESULT WINAPI
property_bag_Write(IPropertyBag
*iface
, const WCHAR
*name
, VARIANT
*var
)
298 struct moniker
*moniker
= impl_from_IPropertyBag(iface
);
303 TRACE("moniker %p, name %s, var %s.\n", moniker
, debugstr_w(name
), debugstr_variant(var
));
305 if (moniker
->type
== DEVICE_DMO
)
306 return E_ACCESSDENIED
;
308 if (moniker
->type
== DEVICE_FILTER
)
310 wcscpy(path
, L
"CLSID\\");
311 if (moniker
->has_class
)
313 StringFromGUID2(&moniker
->class, path
+ wcslen(path
), CHARS_IN_GUID
);
314 wcscat(path
, L
"\\Instance");
316 if ((ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, path
, 0, NULL
, 0, 0, NULL
, &parent
, NULL
)))
317 return HRESULT_FROM_WIN32(ret
);
319 else if (moniker
->type
== DEVICE_CODEC
)
321 wcscpy(path
, L
"Software\\Microsoft\\ActiveMovie\\devenum\\");
322 if (moniker
->has_class
)
323 StringFromGUID2(&moniker
->class, path
+ wcslen(path
), CHARS_IN_GUID
);
324 if ((ret
= RegCreateKeyExW(HKEY_CURRENT_USER
, path
, 0, NULL
, 0, 0, NULL
, &parent
, NULL
)))
325 return HRESULT_FROM_WIN32(ret
);
327 ret
= RegCreateKeyExW(parent
, moniker
->name
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
);
330 return HRESULT_FROM_WIN32(ret
);
335 ret
= RegSetValueExW(key
, name
, 0, REG_SZ
, (BYTE
*)V_BSTR(var
),
336 (wcslen(V_BSTR(var
)) + 1) * sizeof(WCHAR
));
339 ret
= RegSetValueExW(key
, name
, 0, REG_DWORD
, (BYTE
*)&V_I4(var
), sizeof(DWORD
));
341 case VT_ARRAY
| VT_UI1
:
345 SafeArrayGetLBound(V_ARRAY(var
), 1, &lbound
);
346 SafeArrayGetUBound(V_ARRAY(var
), 1, &ubound
);
347 SafeArrayAccessData(V_ARRAY(var
), &array_data
);
348 ret
= RegSetValueExW(key
, name
, 0, REG_BINARY
, array_data
, ubound
- lbound
+ 1);
349 SafeArrayUnaccessData(V_ARRAY(var
));
353 WARN("Unhandled type %s.\n", debugstr_vt(V_VT(var
)));
361 static const IPropertyBagVtbl IPropertyBag_Vtbl
=
363 property_bag_QueryInterface
,
365 property_bag_Release
,
370 static inline struct moniker
*impl_from_IMoniker(IMoniker
*iface
)
372 return CONTAINING_RECORD(iface
, struct moniker
, IMoniker_iface
);
375 static HRESULT WINAPI
moniker_QueryInterface(IMoniker
*iface
, REFIID riid
, void **ppv
)
377 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid
));
382 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
383 IsEqualGUID(riid
, &IID_IPersist
) ||
384 IsEqualGUID(riid
, &IID_IPersistStream
) ||
385 IsEqualGUID(riid
, &IID_IMoniker
))
388 IMoniker_AddRef(iface
);
392 FIXME("- no interface IID: %s\n", debugstr_guid(riid
));
394 return E_NOINTERFACE
;
397 static ULONG WINAPI
moniker_AddRef(IMoniker
*iface
)
399 struct moniker
*moniker
= impl_from_IMoniker(iface
);
400 ULONG refcount
= InterlockedIncrement(&moniker
->ref
);
402 TRACE("%p increasing refcount to %lu.\n", moniker
, refcount
);
407 static ULONG WINAPI
moniker_Release(IMoniker
*iface
)
409 struct moniker
*This
= impl_from_IMoniker(iface
);
410 ULONG refcount
= InterlockedDecrement(&This
->ref
);
412 TRACE("%p decreasing refcount to %lu.\n", This
, refcount
);
422 static HRESULT WINAPI
moniker_GetClassID(IMoniker
*iface
, CLSID
*pClassID
)
424 struct moniker
*This
= impl_from_IMoniker(iface
);
426 TRACE("(%p)->(%p)\n", This
, pClassID
);
428 if (pClassID
== NULL
)
431 *pClassID
= CLSID_CDeviceMoniker
;
436 static HRESULT WINAPI
moniker_IsDirty(IMoniker
*iface
)
438 FIXME("(%p)->(): stub\n", iface
);
443 static HRESULT WINAPI
moniker_Load(IMoniker
*iface
, IStream
*pStm
)
445 FIXME("(%p)->(%p): stub\n", iface
, pStm
);
450 static HRESULT WINAPI
moniker_Save(IMoniker
*iface
, IStream
*pStm
, BOOL fClearDirty
)
452 FIXME("(%p)->(%p, %s): stub\n", iface
, pStm
, fClearDirty
? "true" : "false");
454 return STG_E_CANTSAVE
;
457 static HRESULT WINAPI
moniker_GetSizeMax(IMoniker
*iface
, ULARGE_INTEGER
*pcbSize
)
459 FIXME("(%p)->(%p): stub\n", iface
, pcbSize
);
461 ZeroMemory(pcbSize
, sizeof(*pcbSize
));
466 static HRESULT WINAPI
moniker_BindToObject(IMoniker
*iface
, IBindCtx
*bind_ctx
,
467 IMoniker
*left
, REFIID iid
, void **out
)
469 struct moniker
*moniker
= impl_from_IMoniker(iface
);
470 IPersistPropertyBag
*persist_bag
;
476 TRACE("moniker %p, bind_ctx %p, left %p, iid %s, out %p.\n",
477 moniker
, bind_ctx
, left
, debugstr_guid(iid
), out
);
484 if (moniker
->type
== DEVICE_DMO
)
486 IDMOWrapperFilter
*wrapper
;
488 if (FAILED(hr
= CoCreateInstance(&CLSID_DMOWrapperFilter
, NULL
,
489 CLSCTX_INPROC_SERVER
, &IID_IDMOWrapperFilter
, (void **)&wrapper
)))
492 if (SUCCEEDED(hr
= IDMOWrapperFilter_Init(wrapper
, &moniker
->clsid
, &moniker
->class)))
494 hr
= IDMOWrapperFilter_QueryInterface(wrapper
, iid
, out
);
496 IDMOWrapperFilter_Release(wrapper
);
501 V_VT(&var
) = VT_BSTR
;
502 if (FAILED(hr
= IPropertyBag_Read(&moniker
->IPropertyBag_iface
, L
"CLSID", &var
, NULL
)))
505 hr
= CLSIDFromString(V_BSTR(&var
), &clsid
);
510 if (FAILED(hr
= CoCreateInstance(&clsid
, NULL
, CLSCTX_ALL
, &IID_IUnknown
, (void **)&unk
)))
513 if (SUCCEEDED(IUnknown_QueryInterface(unk
, &IID_IPersistPropertyBag
, (void **)&persist_bag
)))
515 hr
= IPersistPropertyBag_Load(persist_bag
, &moniker
->IPropertyBag_iface
, NULL
);
516 IPersistPropertyBag_Release(persist_bag
);
520 hr
= IUnknown_QueryInterface(unk
, iid
, out
);
522 IUnknown_Release(unk
);
527 static HRESULT WINAPI
moniker_BindToStorage(IMoniker
*iface
, IBindCtx
*pbc
,
528 IMoniker
*pmkToLeft
, REFIID riid
, void **out
)
530 struct moniker
*moniker
= impl_from_IMoniker(iface
);
532 TRACE("moniker %p, left %p, iid %s, out %p.\n", moniker
, pmkToLeft
, debugstr_guid(riid
), out
);
537 return MK_E_NOSTORAGE
;
541 static DWORD reported
;
544 FIXME("ignoring IBindCtx %p\n", pbc
);
549 if (IsEqualGUID(riid
, &IID_IPropertyBag
))
551 *out
= &moniker
->IPropertyBag_iface
;
552 IPropertyBag_AddRef(&moniker
->IPropertyBag_iface
);
556 return MK_E_NOSTORAGE
;
559 static HRESULT WINAPI
moniker_Reduce(IMoniker
*iface
, IBindCtx
*pbc
,
560 DWORD dwReduceHowFar
, IMoniker
**ppmkToLeft
, IMoniker
**ppmkReduced
)
562 struct moniker
*moniker
= impl_from_IMoniker(iface
);
564 TRACE("moniker %p, bind_ctx %p, how_far %#lx, left %p, reduced %p.\n",
565 moniker
, pbc
, dwReduceHowFar
, ppmkToLeft
, ppmkReduced
);
569 *ppmkReduced
= iface
;
571 return MK_S_REDUCED_TO_SELF
;
574 static HRESULT WINAPI
moniker_ComposeWith(IMoniker
*iface
, IMoniker
*pmkRight
,
575 BOOL fOnlyIfNotGeneric
, IMoniker
**ppmkComposite
)
577 FIXME("(%p)->(%p, %s, %p): stub\n", iface
, pmkRight
, fOnlyIfNotGeneric
? "true" : "false", ppmkComposite
);
579 /* FIXME: use CreateGenericComposite? */
580 *ppmkComposite
= NULL
;
585 static HRESULT WINAPI
moniker_Enum(IMoniker
*iface
, BOOL fForward
,
586 IEnumMoniker
**ppenumMoniker
)
588 FIXME("(%p)->(%s, %p): stub\n", iface
, fForward
? "true" : "false", ppenumMoniker
);
590 *ppenumMoniker
= NULL
;
595 static HRESULT WINAPI
moniker_IsEqual(IMoniker
*iface
, IMoniker
*pmkOtherMoniker
)
598 LPOLESTR this_name
, other_name
;
602 TRACE("(%p)->(%p)\n", iface
, pmkOtherMoniker
);
604 if (!pmkOtherMoniker
)
607 IMoniker_GetClassID(pmkOtherMoniker
, &clsid
);
608 if (!IsEqualCLSID(&clsid
, &CLSID_CDeviceMoniker
))
611 res
= CreateBindCtx(0, &bind
);
616 if (SUCCEEDED(IMoniker_GetDisplayName(iface
, bind
, NULL
, &this_name
)) &&
617 SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker
, bind
, NULL
, &other_name
)))
619 int result
= wcsicmp(this_name
, other_name
);
620 CoTaskMemFree(this_name
);
621 CoTaskMemFree(other_name
);
625 IBindCtx_Release(bind
);
629 static HRESULT WINAPI
moniker_Hash(IMoniker
*iface
, DWORD
*pdwHash
)
631 TRACE("(%p)->(%p)\n", iface
, pdwHash
);
638 static HRESULT WINAPI
moniker_IsRunning(IMoniker
*iface
, IBindCtx
*pbc
,
639 IMoniker
*pmkToLeft
, IMoniker
*pmkNewlyRunning
)
641 FIXME("(%p)->(%p, %p, %p): stub\n", iface
, pbc
, pmkToLeft
, pmkNewlyRunning
);
646 static HRESULT WINAPI
moniker_GetTimeOfLastChange(IMoniker
*iface
, IBindCtx
*pbc
,
647 IMoniker
*pmkToLeft
, FILETIME
*pFileTime
)
649 TRACE("(%p)->(%p, %p, %p)\n", iface
, pbc
, pmkToLeft
, pFileTime
);
651 pFileTime
->dwLowDateTime
= 0xFFFFFFFF;
652 pFileTime
->dwHighDateTime
= 0x7FFFFFFF;
654 return MK_E_UNAVAILABLE
;
657 static HRESULT WINAPI
moniker_Inverse(IMoniker
*iface
, IMoniker
**ppmk
)
659 TRACE("(%p)->(%p)\n", iface
, ppmk
);
663 return MK_E_NOINVERSE
;
666 static HRESULT WINAPI
moniker_CommonPrefixWith(IMoniker
*iface
,
667 IMoniker
*pmkOtherMoniker
, IMoniker
**ppmkPrefix
)
669 TRACE("(%p)->(%p, %p)\n", iface
, pmkOtherMoniker
, ppmkPrefix
);
673 return MK_E_NOPREFIX
;
676 static HRESULT WINAPI
moniker_RelativePathTo(IMoniker
*iface
, IMoniker
*pmkOther
,
677 IMoniker
**ppmkRelPath
)
679 TRACE("(%p)->(%p, %p)\n", iface
, pmkOther
, ppmkRelPath
);
681 *ppmkRelPath
= pmkOther
;
686 static HRESULT WINAPI
moniker_GetDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
687 IMoniker
*pmkToLeft
, LPOLESTR
*ppszDisplayName
)
689 struct moniker
*This
= impl_from_IMoniker(iface
);
692 TRACE("(%p)->(%p, %p, %p)\n", iface
, pbc
, pmkToLeft
, ppszDisplayName
);
694 *ppszDisplayName
= NULL
;
696 if (This
->type
== DEVICE_DMO
)
698 buffer
= CoTaskMemAlloc((12 + 2 * CHARS_IN_GUID
+ 1) * sizeof(WCHAR
));
699 if (!buffer
) return E_OUTOFMEMORY
;
701 wcscpy(buffer
, L
"@device:dmo:");
702 StringFromGUID2(&This
->clsid
, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
703 StringFromGUID2(&This
->class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
707 buffer
= CoTaskMemAlloc((11 + (This
->has_class
? CHARS_IN_GUID
: 0)
708 + wcslen(This
->name
) + 1) * sizeof(WCHAR
));
709 if (!buffer
) return E_OUTOFMEMORY
;
711 if (This
->type
== DEVICE_FILTER
)
712 wcscpy(buffer
, L
"@device:sw:");
713 else if (This
->type
== DEVICE_CODEC
)
714 wcscpy(buffer
, L
"@device:cm:");
718 StringFromGUID2(&This
->class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
719 wcscat(buffer
, L
"\\");
721 wcscat(buffer
, This
->name
);
724 *ppszDisplayName
= buffer
;
728 static HRESULT WINAPI
moniker_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
729 IMoniker
*pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
*pchEaten
, IMoniker
**ppmkOut
)
731 FIXME("(%p)->(%p, %p, %s, %p, %p)\n", iface
, pbc
, pmkToLeft
, debugstr_w(pszDisplayName
), pchEaten
, ppmkOut
);
739 static HRESULT WINAPI
moniker_IsSystemMoniker(IMoniker
*iface
, DWORD
*pdwMksys
)
741 TRACE("(%p)->(%p)\n", iface
, pdwMksys
);
746 static const IMonikerVtbl IMoniker_Vtbl
=
748 moniker_QueryInterface
,
756 moniker_BindToObject
,
757 moniker_BindToStorage
,
764 moniker_GetTimeOfLastChange
,
766 moniker_CommonPrefixWith
,
767 moniker_RelativePathTo
,
768 moniker_GetDisplayName
,
769 moniker_ParseDisplayName
,
770 moniker_IsSystemMoniker
,
773 struct moniker
*filter_moniker_create(const GUID
*class, const WCHAR
*name
)
775 struct moniker
*object
;
777 if (!(object
= calloc(1, sizeof(*object
))))
780 object
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
781 object
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
783 object
->type
= DEVICE_FILTER
;
785 object
->class = *class;
786 object
->has_class
= !!class;
787 object
->name
= wcsdup(name
);
792 struct moniker
*codec_moniker_create(const GUID
*class, const WCHAR
*name
)
794 struct moniker
*object
;
796 if (!(object
= calloc(1, sizeof(*object
))))
799 object
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
800 object
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
802 object
->type
= DEVICE_CODEC
;
804 object
->class = *class;
805 object
->has_class
= !!class;
806 object
->name
= wcsdup(name
);
811 struct moniker
*dmo_moniker_create(const GUID
class, const GUID clsid
)
813 struct moniker
*object
;
815 if (!(object
= calloc(1, sizeof(*object
))))
818 object
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
819 object
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
821 object
->type
= DEVICE_DMO
;
822 object
->class = class;
823 object
->clsid
= clsid
;
828 static inline EnumMonikerImpl
*impl_from_IEnumMoniker(IEnumMoniker
*iface
)
830 return CONTAINING_RECORD(iface
, EnumMonikerImpl
, IEnumMoniker_iface
);
833 static HRESULT WINAPI
enum_moniker_QueryInterface(IEnumMoniker
*iface
, REFIID riid
, void **ppv
)
835 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
840 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
841 IsEqualGUID(riid
, &IID_IEnumMoniker
))
844 IEnumMoniker_AddRef(iface
);
848 FIXME("- no interface IID: %s\n", debugstr_guid(riid
));
850 return E_NOINTERFACE
;
853 static ULONG WINAPI
enum_moniker_AddRef(IEnumMoniker
*iface
)
855 EnumMonikerImpl
*enumerator
= impl_from_IEnumMoniker(iface
);
856 ULONG refcount
= InterlockedIncrement(&enumerator
->ref
);
858 TRACE("%p increasing refcount to %lu.\n", enumerator
, refcount
);
863 static ULONG WINAPI
enum_moniker_Release(IEnumMoniker
*iface
)
865 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
866 ULONG refcount
= InterlockedDecrement(&This
->ref
);
868 TRACE("%p decreasing refcount to %lu.\n", This
, refcount
);
873 IEnumDMO_Release(This
->dmo_enum
);
875 IEnumDMO_Release(This
->dmo_enum2
);
876 RegCloseKey(This
->sw_key
);
877 RegCloseKey(This
->cm_key
);
884 static struct moniker
*get_dmo_moniker(EnumMonikerImpl
*enum_moniker
)
888 if (IsEqualGUID(&enum_moniker
->class, &CLSID_LegacyAmFilterCategory
))
890 if (enum_moniker
->dmo_enum
&& IEnumDMO_Next(enum_moniker
->dmo_enum
, 1, &clsid
, NULL
, NULL
) == S_OK
)
891 return dmo_moniker_create(DMOCATEGORY_AUDIO_DECODER
, clsid
);
892 if (enum_moniker
->dmo_enum2
&& IEnumDMO_Next(enum_moniker
->dmo_enum2
, 1, &clsid
, NULL
, NULL
) == S_OK
)
893 return dmo_moniker_create(DMOCATEGORY_VIDEO_DECODER
, clsid
);
897 if (enum_moniker
->dmo_enum
&& IEnumDMO_Next(enum_moniker
->dmo_enum
, 1, &clsid
, NULL
, NULL
) == S_OK
)
898 return dmo_moniker_create(enum_moniker
->class, clsid
);
904 static HRESULT WINAPI
enum_moniker_Next(IEnumMoniker
*iface
, ULONG celt
, IMoniker
**rgelt
,
907 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
908 WCHAR buffer
[MAX_PATH
+ 1];
909 struct moniker
*moniker
;
914 TRACE("enumerator %p, count %lu, monikers %p, ret_count %p.\n", This
, celt
, rgelt
, pceltFetched
);
916 while (fetched
< celt
)
918 /* FIXME: try PNP devices first */
921 if ((moniker
= get_dmo_moniker(This
)))
923 /* try DirectShow filters */
924 else if (!(res
= RegEnumKeyW(This
->sw_key
, This
->sw_index
, buffer
, ARRAY_SIZE(buffer
))))
927 if ((res
= RegOpenKeyExW(This
->sw_key
, buffer
, 0, KEY_QUERY_VALUE
, &hkey
)))
930 moniker
= filter_moniker_create(&This
->class, buffer
);
932 /* then try codecs */
933 else if (!(res
= RegEnumKeyW(This
->cm_key
, This
->cm_index
, buffer
, ARRAY_SIZE(buffer
))))
937 if ((res
= RegOpenKeyExW(This
->cm_key
, buffer
, 0, KEY_QUERY_VALUE
, &hkey
)))
940 moniker
= codec_moniker_create(&This
->class, buffer
);
946 return E_OUTOFMEMORY
;
948 rgelt
[fetched
++] = &moniker
->IMoniker_iface
;
951 TRACE("Returning %lu monikers.\n", fetched
);
954 *pceltFetched
= fetched
;
962 static HRESULT WINAPI
enum_moniker_Skip(IEnumMoniker
*iface
, ULONG celt
)
964 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
966 TRACE("enumerator %p, count %lu.\n", This
, celt
);
970 /* FIXME: try PNP devices first */
973 if (This
->dmo_enum
&& IEnumDMO_Skip(This
->dmo_enum
, 1) == S_OK
)
975 else if (This
->dmo_enum2
&& IEnumDMO_Skip(This
->dmo_enum2
, 1) == S_OK
)
977 /* try DirectShow filters */
978 else if (RegEnumKeyW(This
->sw_key
, This
->sw_index
, NULL
, 0) != ERROR_NO_MORE_ITEMS
)
982 /* then try codecs */
983 else if (RegEnumKeyW(This
->cm_key
, This
->cm_index
, NULL
, 0) != ERROR_NO_MORE_ITEMS
)
994 static HRESULT WINAPI
enum_moniker_Reset(IEnumMoniker
*iface
)
996 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
998 TRACE("(%p)->()\n", iface
);
1001 IEnumDMO_Reset(This
->dmo_enum
);
1002 if (This
->dmo_enum2
)
1003 IEnumDMO_Reset(This
->dmo_enum2
);
1010 static HRESULT WINAPI
enum_moniker_Clone(IEnumMoniker
*iface
, IEnumMoniker
**ppenum
)
1012 FIXME("(%p)->(%p): stub\n", iface
, ppenum
);
1017 /**********************************************************************
1020 static const IEnumMonikerVtbl IEnumMoniker_Vtbl
=
1022 enum_moniker_QueryInterface
,
1023 enum_moniker_AddRef
,
1024 enum_moniker_Release
,
1031 HRESULT
enum_moniker_create(REFCLSID
class, IEnumMoniker
**out
)
1033 EnumMonikerImpl
*object
;
1036 if (!(object
= calloc(1, sizeof(*object
))))
1037 return E_OUTOFMEMORY
;
1039 object
->IEnumMoniker_iface
.lpVtbl
= &IEnumMoniker_Vtbl
;
1041 object
->class = *class;
1043 wcscpy(buffer
, L
"CLSID\\");
1044 StringFromGUID2(class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
1045 wcscat(buffer
, L
"\\Instance");
1046 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, buffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &object
->sw_key
))
1047 object
->sw_key
= NULL
;
1049 wcscpy(buffer
, L
"Software\\Microsoft\\ActiveMovie\\devenum\\");
1050 StringFromGUID2(class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
1051 if (RegOpenKeyExW(HKEY_CURRENT_USER
, buffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &object
->cm_key
))
1052 object
->cm_key
= NULL
;
1054 if (IsEqualGUID(class, &CLSID_LegacyAmFilterCategory
))
1056 if (FAILED(DMOEnum(&DMOCATEGORY_AUDIO_DECODER
, 0, 0, NULL
, 0, NULL
, &object
->dmo_enum
)))
1057 object
->dmo_enum
= NULL
;
1058 if (FAILED(DMOEnum(&DMOCATEGORY_VIDEO_DECODER
, 0, 0, NULL
, 0, NULL
, &object
->dmo_enum2
)))
1059 object
->dmo_enum2
= NULL
;
1063 if (FAILED(DMOEnum(class, 0, 0, NULL
, 0, NULL
, &object
->dmo_enum
)))
1064 object
->dmo_enum
= NULL
;
1067 *out
= &object
->IEnumMoniker_iface
;