2 * Copyright (C) 2003 Michael Günnewig
3 * Copyright (C) 2003 CodeWeavers Inc. (Ulrich Czekalla)
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(msdmo
);
35 BOOL
array_reserve(void **elements
, unsigned int *capacity
, unsigned int count
, unsigned int size
)
37 unsigned int max_capacity
, new_capacity
;
40 if (count
<= *capacity
)
43 max_capacity
= ~0u / size
;
44 if (count
> max_capacity
)
47 new_capacity
= max(8, *capacity
);
48 while (new_capacity
< count
&& new_capacity
<= max_capacity
/ 2)
50 if (new_capacity
< count
)
53 if (!(new_elements
= realloc(*elements
, new_capacity
* size
)))
55 ERR("Failed to allocate memory.\n");
59 *elements
= new_elements
;
60 *capacity
= new_capacity
;
66 IEnumDMO IEnumDMO_iface
;
72 DMO_PARTIAL_MEDIATYPE
*pInTypes
;
74 DMO_PARTIAL_MEDIATYPE
*pOutTypes
;
78 static inline IEnumDMOImpl
*impl_from_IEnumDMO(IEnumDMO
*iface
)
80 return CONTAINING_RECORD(iface
, IEnumDMOImpl
, IEnumDMO_iface
);
83 static const IEnumDMOVtbl edmovt
;
85 static const WCHAR
*GUIDToString(WCHAR
*string
, const GUID
*guid
)
87 swprintf(string
, 37, L
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
88 guid
->Data1
, guid
->Data2
, guid
->Data3
,
89 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
90 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
94 static HRESULT
string_to_guid(const WCHAR
*string
, GUID
*guid
)
98 wcscpy(buffer
+ 1, string
);
101 return CLSIDFromString(buffer
, guid
);
104 static BOOL
IsMediaTypeEqual(const DMO_PARTIAL_MEDIATYPE
* mt1
, const DMO_PARTIAL_MEDIATYPE
* mt2
)
107 return (IsEqualCLSID(&mt1
->type
, &mt2
->type
) ||
108 IsEqualCLSID(&mt2
->type
, &GUID_NULL
) ||
109 IsEqualCLSID(&mt1
->type
, &GUID_NULL
)) &&
110 (IsEqualCLSID(&mt1
->subtype
, &mt2
->subtype
) ||
111 IsEqualCLSID(&mt2
->subtype
, &GUID_NULL
) ||
112 IsEqualCLSID(&mt1
->subtype
, &GUID_NULL
));
115 static HRESULT
write_types(HKEY hkey
, LPCWSTR name
, const DMO_PARTIAL_MEDIATYPE
* types
, DWORD count
)
117 return HRESULT_FROM_WIN32(RegSetValueExW(hkey
, name
, 0, REG_BINARY
,
118 (const BYTE
*)types
, count
* sizeof(DMO_PARTIAL_MEDIATYPE
)));
121 /***************************************************************
122 * DMORegister (MSDMO.@)
124 * Register a DirectX Media Object.
126 HRESULT WINAPI
DMORegister(
129 REFGUID guidCategory
,
132 const DMO_PARTIAL_MEDIATYPE
*pInTypes
,
134 const DMO_PARTIAL_MEDIATYPE
*pOutTypes
145 TRACE("%s %s %s\n", debugstr_w(szName
), debugstr_guid(clsidDMO
), debugstr_guid(guidCategory
));
147 if (IsEqualGUID(guidCategory
, &GUID_NULL
))
150 ret
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, L
"DirectShow\\MediaObjects", 0,
151 NULL
, 0, KEY_WRITE
, NULL
, &hrkey
, NULL
);
155 /* Create clsidDMO key under MediaObjects */
156 ret
= RegCreateKeyExW(hrkey
, GUIDToString(szguid
, clsidDMO
), 0, NULL
,
157 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hkey
, NULL
);
161 /* Set default Name value */
162 ret
= RegSetValueExW(hkey
, NULL
, 0, REG_SZ
, (const BYTE
*) szName
,
163 (wcslen(szName
) + 1) * sizeof(WCHAR
));
166 hres
= write_types(hkey
, L
"InputTypes", pInTypes
, cInTypes
);
168 /* Set OutputTypes */
169 hres
= write_types(hkey
, L
"OutputTypes", pOutTypes
, cOutTypes
);
171 if (dwFlags
& DMO_REGISTERF_IS_KEYED
)
173 /* Create Keyed key */
174 ret
= RegCreateKeyExW(hkey
, L
"Keyed", 0, NULL
, 0, KEY_WRITE
, NULL
, &hckey
, NULL
);
180 /* Register the category */
181 ret
= RegCreateKeyExW(hrkey
, L
"Categories", 0, NULL
, 0, KEY_WRITE
, NULL
, &hckey
, NULL
);
187 ret
= RegCreateKeyExW(hckey
, GUIDToString(szguid
, guidCategory
), 0, NULL
,
188 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hkey
, NULL
);
191 ret
= RegCreateKeyExW(hkey
, GUIDToString(szguid
, clsidDMO
), 0, NULL
,
192 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hclskey
, NULL
);
202 RegCloseKey(hclskey
);
206 hres
= HRESULT_FROM_WIN32(ret
);
207 TRACE(" hresult=0x%08lx\n", hres
);
211 static HRESULT
unregister_dmo_from_category(const WCHAR
*dmoW
, const WCHAR
*catW
, HKEY categories
)
216 ret
= RegOpenKeyExW(categories
, catW
, 0, KEY_WRITE
, &catkey
);
219 ret
= RegDeleteKeyW(catkey
, dmoW
);
223 return !ret
? S_OK
: S_FALSE
;
226 /***************************************************************
227 * DMOUnregister (MSDMO.@)
229 * Unregister a DirectX Media Object.
231 HRESULT WINAPI
DMOUnregister(REFCLSID dmo
, REFGUID category
)
233 HKEY rootkey
= 0, categorieskey
= 0;
234 WCHAR dmoW
[64], catW
[64];
235 HRESULT hr
= S_FALSE
;
238 TRACE("%s %s\n", debugstr_guid(dmo
), debugstr_guid(category
));
240 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"DirectShow\\MediaObjects", 0, KEY_WRITE
, &rootkey
))
243 GUIDToString(dmoW
, dmo
);
244 RegDeleteKeyW(rootkey
, dmoW
);
246 /* open 'Categories' */
247 ret
= RegOpenKeyExW(rootkey
, L
"Categories", 0, KEY_WRITE
|KEY_ENUMERATE_SUB_KEYS
, &categorieskey
);
248 RegCloseKey(rootkey
);
251 hr
= HRESULT_FROM_WIN32(ret
);
255 /* remove from all categories */
256 if (IsEqualGUID(category
, &GUID_NULL
))
258 DWORD index
= 0, len
= ARRAY_SIZE(catW
);
260 while (!RegEnumKeyExW(categorieskey
, index
++, catW
, &len
, NULL
, NULL
, NULL
, NULL
))
261 hr
= unregister_dmo_from_category(dmoW
, catW
, categorieskey
);
265 GUIDToString(catW
, category
);
266 hr
= unregister_dmo_from_category(dmoW
, catW
, categorieskey
);
271 RegCloseKey(categorieskey
);
277 /***************************************************************
278 * DMOGetName (MSDMO.@)
280 * Get DMO Name from the registry
282 HRESULT WINAPI
DMOGetName(REFCLSID clsidDMO
, WCHAR name
[80])
284 static const INT max_name_len
= 80*sizeof(WCHAR
);
285 DWORD count
= max_name_len
;
290 TRACE("%s %p\n", debugstr_guid(clsidDMO
), name
);
292 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"DirectShow\\MediaObjects", 0, KEY_READ
, &hrkey
))
295 ret
= RegOpenKeyExW(hrkey
, GUIDToString(szguid
, clsidDMO
), 0, KEY_READ
, &hkey
);
300 ret
= RegQueryValueExW(hkey
, NULL
, NULL
, NULL
, (LPBYTE
)name
, &count
);
303 if (!ret
&& count
> 1)
305 TRACE("name=%s\n", debugstr_w(name
));
313 static HRESULT
dup_partial_mediatype(const DMO_PARTIAL_MEDIATYPE
*types
, DWORD count
, DMO_PARTIAL_MEDIATYPE
**ret
)
320 *ret
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*types
));
322 return E_OUTOFMEMORY
;
324 memcpy(*ret
, types
, count
*sizeof(*types
));
328 /**************************************************************************
329 * IEnumDMO_Constructor
331 static HRESULT
IEnumDMO_Constructor(
332 REFGUID guidCategory
,
335 const DMO_PARTIAL_MEDIATYPE
*pInTypes
,
337 const DMO_PARTIAL_MEDIATYPE
*pOutTypes
,
340 IEnumDMOImpl
* lpedmo
;
345 lpedmo
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IEnumDMOImpl
));
347 return E_OUTOFMEMORY
;
349 lpedmo
->IEnumDMO_iface
.lpVtbl
= &edmovt
;
352 lpedmo
->category
= *guidCategory
;
353 lpedmo
->dwFlags
= dwFlags
;
354 lpedmo
->cInTypes
= cInTypes
;
355 lpedmo
->cOutTypes
= cOutTypes
;
358 hr
= dup_partial_mediatype(pInTypes
, cInTypes
, &lpedmo
->pInTypes
);
362 hr
= dup_partial_mediatype(pOutTypes
, cOutTypes
, &lpedmo
->pOutTypes
);
366 /* If not filtering by category enum from media objects root */
367 if (IsEqualGUID(guidCategory
, &GUID_NULL
))
369 RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"DirectShow\\MediaObjects", 0, KEY_READ
, &lpedmo
->hkey
);
374 WCHAR szKey
[MAX_PATH
];
376 swprintf(szKey
, ARRAY_SIZE(szKey
), L
"DirectShow\\MediaObjects\\Categories\\%s",
377 GUIDToString(szguid
, guidCategory
));
378 RegOpenKeyExW(HKEY_CLASSES_ROOT
, szKey
, 0, KEY_READ
, &lpedmo
->hkey
);
384 IEnumDMO_Release(&lpedmo
->IEnumDMO_iface
);
387 TRACE("returning %p\n", lpedmo
);
388 *obj
= &lpedmo
->IEnumDMO_iface
;
394 /******************************************************************************
397 static ULONG WINAPI
IEnumDMO_fnAddRef(IEnumDMO
* iface
)
399 IEnumDMOImpl
*This
= impl_from_IEnumDMO(iface
);
400 ULONG refCount
= InterlockedIncrement(&This
->ref
);
401 TRACE("(%p)->(%ld)\n", This
, refCount
);
405 /**************************************************************************
406 * EnumDMO_QueryInterface
408 static HRESULT WINAPI
IEnumDMO_fnQueryInterface(IEnumDMO
* iface
, REFIID riid
, void **ppvObj
)
410 IEnumDMOImpl
*This
= impl_from_IEnumDMO(iface
);
412 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObj
);
416 if (IsEqualIID(riid
, &IID_IEnumDMO
) ||
417 IsEqualIID(riid
, &IID_IUnknown
))
420 IEnumDMO_AddRef(iface
);
423 return *ppvObj
? S_OK
: E_NOINTERFACE
;
426 /******************************************************************************
429 static ULONG WINAPI
IEnumDMO_fnRelease(IEnumDMO
* iface
)
431 IEnumDMOImpl
*This
= impl_from_IEnumDMO(iface
);
432 ULONG refCount
= InterlockedDecrement(&This
->ref
);
434 TRACE("(%p)->(%ld)\n", This
, refCount
);
439 RegCloseKey(This
->hkey
);
440 HeapFree(GetProcessHeap(), 0, This
->pInTypes
);
441 HeapFree(GetProcessHeap(), 0, This
->pOutTypes
);
442 HeapFree(GetProcessHeap(), 0, This
);
447 static BOOL
any_types_match(const DMO_PARTIAL_MEDIATYPE
*a
, unsigned int a_count
,
448 const DMO_PARTIAL_MEDIATYPE
*b
, unsigned int b_count
)
452 for (i
= 0; i
< a_count
; ++i
)
454 for (j
= 0; j
< b_count
; ++j
)
456 if (IsMediaTypeEqual(&a
[i
], &b
[j
]))
463 /******************************************************************************
466 static HRESULT WINAPI
IEnumDMO_fnNext(
471 DWORD
* pcItemsFetched
)
473 DMO_PARTIAL_MEDIATYPE
*types
= NULL
;
474 unsigned int types_size
= 0;
476 WCHAR szNextKey
[MAX_PATH
];
477 WCHAR path
[MAX_PATH
];
478 WCHAR szValue
[MAX_PATH
];
484 IEnumDMOImpl
*This
= impl_from_IEnumDMO(iface
);
486 TRACE("(%p)->(%ld %p %p %p)\n", This
, cItemsToFetch
, pCLSID
, Names
, pcItemsFetched
);
491 if (!pcItemsFetched
&& cItemsToFetch
> 1)
494 while (count
< cItemsToFetch
)
499 ret
= RegEnumKeyExW(This
->hkey
, This
->index
, szNextKey
, &len
, NULL
, NULL
, NULL
, NULL
);
500 if (ret
!= ERROR_SUCCESS
)
502 hres
= HRESULT_FROM_WIN32(ret
);
506 if (string_to_guid(szNextKey
, &pCLSID
[count
]) != S_OK
)
509 TRACE("found %s\n", debugstr_w(szNextKey
));
511 if (!(This
->dwFlags
& DMO_ENUMF_INCLUDE_KEYED
))
513 swprintf(path
, ARRAY_SIZE(path
), L
"DirectShow\\MediaObjects\\%s\\Keyed", szNextKey
);
514 ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, path
, 0, KEY_READ
, &hkey
);
515 if (ERROR_SUCCESS
== ret
)
518 /* Skip Keyed entries */
523 swprintf(path
, ARRAY_SIZE(path
), L
"DirectShow\\MediaObjects\\%s", szNextKey
);
524 ret
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, path
, 0, KEY_READ
, &hkey
);
525 TRACE("Testing %s.\n", debugstr_w(path
));
534 ret
= RegQueryValueExW(hkey
, L
"InputTypes", NULL
, NULL
, (BYTE
*)types
, &size
);
535 if (ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
)
537 if (size
<= types_size
)
539 if (!array_reserve((void **)&types
, &types_size
, size
, 1))
543 return E_OUTOFMEMORY
;
552 for (i
= 0; i
< size
/ sizeof(DMO_PARTIAL_MEDIATYPE
); ++i
)
553 TRACE("intype %ld: type %s, subtype %s\n", i
, debugstr_guid(&types
[i
].type
),
554 debugstr_guid(&types
[i
].subtype
));
556 if (!any_types_match(types
, size
/ sizeof(DMO_PARTIAL_MEDIATYPE
), This
->pInTypes
, This
->cInTypes
))
565 DWORD size
= types_size
, i
;
570 ret
= RegQueryValueExW(hkey
, L
"OutputTypes", NULL
, NULL
, (BYTE
*)types
, &size
);
571 if (ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
)
573 if (size
<= types_size
)
575 if (!array_reserve((void **)&types
, &types_size
, size
, 1))
579 return E_OUTOFMEMORY
;
588 for (i
= 0; i
< size
/ sizeof(DMO_PARTIAL_MEDIATYPE
); ++i
)
589 TRACE("outtype %ld: type %s, subtype %s\n", i
, debugstr_guid(&types
[i
].type
),
590 debugstr_guid(&types
[i
].subtype
));
592 if (!any_types_match(types
, size
/ sizeof(DMO_PARTIAL_MEDIATYPE
), This
->pOutTypes
, This
->cOutTypes
))
599 /* Media object wasn't filtered so add it to return list */
600 len
= MAX_PATH
* sizeof(WCHAR
);
601 ret
= RegQueryValueExW(hkey
, NULL
, NULL
, NULL
, (LPBYTE
)szValue
, &len
);
605 if (ret
== ERROR_SUCCESS
)
607 Names
[count
] = CoTaskMemAlloc((wcslen(szValue
) + 1) * sizeof(WCHAR
));
609 wcscpy(Names
[count
], szValue
);
613 TRACE("found match %s %s\n", debugstr_w(szValue
), debugstr_w(szNextKey
));
620 if (pcItemsFetched
) *pcItemsFetched
= count
;
621 if (count
< cItemsToFetch
)
624 TRACE("<-- %i found\n",count
);
629 /******************************************************************************
632 static HRESULT WINAPI
IEnumDMO_fnSkip(IEnumDMO
* iface
, DWORD cItemsToSkip
)
634 IEnumDMOImpl
*This
= impl_from_IEnumDMO(iface
);
636 TRACE("(%p)->(%ld)\n", This
, cItemsToSkip
);
637 This
->index
+= cItemsToSkip
;
643 /******************************************************************************
646 static HRESULT WINAPI
IEnumDMO_fnReset(IEnumDMO
* iface
)
648 IEnumDMOImpl
*This
= impl_from_IEnumDMO(iface
);
650 TRACE("(%p)\n", This
);
657 /******************************************************************************
660 static HRESULT WINAPI
IEnumDMO_fnClone(IEnumDMO
*iface
, IEnumDMO
**ppEnum
)
662 IEnumDMOImpl
*This
= impl_from_IEnumDMO(iface
);
663 TRACE("(%p)->(%p)\n", This
, ppEnum
);
664 return IEnumDMO_Constructor(&This
->category
, This
->dwFlags
, This
->cInTypes
, This
->pInTypes
,
665 This
->cOutTypes
, This
->pOutTypes
, ppEnum
);
669 /***************************************************************
672 * Enumerate DirectX Media Objects in the registry.
674 HRESULT WINAPI
DMOEnum(
678 const DMO_PARTIAL_MEDIATYPE
*pInTypes
,
680 const DMO_PARTIAL_MEDIATYPE
*pOutTypes
,
683 TRACE("%s 0x%08lx %ld %p %ld %p %p\n", debugstr_guid(category
), flags
, cInTypes
, pInTypes
,
684 cOutTypes
, pOutTypes
, ppEnum
);
691 for (i
= 0; i
< cInTypes
; i
++)
692 TRACE("intype %ld - type %s, subtype %s\n", i
, debugstr_guid(&pInTypes
[i
].type
),
693 debugstr_guid(&pInTypes
[i
].subtype
));
697 for (i
= 0; i
< cOutTypes
; i
++)
698 TRACE("outtype %ld - type %s, subtype %s\n", i
, debugstr_guid(&pOutTypes
[i
].type
),
699 debugstr_guid(&pOutTypes
[i
].subtype
));
703 return IEnumDMO_Constructor(category
, flags
, cInTypes
,
704 pInTypes
, cOutTypes
, pOutTypes
, ppEnum
);
708 static const IEnumDMOVtbl edmovt
=
710 IEnumDMO_fnQueryInterface
,
719 /***************************************************************
720 * DMOGetTypes (MSDMO.@)
722 HRESULT WINAPI
DMOGetTypes(REFCLSID clsid
, ULONG input_count
, ULONG
*ret_input_count
, DMO_PARTIAL_MEDIATYPE
*input
,
723 ULONG output_count
, ULONG
*ret_output_count
, DMO_PARTIAL_MEDIATYPE
*output
)
730 TRACE("clsid %s, input_count %lu, ret_input_count %p, input %p, output_count %lu, ret_output_count %p, output %p.\n",
731 debugstr_guid(clsid
), input_count
, ret_input_count
, input
, output_count
, ret_output_count
, output
);
733 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"DirectShow\\MediaObjects", 0, KEY_READ
, &root
))
736 if (RegOpenKeyExW(root
, GUIDToString(guidstr
, clsid
), 0, KEY_READ
, &key
))
742 *ret_input_count
= 0;
743 size
= input_count
* sizeof(DMO_PARTIAL_MEDIATYPE
);
744 ret
= RegQueryValueExW(key
, L
"InputTypes", NULL
, NULL
, (BYTE
*)input
, &size
);
745 if (!ret
|| ret
== ERROR_MORE_DATA
)
746 *ret_input_count
= min(input_count
, size
/ sizeof(DMO_PARTIAL_MEDIATYPE
));
748 *ret_output_count
= 0;
749 size
= output_count
* sizeof(DMO_PARTIAL_MEDIATYPE
);
750 ret
= RegQueryValueExW(key
, L
"OutputTypes", NULL
, NULL
, (BYTE
*)output
, &size
);
751 if (!ret
|| ret
== ERROR_MORE_DATA
)
752 *ret_output_count
= min(output_count
, size
/ sizeof(DMO_PARTIAL_MEDIATYPE
));