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 unsigned int count
= 1, input_count
, output_count
, i
;
141 DMO_PARTIAL_MEDIATYPE
*types
= NULL
, *new_array
;
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 %#x.\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
*This
= impl_from_IMoniker(iface
);
400 ULONG ref
= InterlockedIncrement(&This
->ref
);
402 TRACE("(%p) ref=%d\n", This
, ref
);
407 static ULONG WINAPI
moniker_Release(IMoniker
*iface
)
409 struct moniker
*This
= impl_from_IMoniker(iface
);
410 ULONG ref
= InterlockedDecrement(&This
->ref
);
412 TRACE("(%p) ref=%d\n", This
, ref
);
417 DEVENUM_UnlockModule();
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 TRACE("(%p)->(%p, %d, %p, %p)\n", iface
, pbc
, dwReduceHowFar
, ppmkToLeft
, ppmkReduced
);
566 *ppmkReduced
= iface
;
568 return MK_S_REDUCED_TO_SELF
;
571 static HRESULT WINAPI
moniker_ComposeWith(IMoniker
*iface
, IMoniker
*pmkRight
,
572 BOOL fOnlyIfNotGeneric
, IMoniker
**ppmkComposite
)
574 FIXME("(%p)->(%p, %s, %p): stub\n", iface
, pmkRight
, fOnlyIfNotGeneric
? "true" : "false", ppmkComposite
);
576 /* FIXME: use CreateGenericComposite? */
577 *ppmkComposite
= NULL
;
582 static HRESULT WINAPI
moniker_Enum(IMoniker
*iface
, BOOL fForward
,
583 IEnumMoniker
**ppenumMoniker
)
585 FIXME("(%p)->(%s, %p): stub\n", iface
, fForward
? "true" : "false", ppenumMoniker
);
587 *ppenumMoniker
= NULL
;
592 static HRESULT WINAPI
moniker_IsEqual(IMoniker
*iface
, IMoniker
*pmkOtherMoniker
)
595 LPOLESTR this_name
, other_name
;
599 TRACE("(%p)->(%p)\n", iface
, pmkOtherMoniker
);
601 if (!pmkOtherMoniker
)
604 IMoniker_GetClassID(pmkOtherMoniker
, &clsid
);
605 if (!IsEqualCLSID(&clsid
, &CLSID_CDeviceMoniker
))
608 res
= CreateBindCtx(0, &bind
);
613 if (SUCCEEDED(IMoniker_GetDisplayName(iface
, bind
, NULL
, &this_name
)) &&
614 SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker
, bind
, NULL
, &other_name
)))
616 int result
= wcsicmp(this_name
, other_name
);
617 CoTaskMemFree(this_name
);
618 CoTaskMemFree(other_name
);
622 IBindCtx_Release(bind
);
626 static HRESULT WINAPI
moniker_Hash(IMoniker
*iface
, DWORD
*pdwHash
)
628 TRACE("(%p)->(%p)\n", iface
, pdwHash
);
635 static HRESULT WINAPI
moniker_IsRunning(IMoniker
*iface
, IBindCtx
*pbc
,
636 IMoniker
*pmkToLeft
, IMoniker
*pmkNewlyRunning
)
638 FIXME("(%p)->(%p, %p, %p): stub\n", iface
, pbc
, pmkToLeft
, pmkNewlyRunning
);
643 static HRESULT WINAPI
moniker_GetTimeOfLastChange(IMoniker
*iface
, IBindCtx
*pbc
,
644 IMoniker
*pmkToLeft
, FILETIME
*pFileTime
)
646 TRACE("(%p)->(%p, %p, %p)\n", iface
, pbc
, pmkToLeft
, pFileTime
);
648 pFileTime
->dwLowDateTime
= 0xFFFFFFFF;
649 pFileTime
->dwHighDateTime
= 0x7FFFFFFF;
651 return MK_E_UNAVAILABLE
;
654 static HRESULT WINAPI
moniker_Inverse(IMoniker
*iface
, IMoniker
**ppmk
)
656 TRACE("(%p)->(%p)\n", iface
, ppmk
);
660 return MK_E_NOINVERSE
;
663 static HRESULT WINAPI
moniker_CommonPrefixWith(IMoniker
*iface
,
664 IMoniker
*pmkOtherMoniker
, IMoniker
**ppmkPrefix
)
666 TRACE("(%p)->(%p, %p)\n", iface
, pmkOtherMoniker
, ppmkPrefix
);
670 return MK_E_NOPREFIX
;
673 static HRESULT WINAPI
moniker_RelativePathTo(IMoniker
*iface
, IMoniker
*pmkOther
,
674 IMoniker
**ppmkRelPath
)
676 TRACE("(%p)->(%p, %p)\n", iface
, pmkOther
, ppmkRelPath
);
678 *ppmkRelPath
= pmkOther
;
683 static HRESULT WINAPI
moniker_GetDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
684 IMoniker
*pmkToLeft
, LPOLESTR
*ppszDisplayName
)
686 struct moniker
*This
= impl_from_IMoniker(iface
);
689 TRACE("(%p)->(%p, %p, %p)\n", iface
, pbc
, pmkToLeft
, ppszDisplayName
);
691 *ppszDisplayName
= NULL
;
693 if (This
->type
== DEVICE_DMO
)
695 buffer
= CoTaskMemAlloc((12 + 2 * CHARS_IN_GUID
+ 1) * sizeof(WCHAR
));
696 if (!buffer
) return E_OUTOFMEMORY
;
698 wcscpy(buffer
, L
"@device:dmo:");
699 StringFromGUID2(&This
->clsid
, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
700 StringFromGUID2(&This
->class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
704 buffer
= CoTaskMemAlloc((11 + (This
->has_class
? CHARS_IN_GUID
: 0)
705 + wcslen(This
->name
) + 1) * sizeof(WCHAR
));
706 if (!buffer
) return E_OUTOFMEMORY
;
708 if (This
->type
== DEVICE_FILTER
)
709 wcscpy(buffer
, L
"@device:sw:");
710 else if (This
->type
== DEVICE_CODEC
)
711 wcscpy(buffer
, L
"@device:cm:");
715 StringFromGUID2(&This
->class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
716 wcscat(buffer
, L
"\\");
718 wcscat(buffer
, This
->name
);
721 *ppszDisplayName
= buffer
;
725 static HRESULT WINAPI
moniker_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
726 IMoniker
*pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
*pchEaten
, IMoniker
**ppmkOut
)
728 FIXME("(%p)->(%p, %p, %s, %p, %p)\n", iface
, pbc
, pmkToLeft
, debugstr_w(pszDisplayName
), pchEaten
, ppmkOut
);
736 static HRESULT WINAPI
moniker_IsSystemMoniker(IMoniker
*iface
, DWORD
*pdwMksys
)
738 TRACE("(%p)->(%p)\n", iface
, pdwMksys
);
743 static const IMonikerVtbl IMoniker_Vtbl
=
745 moniker_QueryInterface
,
753 moniker_BindToObject
,
754 moniker_BindToStorage
,
761 moniker_GetTimeOfLastChange
,
763 moniker_CommonPrefixWith
,
764 moniker_RelativePathTo
,
765 moniker_GetDisplayName
,
766 moniker_ParseDisplayName
,
767 moniker_IsSystemMoniker
,
770 struct moniker
*filter_moniker_create(const GUID
*class, const WCHAR
*name
)
772 struct moniker
*object
;
774 if (!(object
= calloc(1, sizeof(*object
))))
777 object
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
778 object
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
780 object
->type
= DEVICE_FILTER
;
782 object
->class = *class;
783 object
->has_class
= !!class;
784 object
->name
= wcsdup(name
);
786 DEVENUM_LockModule();
791 struct moniker
*codec_moniker_create(const GUID
*class, const WCHAR
*name
)
793 struct moniker
*object
;
795 if (!(object
= calloc(1, sizeof(*object
))))
798 object
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
799 object
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
801 object
->type
= DEVICE_CODEC
;
803 object
->class = *class;
804 object
->has_class
= !!class;
805 object
->name
= wcsdup(name
);
807 DEVENUM_LockModule();
812 struct moniker
*dmo_moniker_create(const GUID
class, const GUID clsid
)
814 struct moniker
*object
;
816 if (!(object
= calloc(1, sizeof(*object
))))
819 object
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
820 object
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
822 object
->type
= DEVICE_DMO
;
823 object
->class = class;
824 object
->clsid
= clsid
;
826 DEVENUM_LockModule();
831 static inline EnumMonikerImpl
*impl_from_IEnumMoniker(IEnumMoniker
*iface
)
833 return CONTAINING_RECORD(iface
, EnumMonikerImpl
, IEnumMoniker_iface
);
836 static HRESULT WINAPI
enum_moniker_QueryInterface(IEnumMoniker
*iface
, REFIID riid
, void **ppv
)
838 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
843 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
844 IsEqualGUID(riid
, &IID_IEnumMoniker
))
847 IEnumMoniker_AddRef(iface
);
851 FIXME("- no interface IID: %s\n", debugstr_guid(riid
));
853 return E_NOINTERFACE
;
856 static ULONG WINAPI
enum_moniker_AddRef(IEnumMoniker
*iface
)
858 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
859 ULONG ref
= InterlockedIncrement(&This
->ref
);
861 TRACE("(%p) ref=%d\n", This
, ref
);
866 static ULONG WINAPI
enum_moniker_Release(IEnumMoniker
*iface
)
868 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
869 ULONG ref
= InterlockedDecrement(&This
->ref
);
871 TRACE("(%p) ref=%d\n", This
, ref
);
876 IEnumDMO_Release(This
->dmo_enum
);
878 IEnumDMO_Release(This
->dmo_enum2
);
879 RegCloseKey(This
->sw_key
);
880 RegCloseKey(This
->cm_key
);
882 DEVENUM_UnlockModule();
888 static struct moniker
*get_dmo_moniker(EnumMonikerImpl
*enum_moniker
)
892 if (IsEqualGUID(&enum_moniker
->class, &CLSID_LegacyAmFilterCategory
))
894 if (enum_moniker
->dmo_enum
&& IEnumDMO_Next(enum_moniker
->dmo_enum
, 1, &clsid
, NULL
, NULL
) == S_OK
)
895 return dmo_moniker_create(DMOCATEGORY_AUDIO_DECODER
, clsid
);
896 if (enum_moniker
->dmo_enum2
&& IEnumDMO_Next(enum_moniker
->dmo_enum2
, 1, &clsid
, NULL
, NULL
) == S_OK
)
897 return dmo_moniker_create(DMOCATEGORY_VIDEO_DECODER
, clsid
);
901 if (enum_moniker
->dmo_enum
&& IEnumDMO_Next(enum_moniker
->dmo_enum
, 1, &clsid
, NULL
, NULL
) == S_OK
)
902 return dmo_moniker_create(enum_moniker
->class, clsid
);
908 static HRESULT WINAPI
enum_moniker_Next(IEnumMoniker
*iface
, ULONG celt
, IMoniker
**rgelt
,
911 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
912 WCHAR buffer
[MAX_PATH
+ 1];
913 struct moniker
*moniker
;
918 TRACE("(%p)->(%d, %p, %p)\n", iface
, celt
, rgelt
, pceltFetched
);
920 while (fetched
< celt
)
922 /* FIXME: try PNP devices first */
925 if ((moniker
= get_dmo_moniker(This
)))
927 /* try DirectShow filters */
928 else if (!(res
= RegEnumKeyW(This
->sw_key
, This
->sw_index
, buffer
, ARRAY_SIZE(buffer
))))
931 if ((res
= RegOpenKeyExW(This
->sw_key
, buffer
, 0, KEY_QUERY_VALUE
, &hkey
)))
934 moniker
= filter_moniker_create(&This
->class, buffer
);
936 /* then try codecs */
937 else if (!(res
= RegEnumKeyW(This
->cm_key
, This
->cm_index
, buffer
, ARRAY_SIZE(buffer
))))
941 if ((res
= RegOpenKeyExW(This
->cm_key
, buffer
, 0, KEY_QUERY_VALUE
, &hkey
)))
944 moniker
= codec_moniker_create(&This
->class, buffer
);
950 return E_OUTOFMEMORY
;
952 rgelt
[fetched
++] = &moniker
->IMoniker_iface
;
955 TRACE("-- fetched %d\n", fetched
);
958 *pceltFetched
= fetched
;
966 static HRESULT WINAPI
enum_moniker_Skip(IEnumMoniker
*iface
, ULONG celt
)
968 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
970 TRACE("(%p)->(%d)\n", iface
, celt
);
974 /* FIXME: try PNP devices first */
977 if (This
->dmo_enum
&& IEnumDMO_Skip(This
->dmo_enum
, 1) == S_OK
)
979 else if (This
->dmo_enum2
&& IEnumDMO_Skip(This
->dmo_enum2
, 1) == S_OK
)
981 /* try DirectShow filters */
982 else if (RegEnumKeyW(This
->sw_key
, This
->sw_index
, NULL
, 0) != ERROR_NO_MORE_ITEMS
)
986 /* then try codecs */
987 else if (RegEnumKeyW(This
->cm_key
, This
->cm_index
, NULL
, 0) != ERROR_NO_MORE_ITEMS
)
998 static HRESULT WINAPI
enum_moniker_Reset(IEnumMoniker
*iface
)
1000 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1002 TRACE("(%p)->()\n", iface
);
1005 IEnumDMO_Reset(This
->dmo_enum
);
1006 if (This
->dmo_enum2
)
1007 IEnumDMO_Reset(This
->dmo_enum2
);
1014 static HRESULT WINAPI
enum_moniker_Clone(IEnumMoniker
*iface
, IEnumMoniker
**ppenum
)
1016 FIXME("(%p)->(%p): stub\n", iface
, ppenum
);
1021 /**********************************************************************
1024 static const IEnumMonikerVtbl IEnumMoniker_Vtbl
=
1026 enum_moniker_QueryInterface
,
1027 enum_moniker_AddRef
,
1028 enum_moniker_Release
,
1035 HRESULT
enum_moniker_create(REFCLSID
class, IEnumMoniker
**out
)
1037 EnumMonikerImpl
*object
;
1040 if (!(object
= calloc(1, sizeof(*object
))))
1041 return E_OUTOFMEMORY
;
1043 object
->IEnumMoniker_iface
.lpVtbl
= &IEnumMoniker_Vtbl
;
1045 object
->class = *class;
1047 wcscpy(buffer
, L
"CLSID\\");
1048 StringFromGUID2(class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
1049 wcscat(buffer
, L
"\\Instance");
1050 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, buffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &object
->sw_key
))
1051 object
->sw_key
= NULL
;
1053 wcscpy(buffer
, L
"Software\\Microsoft\\ActiveMovie\\devenum\\");
1054 StringFromGUID2(class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
1055 if (RegOpenKeyExW(HKEY_CURRENT_USER
, buffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &object
->cm_key
))
1056 object
->cm_key
= NULL
;
1058 if (IsEqualGUID(class, &CLSID_LegacyAmFilterCategory
))
1060 if (FAILED(DMOEnum(&DMOCATEGORY_AUDIO_DECODER
, 0, 0, NULL
, 0, NULL
, &object
->dmo_enum
)))
1061 object
->dmo_enum
= NULL
;
1062 if (FAILED(DMOEnum(&DMOCATEGORY_VIDEO_DECODER
, 0, 0, NULL
, 0, NULL
, &object
->dmo_enum2
)))
1063 object
->dmo_enum2
= NULL
;
1067 if (FAILED(DMOEnum(class, 0, 0, NULL
, 0, NULL
, &object
->dmo_enum
)))
1068 object
->dmo_enum
= NULL
;
1071 *out
= &object
->IEnumMoniker_iface
;
1073 DEVENUM_LockModule();