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 REGFILTERPINS2 reg_pins
[2] = {{0}};
141 REGFILTER2 reg_filter
=
144 .dwMerit
= MERIT_NORMAL
+ 0x800,
149 unsigned int count
= 1, input_count
, output_count
, i
;
150 DMO_PARTIAL_MEDIATYPE
*types
= NULL
;
151 REGPINTYPES
*reg_types
;
154 if (!(types
= malloc(2 * count
* sizeof(*types
))))
155 return E_OUTOFMEMORY
;
157 while ((hr
= DMOGetTypes(&moniker
->clsid
, count
, &input_count
, types
,
158 count
, &output_count
, types
+ count
)) == S_FALSE
)
161 if (!(types
= realloc(types
, count
* sizeof(*types
))))
164 return E_OUTOFMEMORY
;
173 if (!(reg_types
= malloc(2 * count
* sizeof(*reg_types
))))
179 for (i
= 0; i
< input_count
; ++i
)
181 reg_types
[i
].clsMajorType
= &types
[i
].type
;
182 reg_types
[i
].clsMinorType
= &types
[i
].subtype
;
184 for (i
= 0; i
< output_count
; ++i
)
186 reg_types
[count
+ i
].clsMajorType
= &types
[count
+ i
].type
;
187 reg_types
[count
+ i
].clsMinorType
= &types
[count
+ i
].subtype
;
189 reg_pins
[0].cInstances
= 1;
190 reg_pins
[0].nMediaTypes
= input_count
;
191 reg_pins
[0].lpMediaType
= reg_types
;
192 reg_pins
[1].dwFlags
= REG_PINFLAG_B_OUTPUT
;
193 reg_pins
[1].cInstances
= 1;
194 reg_pins
[1].nMediaTypes
= output_count
;
195 reg_pins
[1].lpMediaType
= reg_types
+ count
;
197 hr
= create_filter_data(var
, ®_filter
);
202 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND
);
205 if (moniker
->type
== DEVICE_FILTER
)
207 wcscpy(path
, L
"CLSID\\");
208 if (moniker
->has_class
)
210 StringFromGUID2(&moniker
->class, path
+ wcslen(path
), CHARS_IN_GUID
);
211 wcscat(path
, L
"\\Instance");
213 if ((ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, path
, 0, 0, &parent
)))
214 return HRESULT_FROM_WIN32(ret
);
216 else if (moniker
->type
== DEVICE_CODEC
)
218 wcscpy(path
, L
"Software\\Microsoft\\ActiveMovie\\devenum\\");
219 if (moniker
->has_class
)
220 StringFromGUID2(&moniker
->class, path
+ wcslen(path
), CHARS_IN_GUID
);
221 if ((ret
= RegOpenKeyExW(HKEY_CURRENT_USER
, path
, 0, 0, &parent
)))
222 return HRESULT_FROM_WIN32(ret
);
224 ret
= RegOpenKeyExW(parent
, moniker
->name
, 0, KEY_READ
, &key
);
227 return HRESULT_FROM_WIN32(ret
);
229 if ((ret
= RegQueryValueExW(key
, name
, NULL
, NULL
, NULL
, &size
)))
232 return HRESULT_FROM_WIN32(ret
);
236 if ((ret
= RegQueryValueExW(key
, name
, NULL
, &type
, data
, &size
)))
240 return HRESULT_FROM_WIN32(ret
);
247 if (V_VT(var
) == VT_EMPTY
)
249 if (V_VT(var
) != VT_BSTR
)
251 WARN("Invalid type %s.\n", debugstr_vt(V_VT(var
)));
254 V_BSTR(var
) = SysAllocStringLen(data
, size
/ sizeof(WCHAR
) - 1);
258 if (V_VT(var
) == VT_EMPTY
)
260 if (V_VT(var
) != VT_I4
)
262 WARN("Invalid type %s.\n", debugstr_vt(V_VT(var
)));
265 V_I4(var
) = *(DWORD
*)data
;
270 SAFEARRAYBOUND bound
= {.cElements
= size
};
273 if (V_VT(var
) == VT_EMPTY
)
274 V_VT(var
) = VT_ARRAY
| VT_UI1
;
275 if (V_VT(var
) != (VT_ARRAY
| VT_UI1
))
277 WARN("Invalid type %s.\n", debugstr_vt(V_VT(var
)));
281 if (!(V_ARRAY(var
) = SafeArrayCreate(VT_UI1
, 1, &bound
)))
284 return E_OUTOFMEMORY
;
287 SafeArrayAccessData(V_ARRAY(var
), &array_data
);
288 memcpy(array_data
, data
, size
);
289 SafeArrayUnaccessData(V_ARRAY(var
));
294 FIXME("Unhandled type %#x.\n", type
);
300 static HRESULT WINAPI
property_bag_Write(IPropertyBag
*iface
, const WCHAR
*name
, VARIANT
*var
)
302 struct moniker
*moniker
= impl_from_IPropertyBag(iface
);
307 TRACE("moniker %p, name %s, var %s.\n", moniker
, debugstr_w(name
), debugstr_variant(var
));
309 if (moniker
->type
== DEVICE_DMO
)
310 return E_ACCESSDENIED
;
312 if (moniker
->type
== DEVICE_FILTER
)
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
);
323 else if (moniker
->type
== DEVICE_CODEC
)
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
);
331 ret
= RegCreateKeyExW(parent
, moniker
->name
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
);
334 return HRESULT_FROM_WIN32(ret
);
339 ret
= RegSetValueExW(key
, name
, 0, REG_SZ
, (BYTE
*)V_BSTR(var
),
340 (wcslen(V_BSTR(var
)) + 1) * sizeof(WCHAR
));
343 ret
= RegSetValueExW(key
, name
, 0, REG_DWORD
, (BYTE
*)&V_I4(var
), sizeof(DWORD
));
345 case VT_ARRAY
| VT_UI1
:
349 SafeArrayGetLBound(V_ARRAY(var
), 1, &lbound
);
350 SafeArrayGetUBound(V_ARRAY(var
), 1, &ubound
);
351 SafeArrayAccessData(V_ARRAY(var
), &array_data
);
352 ret
= RegSetValueExW(key
, name
, 0, REG_BINARY
, array_data
, ubound
- lbound
+ 1);
353 SafeArrayUnaccessData(V_ARRAY(var
));
357 WARN("Unhandled type %s.\n", debugstr_vt(V_VT(var
)));
365 static const IPropertyBagVtbl IPropertyBag_Vtbl
=
367 property_bag_QueryInterface
,
369 property_bag_Release
,
374 static inline struct moniker
*impl_from_IMoniker(IMoniker
*iface
)
376 return CONTAINING_RECORD(iface
, struct moniker
, IMoniker_iface
);
379 static HRESULT WINAPI
moniker_QueryInterface(IMoniker
*iface
, REFIID riid
, void **ppv
)
381 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid
));
386 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
387 IsEqualGUID(riid
, &IID_IPersist
) ||
388 IsEqualGUID(riid
, &IID_IPersistStream
) ||
389 IsEqualGUID(riid
, &IID_IMoniker
))
392 IMoniker_AddRef(iface
);
396 FIXME("- no interface IID: %s\n", debugstr_guid(riid
));
398 return E_NOINTERFACE
;
401 static ULONG WINAPI
moniker_AddRef(IMoniker
*iface
)
403 struct moniker
*This
= impl_from_IMoniker(iface
);
404 ULONG ref
= InterlockedIncrement(&This
->ref
);
406 TRACE("(%p) ref=%d\n", This
, ref
);
411 static ULONG WINAPI
moniker_Release(IMoniker
*iface
)
413 struct moniker
*This
= impl_from_IMoniker(iface
);
414 ULONG ref
= InterlockedDecrement(&This
->ref
);
416 TRACE("(%p) ref=%d\n", This
, ref
);
421 DEVENUM_UnlockModule();
426 static HRESULT WINAPI
moniker_GetClassID(IMoniker
*iface
, CLSID
*pClassID
)
428 struct moniker
*This
= impl_from_IMoniker(iface
);
430 TRACE("(%p)->(%p)\n", This
, pClassID
);
432 if (pClassID
== NULL
)
435 *pClassID
= CLSID_CDeviceMoniker
;
440 static HRESULT WINAPI
moniker_IsDirty(IMoniker
*iface
)
442 FIXME("(%p)->(): stub\n", iface
);
447 static HRESULT WINAPI
moniker_Load(IMoniker
*iface
, IStream
*pStm
)
449 FIXME("(%p)->(%p): stub\n", iface
, pStm
);
454 static HRESULT WINAPI
moniker_Save(IMoniker
*iface
, IStream
*pStm
, BOOL fClearDirty
)
456 FIXME("(%p)->(%p, %s): stub\n", iface
, pStm
, fClearDirty
? "true" : "false");
458 return STG_E_CANTSAVE
;
461 static HRESULT WINAPI
moniker_GetSizeMax(IMoniker
*iface
, ULARGE_INTEGER
*pcbSize
)
463 FIXME("(%p)->(%p): stub\n", iface
, pcbSize
);
465 ZeroMemory(pcbSize
, sizeof(*pcbSize
));
470 static HRESULT WINAPI
moniker_BindToObject(IMoniker
*iface
, IBindCtx
*bind_ctx
,
471 IMoniker
*left
, REFIID iid
, void **out
)
473 struct moniker
*moniker
= impl_from_IMoniker(iface
);
474 IPersistPropertyBag
*persist_bag
;
480 TRACE("moniker %p, bind_ctx %p, left %p, iid %s, out %p.\n",
481 moniker
, bind_ctx
, left
, debugstr_guid(iid
), out
);
488 if (moniker
->type
== DEVICE_DMO
)
490 IDMOWrapperFilter
*wrapper
;
492 if (FAILED(hr
= CoCreateInstance(&CLSID_DMOWrapperFilter
, NULL
,
493 CLSCTX_INPROC_SERVER
, &IID_IDMOWrapperFilter
, (void **)&wrapper
)))
496 if (SUCCEEDED(hr
= IDMOWrapperFilter_Init(wrapper
, &moniker
->clsid
, &moniker
->class)))
498 hr
= IDMOWrapperFilter_QueryInterface(wrapper
, iid
, out
);
500 IDMOWrapperFilter_Release(wrapper
);
505 V_VT(&var
) = VT_BSTR
;
506 if (FAILED(hr
= IPropertyBag_Read(&moniker
->IPropertyBag_iface
, L
"CLSID", &var
, NULL
)))
509 hr
= CLSIDFromString(V_BSTR(&var
), &clsid
);
514 if (FAILED(hr
= CoCreateInstance(&clsid
, NULL
, CLSCTX_ALL
, &IID_IUnknown
, (void **)&unk
)))
517 if (SUCCEEDED(IUnknown_QueryInterface(unk
, &IID_IPersistPropertyBag
, (void **)&persist_bag
)))
519 hr
= IPersistPropertyBag_Load(persist_bag
, &moniker
->IPropertyBag_iface
, NULL
);
520 IPersistPropertyBag_Release(persist_bag
);
524 hr
= IUnknown_QueryInterface(unk
, iid
, out
);
526 IUnknown_Release(unk
);
531 static HRESULT WINAPI
moniker_BindToStorage(IMoniker
*iface
, IBindCtx
*pbc
,
532 IMoniker
*pmkToLeft
, REFIID riid
, void **out
)
534 struct moniker
*moniker
= impl_from_IMoniker(iface
);
536 TRACE("moniker %p, left %p, iid %s, out %p.\n", moniker
, pmkToLeft
, debugstr_guid(riid
), out
);
541 return MK_E_NOSTORAGE
;
545 static DWORD reported
;
548 FIXME("ignoring IBindCtx %p\n", pbc
);
553 if (IsEqualGUID(riid
, &IID_IPropertyBag
))
555 *out
= &moniker
->IPropertyBag_iface
;
556 IPropertyBag_AddRef(&moniker
->IPropertyBag_iface
);
560 return MK_E_NOSTORAGE
;
563 static HRESULT WINAPI
moniker_Reduce(IMoniker
*iface
, IBindCtx
*pbc
,
564 DWORD dwReduceHowFar
, IMoniker
**ppmkToLeft
, IMoniker
**ppmkReduced
)
566 TRACE("(%p)->(%p, %d, %p, %p)\n", iface
, pbc
, dwReduceHowFar
, ppmkToLeft
, ppmkReduced
);
570 *ppmkReduced
= iface
;
572 return MK_S_REDUCED_TO_SELF
;
575 static HRESULT WINAPI
moniker_ComposeWith(IMoniker
*iface
, IMoniker
*pmkRight
,
576 BOOL fOnlyIfNotGeneric
, IMoniker
**ppmkComposite
)
578 FIXME("(%p)->(%p, %s, %p): stub\n", iface
, pmkRight
, fOnlyIfNotGeneric
? "true" : "false", ppmkComposite
);
580 /* FIXME: use CreateGenericComposite? */
581 *ppmkComposite
= NULL
;
586 static HRESULT WINAPI
moniker_Enum(IMoniker
*iface
, BOOL fForward
,
587 IEnumMoniker
**ppenumMoniker
)
589 FIXME("(%p)->(%s, %p): stub\n", iface
, fForward
? "true" : "false", ppenumMoniker
);
591 *ppenumMoniker
= NULL
;
596 static HRESULT WINAPI
moniker_IsEqual(IMoniker
*iface
, IMoniker
*pmkOtherMoniker
)
599 LPOLESTR this_name
, other_name
;
603 TRACE("(%p)->(%p)\n", iface
, pmkOtherMoniker
);
605 if (!pmkOtherMoniker
)
608 IMoniker_GetClassID(pmkOtherMoniker
, &clsid
);
609 if (!IsEqualCLSID(&clsid
, &CLSID_CDeviceMoniker
))
612 res
= CreateBindCtx(0, &bind
);
617 if (SUCCEEDED(IMoniker_GetDisplayName(iface
, bind
, NULL
, &this_name
)) &&
618 SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker
, bind
, NULL
, &other_name
)))
620 int result
= wcsicmp(this_name
, other_name
);
621 CoTaskMemFree(this_name
);
622 CoTaskMemFree(other_name
);
626 IBindCtx_Release(bind
);
630 static HRESULT WINAPI
moniker_Hash(IMoniker
*iface
, DWORD
*pdwHash
)
632 TRACE("(%p)->(%p)\n", iface
, pdwHash
);
639 static HRESULT WINAPI
moniker_IsRunning(IMoniker
*iface
, IBindCtx
*pbc
,
640 IMoniker
*pmkToLeft
, IMoniker
*pmkNewlyRunning
)
642 FIXME("(%p)->(%p, %p, %p): stub\n", iface
, pbc
, pmkToLeft
, pmkNewlyRunning
);
647 static HRESULT WINAPI
moniker_GetTimeOfLastChange(IMoniker
*iface
, IBindCtx
*pbc
,
648 IMoniker
*pmkToLeft
, FILETIME
*pFileTime
)
650 TRACE("(%p)->(%p, %p, %p)\n", iface
, pbc
, pmkToLeft
, pFileTime
);
652 pFileTime
->dwLowDateTime
= 0xFFFFFFFF;
653 pFileTime
->dwHighDateTime
= 0x7FFFFFFF;
655 return MK_E_UNAVAILABLE
;
658 static HRESULT WINAPI
moniker_Inverse(IMoniker
*iface
, IMoniker
**ppmk
)
660 TRACE("(%p)->(%p)\n", iface
, ppmk
);
664 return MK_E_NOINVERSE
;
667 static HRESULT WINAPI
moniker_CommonPrefixWith(IMoniker
*iface
,
668 IMoniker
*pmkOtherMoniker
, IMoniker
**ppmkPrefix
)
670 TRACE("(%p)->(%p, %p)\n", iface
, pmkOtherMoniker
, ppmkPrefix
);
674 return MK_E_NOPREFIX
;
677 static HRESULT WINAPI
moniker_RelativePathTo(IMoniker
*iface
, IMoniker
*pmkOther
,
678 IMoniker
**ppmkRelPath
)
680 TRACE("(%p)->(%p, %p)\n", iface
, pmkOther
, ppmkRelPath
);
682 *ppmkRelPath
= pmkOther
;
687 static HRESULT WINAPI
moniker_GetDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
688 IMoniker
*pmkToLeft
, LPOLESTR
*ppszDisplayName
)
690 struct moniker
*This
= impl_from_IMoniker(iface
);
693 TRACE("(%p)->(%p, %p, %p)\n", iface
, pbc
, pmkToLeft
, ppszDisplayName
);
695 *ppszDisplayName
= NULL
;
697 if (This
->type
== DEVICE_DMO
)
699 buffer
= CoTaskMemAlloc((12 + 2 * CHARS_IN_GUID
+ 1) * sizeof(WCHAR
));
700 if (!buffer
) return E_OUTOFMEMORY
;
702 wcscpy(buffer
, L
"@device:dmo:");
703 StringFromGUID2(&This
->clsid
, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
704 StringFromGUID2(&This
->class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
708 buffer
= CoTaskMemAlloc((11 + (This
->has_class
? CHARS_IN_GUID
: 0)
709 + wcslen(This
->name
) + 1) * sizeof(WCHAR
));
710 if (!buffer
) return E_OUTOFMEMORY
;
712 if (This
->type
== DEVICE_FILTER
)
713 wcscpy(buffer
, L
"@device:sw:");
714 else if (This
->type
== DEVICE_CODEC
)
715 wcscpy(buffer
, L
"@device:cm:");
719 StringFromGUID2(&This
->class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
720 wcscat(buffer
, L
"\\");
722 wcscat(buffer
, This
->name
);
725 *ppszDisplayName
= buffer
;
729 static HRESULT WINAPI
moniker_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
730 IMoniker
*pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
*pchEaten
, IMoniker
**ppmkOut
)
732 FIXME("(%p)->(%p, %p, %s, %p, %p)\n", iface
, pbc
, pmkToLeft
, debugstr_w(pszDisplayName
), pchEaten
, ppmkOut
);
740 static HRESULT WINAPI
moniker_IsSystemMoniker(IMoniker
*iface
, DWORD
*pdwMksys
)
742 TRACE("(%p)->(%p)\n", iface
, pdwMksys
);
747 static const IMonikerVtbl IMoniker_Vtbl
=
749 moniker_QueryInterface
,
757 moniker_BindToObject
,
758 moniker_BindToStorage
,
765 moniker_GetTimeOfLastChange
,
767 moniker_CommonPrefixWith
,
768 moniker_RelativePathTo
,
769 moniker_GetDisplayName
,
770 moniker_ParseDisplayName
,
771 moniker_IsSystemMoniker
,
774 struct moniker
*filter_moniker_create(const GUID
*class, const WCHAR
*name
)
776 struct moniker
*object
;
778 if (!(object
= calloc(1, sizeof(*object
))))
781 object
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
782 object
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
784 object
->type
= DEVICE_FILTER
;
786 object
->class = *class;
787 object
->has_class
= !!class;
788 object
->name
= wcsdup(name
);
790 DEVENUM_LockModule();
795 struct moniker
*codec_moniker_create(const GUID
*class, const WCHAR
*name
)
797 struct moniker
*object
;
799 if (!(object
= calloc(1, sizeof(*object
))))
802 object
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
803 object
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
805 object
->type
= DEVICE_CODEC
;
807 object
->class = *class;
808 object
->has_class
= !!class;
809 object
->name
= wcsdup(name
);
811 DEVENUM_LockModule();
816 struct moniker
*dmo_moniker_create(const GUID
class, const GUID clsid
)
818 struct moniker
*object
;
820 if (!(object
= calloc(1, sizeof(*object
))))
823 object
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
824 object
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
826 object
->type
= DEVICE_DMO
;
827 object
->class = class;
828 object
->clsid
= clsid
;
830 DEVENUM_LockModule();
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
*This
= impl_from_IEnumMoniker(iface
);
863 ULONG ref
= InterlockedIncrement(&This
->ref
);
865 TRACE("(%p) ref=%d\n", This
, ref
);
870 static ULONG WINAPI
enum_moniker_Release(IEnumMoniker
*iface
)
872 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
873 ULONG ref
= InterlockedDecrement(&This
->ref
);
875 TRACE("(%p) ref=%d\n", This
, ref
);
880 IEnumDMO_Release(This
->dmo_enum
);
882 IEnumDMO_Release(This
->dmo_enum2
);
883 RegCloseKey(This
->sw_key
);
884 RegCloseKey(This
->cm_key
);
886 DEVENUM_UnlockModule();
892 static struct moniker
*get_dmo_moniker(EnumMonikerImpl
*enum_moniker
)
896 if (IsEqualGUID(&enum_moniker
->class, &CLSID_LegacyAmFilterCategory
))
898 if (enum_moniker
->dmo_enum
&& IEnumDMO_Next(enum_moniker
->dmo_enum
, 1, &clsid
, NULL
, NULL
) == S_OK
)
899 return dmo_moniker_create(DMOCATEGORY_AUDIO_DECODER
, clsid
);
900 if (enum_moniker
->dmo_enum2
&& IEnumDMO_Next(enum_moniker
->dmo_enum2
, 1, &clsid
, NULL
, NULL
) == S_OK
)
901 return dmo_moniker_create(DMOCATEGORY_VIDEO_DECODER
, clsid
);
905 if (enum_moniker
->dmo_enum
&& IEnumDMO_Next(enum_moniker
->dmo_enum
, 1, &clsid
, NULL
, NULL
) == S_OK
)
906 return dmo_moniker_create(enum_moniker
->class, clsid
);
912 static HRESULT WINAPI
enum_moniker_Next(IEnumMoniker
*iface
, ULONG celt
, IMoniker
**rgelt
,
915 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
916 WCHAR buffer
[MAX_PATH
+ 1];
917 struct moniker
*moniker
;
922 TRACE("(%p)->(%d, %p, %p)\n", iface
, celt
, rgelt
, pceltFetched
);
924 while (fetched
< celt
)
926 /* FIXME: try PNP devices first */
929 if ((moniker
= get_dmo_moniker(This
)))
931 /* try DirectShow filters */
932 else if (!(res
= RegEnumKeyW(This
->sw_key
, This
->sw_index
, buffer
, ARRAY_SIZE(buffer
))))
935 if ((res
= RegOpenKeyExW(This
->sw_key
, buffer
, 0, KEY_QUERY_VALUE
, &hkey
)))
938 moniker
= filter_moniker_create(&This
->class, buffer
);
940 /* then try codecs */
941 else if (!(res
= RegEnumKeyW(This
->cm_key
, This
->cm_index
, buffer
, ARRAY_SIZE(buffer
))))
945 if ((res
= RegOpenKeyExW(This
->cm_key
, buffer
, 0, KEY_QUERY_VALUE
, &hkey
)))
948 moniker
= codec_moniker_create(&This
->class, buffer
);
954 return E_OUTOFMEMORY
;
956 rgelt
[fetched
++] = &moniker
->IMoniker_iface
;
959 TRACE("-- fetched %d\n", fetched
);
962 *pceltFetched
= fetched
;
970 static HRESULT WINAPI
enum_moniker_Skip(IEnumMoniker
*iface
, ULONG celt
)
972 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
974 TRACE("(%p)->(%d)\n", iface
, celt
);
978 /* FIXME: try PNP devices first */
981 if (This
->dmo_enum
&& IEnumDMO_Skip(This
->dmo_enum
, 1) == S_OK
)
983 else if (This
->dmo_enum2
&& IEnumDMO_Skip(This
->dmo_enum2
, 1) == S_OK
)
985 /* try DirectShow filters */
986 else if (RegEnumKeyW(This
->sw_key
, This
->sw_index
, NULL
, 0) != ERROR_NO_MORE_ITEMS
)
990 /* then try codecs */
991 else if (RegEnumKeyW(This
->cm_key
, This
->cm_index
, NULL
, 0) != ERROR_NO_MORE_ITEMS
)
1002 static HRESULT WINAPI
enum_moniker_Reset(IEnumMoniker
*iface
)
1004 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1006 TRACE("(%p)->()\n", iface
);
1009 IEnumDMO_Reset(This
->dmo_enum
);
1010 if (This
->dmo_enum2
)
1011 IEnumDMO_Reset(This
->dmo_enum2
);
1018 static HRESULT WINAPI
enum_moniker_Clone(IEnumMoniker
*iface
, IEnumMoniker
**ppenum
)
1020 FIXME("(%p)->(%p): stub\n", iface
, ppenum
);
1025 /**********************************************************************
1028 static const IEnumMonikerVtbl IEnumMoniker_Vtbl
=
1030 enum_moniker_QueryInterface
,
1031 enum_moniker_AddRef
,
1032 enum_moniker_Release
,
1039 HRESULT
enum_moniker_create(REFCLSID
class, IEnumMoniker
**out
)
1041 EnumMonikerImpl
*object
;
1044 if (!(object
= calloc(1, sizeof(*object
))))
1045 return E_OUTOFMEMORY
;
1047 object
->IEnumMoniker_iface
.lpVtbl
= &IEnumMoniker_Vtbl
;
1049 object
->class = *class;
1051 wcscpy(buffer
, L
"CLSID\\");
1052 StringFromGUID2(class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
1053 wcscat(buffer
, L
"\\Instance");
1054 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, buffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &object
->sw_key
))
1055 object
->sw_key
= NULL
;
1057 wcscpy(buffer
, L
"Software\\Microsoft\\ActiveMovie\\devenum\\");
1058 StringFromGUID2(class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
1059 if (RegOpenKeyExW(HKEY_CURRENT_USER
, buffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &object
->cm_key
))
1060 object
->cm_key
= NULL
;
1062 if (IsEqualGUID(class, &CLSID_LegacyAmFilterCategory
))
1064 if (FAILED(DMOEnum(&DMOCATEGORY_AUDIO_DECODER
, 0, 0, NULL
, 0, NULL
, &object
->dmo_enum
)))
1065 object
->dmo_enum
= NULL
;
1066 if (FAILED(DMOEnum(&DMOCATEGORY_VIDEO_DECODER
, 0, 0, NULL
, 0, NULL
, &object
->dmo_enum2
)))
1067 object
->dmo_enum2
= NULL
;
1071 if (FAILED(DMOEnum(class, 0, 0, NULL
, 0, NULL
, &object
->dmo_enum
)))
1072 object
->dmo_enum
= NULL
;
1075 *out
= &object
->IEnumMoniker_iface
;
1077 DEVENUM_LockModule();