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
20 #define WIN32_NO_STATUS
22 #define COM_NO_WINDOWS_H
29 //#include "winerror.h"
32 #include <wine/unicode.h>
33 #include <wine/debug.h>
34 //#include "initguid.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msdmo
);
39 #define MSDMO_MAJOR_VERSION 6
41 static const WCHAR szDMORootKey
[] =
43 'D','i','r','e','c','t','S','h','o','w','\\',
44 'M','e','d','i','a','O','b','j','e','c','t','s',0
47 static const WCHAR szDMOInputType
[] =
49 'I','n','p','u','t','T','y','p','e','s',0
52 static const WCHAR szDMOOutputType
[] =
54 'O','u','t','p','u','t','T','y','p','e','s',0
57 static const WCHAR szDMOKeyed
[] =
62 static const WCHAR szDMOCategories
[] =
64 'C','a','t','e','g','o','r','i','e','s',0
67 static const WCHAR szGUIDFmt
[] =
69 '%','0','8','X','-','%','0','4','X','-','%','0','4','X','-','%','0',
70 '2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2',
71 'X','%','0','2','X','%','0','2','X','%','0','2','X',0
74 static const WCHAR szCat3Fmt
[] =
76 '%','s','\\','%','s','\\','%','s',0
79 static const WCHAR szCat2Fmt
[] =
81 '%','s','\\','%','s',0
84 static const WCHAR szToGuidFmt
[] =
92 const IEnumDMOVtbl
*lpVtbl
;
95 const GUID
* guidCategory
;
98 DMO_PARTIAL_MEDIATYPE
*pInTypes
;
100 DMO_PARTIAL_MEDIATYPE
*pOutTypes
;
104 static HRESULT
read_types(HKEY root
, LPCWSTR key
, ULONG
*supplied
, ULONG requested
, DMO_PARTIAL_MEDIATYPE
* types
);
106 static const IEnumDMOVtbl edmovt
;
108 static LPWSTR
GUIDToString(LPWSTR lpwstr
, REFGUID lpcguid
)
110 wsprintfW(lpwstr
, szGUIDFmt
, lpcguid
->Data1
, lpcguid
->Data2
,
111 lpcguid
->Data3
, lpcguid
->Data4
[0], lpcguid
->Data4
[1],
112 lpcguid
->Data4
[2], lpcguid
->Data4
[3], lpcguid
->Data4
[4],
113 lpcguid
->Data4
[5], lpcguid
->Data4
[6], lpcguid
->Data4
[7]);
118 static BOOL
IsMediaTypeEqual(const DMO_PARTIAL_MEDIATYPE
* mt1
, const DMO_PARTIAL_MEDIATYPE
* mt2
)
121 return (IsEqualCLSID(&mt1
->type
, &mt2
->type
) ||
122 IsEqualCLSID(&mt2
->type
, &GUID_NULL
) ||
123 IsEqualCLSID(&mt1
->type
, &GUID_NULL
)) &&
124 (IsEqualCLSID(&mt1
->subtype
, &mt2
->subtype
) ||
125 IsEqualCLSID(&mt2
->subtype
, &GUID_NULL
) ||
126 IsEqualCLSID(&mt1
->subtype
, &GUID_NULL
));
129 static HRESULT
write_types(HKEY hkey
, LPCWSTR name
, const DMO_PARTIAL_MEDIATYPE
* types
, DWORD count
)
132 if (MSDMO_MAJOR_VERSION
> 5)
134 hres
= RegSetValueExW(hkey
, name
, 0, REG_BINARY
, (const BYTE
*) types
,
135 count
* sizeof(DMO_PARTIAL_MEDIATYPE
));
139 HKEY skey1
,skey2
,skey3
;
143 hres
= RegCreateKeyExW(hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
144 KEY_WRITE
, NULL
, &skey1
, NULL
);
145 while (index
< count
)
147 GUIDToString(szGuidKey
,&types
[index
].type
);
148 hres
= RegCreateKeyExW(skey1
, szGuidKey
, 0, NULL
,
149 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &skey2
, NULL
);
150 GUIDToString(szGuidKey
,&types
[index
].subtype
);
151 hres
= RegCreateKeyExW(skey2
, szGuidKey
, 0, NULL
,
152 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &skey3
, NULL
);
163 /***************************************************************
164 * DMORegister (MSDMO.@)
166 * Register a DirectX Media Object.
168 HRESULT WINAPI
DMORegister(
171 REFGUID guidCategory
,
174 const DMO_PARTIAL_MEDIATYPE
*pInTypes
,
176 const DMO_PARTIAL_MEDIATYPE
*pOutTypes
186 TRACE("%s\n", debugstr_w(szName
));
188 hres
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, szDMORootKey
, 0, NULL
,
189 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hrkey
, NULL
);
190 if (ERROR_SUCCESS
!= hres
)
193 /* Create clsidDMO key under MediaObjects */
194 hres
= RegCreateKeyExW(hrkey
, GUIDToString(szguid
, clsidDMO
), 0, NULL
,
195 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hkey
, NULL
);
196 if (ERROR_SUCCESS
!= hres
)
199 /* Set default Name value */
200 hres
= RegSetValueExW(hkey
, NULL
, 0, REG_SZ
, (const BYTE
*) szName
,
201 (strlenW(szName
) + 1) * sizeof(WCHAR
));
204 hres
= write_types(hkey
, szDMOInputType
, pInTypes
, cInTypes
);
206 /* Set OutputTypes */
207 hres
= write_types(hkey
, szDMOOutputType
, pOutTypes
, cOutTypes
);
209 if (dwFlags
& DMO_REGISTERF_IS_KEYED
)
211 /* Create Keyed key */
212 hres
= RegCreateKeyExW(hkey
, szDMOKeyed
, 0, NULL
,
213 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hckey
, NULL
);
214 if (ERROR_SUCCESS
!= hres
)
219 /* Register the category */
220 hres
= RegCreateKeyExW(hrkey
, szDMOCategories
, 0, NULL
,
221 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hckey
, NULL
);
222 if (ERROR_SUCCESS
!= hres
)
227 hres
= RegCreateKeyExW(hckey
, GUIDToString(szguid
, guidCategory
), 0, NULL
,
228 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hkey
, NULL
);
229 if (ERROR_SUCCESS
!= hres
)
231 hres
= RegCreateKeyExW(hkey
, GUIDToString(szguid
, clsidDMO
), 0, NULL
,
232 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hclskey
, NULL
);
233 if (ERROR_SUCCESS
!= hres
)
242 RegCloseKey(hclskey
);
246 TRACE(" hresult=0x%08x\n", hres
);
251 /***************************************************************
252 * DMOUnregister (MSDMO.@)
254 * Unregister a DirectX Media Object.
256 HRESULT WINAPI
DMOUnregister(REFCLSID clsidDMO
, REFGUID guidCategory
)
263 GUIDToString(szguid
, clsidDMO
);
265 TRACE("%s %p\n", debugstr_w(szguid
), guidCategory
);
267 hres
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, szDMORootKey
, 0, KEY_WRITE
, &hrkey
);
268 if (ERROR_SUCCESS
!= hres
)
271 hres
= RegDeleteKeyW(hrkey
, szguid
);
272 if (ERROR_SUCCESS
!= hres
)
275 hres
= RegOpenKeyExW(hrkey
, szDMOCategories
, 0, KEY_WRITE
, &hckey
);
276 if (ERROR_SUCCESS
!= hres
)
279 hres
= RegDeleteKeyW(hckey
, szguid
);
280 if (ERROR_SUCCESS
!= hres
)
293 /***************************************************************
294 * DMOGetName (MSDMO.@)
296 * Get DMP Name from the registry
298 HRESULT WINAPI
DMOGetName(REFCLSID clsidDMO
, WCHAR szName
[])
304 static const INT max_name_len
= 80;
307 TRACE("%s\n", debugstr_guid(clsidDMO
));
309 hres
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, szDMORootKey
,
310 0, KEY_READ
, &hrkey
);
311 if (ERROR_SUCCESS
!= hres
)
314 hres
= RegOpenKeyExW(hrkey
, GUIDToString(szguid
, clsidDMO
),
316 if (ERROR_SUCCESS
!= hres
)
319 count
= max_name_len
* sizeof(WCHAR
);
320 hres
= RegQueryValueExW(hkey
, NULL
, NULL
, NULL
,
321 (LPBYTE
) szName
, &count
);
323 TRACE(" szName=%s\n", debugstr_w(szName
));
334 /**************************************************************************
335 * IEnumDMO_Destructor
337 static BOOL
IEnumDMO_Destructor(IEnumDMO
* iface
)
339 IEnumDMOImpl
*This
= (IEnumDMOImpl
*)iface
;
344 RegCloseKey(This
->hkey
);
346 HeapFree(GetProcessHeap(), 0, This
->pInTypes
);
347 HeapFree(GetProcessHeap(), 0, This
->pOutTypes
);
353 /**************************************************************************
354 * IEnumDMO_Constructor
356 static IEnumDMO
* IEnumDMO_Constructor(
357 REFGUID guidCategory
,
360 const DMO_PARTIAL_MEDIATYPE
*pInTypes
,
362 const DMO_PARTIAL_MEDIATYPE
*pOutTypes
)
365 IEnumDMOImpl
* lpedmo
;
368 lpedmo
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IEnumDMOImpl
));
373 lpedmo
->lpVtbl
= &edmovt
;
375 lpedmo
->guidCategory
= guidCategory
;
376 lpedmo
->dwFlags
= dwFlags
;
380 size
= cInTypes
* sizeof(DMO_PARTIAL_MEDIATYPE
);
381 lpedmo
->pInTypes
= HeapAlloc(GetProcessHeap(), 0, size
);
382 if (!lpedmo
->pInTypes
)
384 memcpy(lpedmo
->pInTypes
, pInTypes
, size
);
385 lpedmo
->cInTypes
= cInTypes
;
390 size
= cOutTypes
* sizeof(DMO_PARTIAL_MEDIATYPE
);
391 lpedmo
->pOutTypes
= HeapAlloc(GetProcessHeap(), 0, size
);
392 if (!lpedmo
->pOutTypes
)
394 memcpy(lpedmo
->pOutTypes
, pOutTypes
, size
);
395 lpedmo
->cOutTypes
= cOutTypes
;
398 /* If not filtering by category enum from media objects root */
399 if (IsEqualGUID(guidCategory
, &GUID_NULL
))
401 if (ERROR_SUCCESS
== RegOpenKeyExW(HKEY_CLASSES_ROOT
, szDMORootKey
,
402 0, KEY_READ
, &lpedmo
->hkey
))
408 WCHAR szKey
[MAX_PATH
];
410 wsprintfW(szKey
, szCat3Fmt
, szDMORootKey
, szDMOCategories
,
411 GUIDToString(szguid
, guidCategory
));
412 if (ERROR_SUCCESS
== RegOpenKeyExW(HKEY_CLASSES_ROOT
, szKey
,
413 0, KEY_READ
, &lpedmo
->hkey
))
420 IEnumDMO_Destructor((IEnumDMO
*)lpedmo
);
421 HeapFree(GetProcessHeap(),0,lpedmo
);
426 TRACE("returning %p\n", lpedmo
);
428 return (IEnumDMO
*)lpedmo
;
432 /******************************************************************************
435 static ULONG WINAPI
IEnumDMO_fnAddRef(IEnumDMO
* iface
)
437 IEnumDMOImpl
*This
= (IEnumDMOImpl
*)iface
;
438 return InterlockedIncrement(&This
->ref
);
442 /**************************************************************************
443 * EnumDMO_QueryInterface
445 static HRESULT WINAPI
IEnumDMO_fnQueryInterface(
450 IEnumDMOImpl
*This
= (IEnumDMOImpl
*)iface
;
454 if(IsEqualIID(riid
, &IID_IUnknown
))
456 else if(IsEqualIID(riid
, &IID_IEnumDMO
))
461 IEnumDMO_fnAddRef(*ppvObj
);
465 return E_NOINTERFACE
;
469 /******************************************************************************
472 static ULONG WINAPI
IEnumDMO_fnRelease(IEnumDMO
* iface
)
474 IEnumDMOImpl
*This
= (IEnumDMOImpl
*)iface
;
475 ULONG refCount
= InterlockedDecrement(&This
->ref
);
479 IEnumDMO_Destructor((IEnumDMO
*)This
);
480 HeapFree(GetProcessHeap(),0,This
);
486 /******************************************************************************
489 static HRESULT WINAPI
IEnumDMO_fnNext(
494 DWORD
* pcItemsFetched
)
498 WCHAR szNextKey
[MAX_PATH
];
500 WCHAR szKey
[MAX_PATH
];
501 WCHAR szValue
[MAX_PATH
];
506 IEnumDMOImpl
*This
= (IEnumDMOImpl
*)iface
;
508 TRACE("--> (%p) %d %p %p %p\n", iface
, cItemsToFetch
, pCLSID
, Names
, pcItemsFetched
);
510 if (!pCLSID
|| !Names
|| !pcItemsFetched
)
513 while (count
< cItemsToFetch
)
518 hres
= RegEnumKeyExW(This
->hkey
, This
->index
, szNextKey
, &len
, NULL
, NULL
, NULL
, &ft
);
519 if (hres
!= ERROR_SUCCESS
)
522 TRACE("found %s\n", debugstr_w(szNextKey
));
524 if (!(This
->dwFlags
& DMO_ENUMF_INCLUDE_KEYED
))
526 wsprintfW(szKey
, szCat3Fmt
, szDMORootKey
, szNextKey
, szDMOKeyed
);
527 hres
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, szKey
, 0, KEY_READ
, &hkey
);
528 if (ERROR_SUCCESS
== hres
)
531 /* Skip Keyed entries */
536 wsprintfW(szKey
, szCat2Fmt
, szDMORootKey
, szNextKey
);
537 hres
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, szKey
, 0, KEY_READ
, &hkey
);
543 DMO_PARTIAL_MEDIATYPE
* pInTypes
;
545 hres
= read_types(hkey
, szDMOInputType
, &cInTypes
,
546 sizeof(szValue
)/sizeof(DMO_PARTIAL_MEDIATYPE
),
547 (DMO_PARTIAL_MEDIATYPE
*)szValue
);
549 if (ERROR_SUCCESS
!= hres
)
555 pInTypes
= (DMO_PARTIAL_MEDIATYPE
*) szValue
;
557 for (i
= 0; i
< This
->cInTypes
; i
++)
559 for (j
= 0; j
< cInTypes
; j
++)
561 if (IsMediaTypeEqual(&pInTypes
[j
], &This
->pInTypes
[i
]))
569 if (i
< This
->cInTypes
)
580 DMO_PARTIAL_MEDIATYPE
* pOutTypes
;
582 hres
= read_types(hkey
, szDMOOutputType
, &cOutTypes
,
583 sizeof(szValue
)/sizeof(DMO_PARTIAL_MEDIATYPE
),
584 (DMO_PARTIAL_MEDIATYPE
*)szValue
);
586 if (ERROR_SUCCESS
!= hres
)
592 pOutTypes
= (DMO_PARTIAL_MEDIATYPE
*) szValue
;
594 for (i
= 0; i
< This
->cOutTypes
; i
++)
596 for (j
= 0; j
< cOutTypes
; j
++)
598 if (IsMediaTypeEqual(&pOutTypes
[j
], &This
->pOutTypes
[i
]))
606 if (i
< This
->cOutTypes
)
613 /* Media object wasn't filtered so add it to return list */
615 len
= MAX_PATH
* sizeof(WCHAR
);
616 hres
= RegQueryValueExW(hkey
, NULL
, NULL
, NULL
, (LPBYTE
) szValue
, &len
);
617 if (ERROR_SUCCESS
== hres
)
619 Names
[count
] = HeapAlloc(GetProcessHeap(), 0, strlenW(szValue
) + 1);
621 strcmpW(Names
[count
], szValue
);
623 wsprintfW(szGuidKey
,szToGuidFmt
,szNextKey
);
624 CLSIDFromString(szGuidKey
, &pCLSID
[count
]);
626 TRACE("found match %s %s\n", debugstr_w(szValue
), debugstr_w(szNextKey
));
631 *pcItemsFetched
= count
;
632 if (*pcItemsFetched
< cItemsToFetch
)
635 TRACE("<-- %i found\n",count
);
640 /******************************************************************************
643 static HRESULT WINAPI
IEnumDMO_fnSkip(IEnumDMO
* iface
, DWORD cItemsToSkip
)
645 IEnumDMOImpl
*This
= (IEnumDMOImpl
*)iface
;
647 This
->index
+= cItemsToSkip
;
653 /******************************************************************************
656 static HRESULT WINAPI
IEnumDMO_fnReset(IEnumDMO
* iface
)
658 IEnumDMOImpl
*This
= (IEnumDMOImpl
*)iface
;
666 /******************************************************************************
669 static HRESULT WINAPI
IEnumDMO_fnClone(IEnumDMO
* iface
, IEnumDMO
**ppEnum
)
671 IEnumDMOImpl
*This
= (IEnumDMOImpl
*)iface
;
673 FIXME("(%p)->() to (%p)->() E_NOTIMPL\n", This
, ppEnum
);
679 /***************************************************************
682 * Enumerate DirectX Media Objects in the registry.
684 HRESULT WINAPI
DMOEnum(
685 REFGUID guidCategory
,
688 const DMO_PARTIAL_MEDIATYPE
*pInTypes
,
690 const DMO_PARTIAL_MEDIATYPE
*pOutTypes
,
693 HRESULT hres
= E_FAIL
;
695 TRACE("guidCategory=%p dwFlags=0x%08x cInTypes=%d cOutTypes=%d\n",
696 guidCategory
, dwFlags
, cInTypes
, cOutTypes
);
698 *ppEnum
= IEnumDMO_Constructor(guidCategory
, dwFlags
, cInTypes
,
699 pInTypes
, cOutTypes
, pOutTypes
);
707 static const IEnumDMOVtbl edmovt
=
709 IEnumDMO_fnQueryInterface
,
719 HRESULT
read_types(HKEY root
, LPCWSTR key
, ULONG
*supplied
, ULONG requested
, DMO_PARTIAL_MEDIATYPE
* types
)
722 if (MSDMO_MAJOR_VERSION
> 5)
725 len
= requested
* sizeof(DMO_PARTIAL_MEDIATYPE
);
726 ret
= RegQueryValueExW(root
, key
, NULL
, NULL
, (LPBYTE
) types
, &len
);
727 *supplied
= len
/ sizeof(DMO_PARTIAL_MEDIATYPE
);
735 if (ERROR_SUCCESS
== RegOpenKeyExW(root
, key
, 0, KEY_READ
, &hkey
))
738 WCHAR szNextKey
[MAX_PATH
];
740 LONG rc
= ERROR_SUCCESS
;
742 while (rc
== ERROR_SUCCESS
)
745 rc
= RegEnumKeyExW(hkey
, index
, szNextKey
, &len
, NULL
, NULL
, NULL
, NULL
);
746 if (rc
== ERROR_SUCCESS
)
750 LONG rcs
= ERROR_SUCCESS
;
751 WCHAR szSubKey
[MAX_PATH
];
753 RegOpenKeyExW(hkey
, szNextKey
, 0, KEY_READ
, &subk
);
754 while (rcs
== ERROR_SUCCESS
)
757 rcs
= RegEnumKeyExW(subk
, sub_index
, szSubKey
, &len
, NULL
, NULL
, NULL
, NULL
);
758 if (rcs
== ERROR_SUCCESS
)
760 if (*supplied
>= requested
)
764 rc
= ERROR_MORE_DATA
;
765 rcs
= ERROR_MORE_DATA
;
769 wsprintfW(szGuidKey
,szToGuidFmt
,szNextKey
);
770 CLSIDFromString(szGuidKey
, &types
[*supplied
].type
);
771 wsprintfW(szGuidKey
,szToGuidFmt
,szSubKey
);
772 CLSIDFromString(szGuidKey
, &types
[*supplied
].subtype
);
773 TRACE("Adding type %s subtype %s at index %i\n",
774 debugstr_guid(&types
[*supplied
].type
),
775 debugstr_guid(&types
[*supplied
].subtype
),
790 /***************************************************************
791 * DMOGetTypes (MSDMO.@)
793 HRESULT WINAPI
DMOGetTypes(REFCLSID clsidDMO
,
794 ULONG ulInputTypesRequested
,
795 ULONG
* pulInputTypesSupplied
,
796 DMO_PARTIAL_MEDIATYPE
* pInputTypes
,
797 ULONG ulOutputTypesRequested
,
798 ULONG
* pulOutputTypesSupplied
,
799 DMO_PARTIAL_MEDIATYPE
* pOutputTypes
)
805 TRACE ("(%s,%u,%p,%p,%u,%p,%p),stub!\n", debugstr_guid(clsidDMO
),
806 ulInputTypesRequested
, pulInputTypesSupplied
, pInputTypes
,
807 ulOutputTypesRequested
, pulOutputTypesSupplied
, pOutputTypes
);
809 if (ERROR_SUCCESS
!= RegOpenKeyExW(HKEY_CLASSES_ROOT
, szDMORootKey
, 0,
813 if (ERROR_SUCCESS
!= RegOpenKeyExW(root
,GUIDToString(szguid
,clsidDMO
) , 0,
820 if (ulInputTypesRequested
> 0)
822 ret
= read_types(hkey
, szDMOInputType
, pulInputTypesSupplied
, ulInputTypesRequested
, pInputTypes
);
825 *pulInputTypesSupplied
= 0;
827 if (ulOutputTypesRequested
> 0)
830 ret2
= read_types(hkey
, szDMOOutputType
, pulOutputTypesSupplied
, ulOutputTypesRequested
, pOutputTypes
);
836 *pulOutputTypesSupplied
= 0;