These implementations are based on my observations under win2k. Changelog: Ulrich Czekalla <ulrich@xxxxxxxxxxxxxxx> Implement DMORegister, DMOUnregister, DMOGetName, DMOEnum
Index: dlls/msdmo/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/msdmo/Makefile.in,v retrieving revision 1.8 diff -u -w -r1.8 Makefile.in --- dlls/msdmo/Makefile.in 11 Oct 2003 01:09:18 -0000 1.8 +++ dlls/msdmo/Makefile.in 24 Nov 2003 16:17:54 -0000 @@ -3,7 +3,8 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = msdmo.dll -IMPORTS = ole32 kernel32 +IMPORTS = ole32 kernel32 advapi32 user32 +EXTRALIBS = $(LIBUUID) C_SRCS = \ dmoreg.c \ Index: dlls/msdmo/dmoreg.c =================================================================== RCS file: /home/wine/wine/dlls/msdmo/dmoreg.c,v retrieving revision 1.4 diff -u -w -r1.4 dmoreg.c --- dlls/msdmo/dmoreg.c 5 Sep 2003 23:08:36 -0000 1.4 +++ dlls/msdmo/dmoreg.c 24 Nov 2003 16:17:54 -0000 @@ -1,5 +1,6 @@ /* * Copyright (C) 2003 Michael Günnewig + * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,49 +22,644 @@ #include "windef.h" #include "winbase.h" +#include "winuser.h" +#include "winerror.h" +#include "winreg.h" #include "objbase.h" -#include "mediaobj.h" -#include "dmoreg.h" +#include "dmo.h" +#include "wine/unicode.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(msdmo); -/***********************************************************************/ -HRESULT WINAPI DMORegister(LPCWSTR a, REFCLSID b, REFGUID c, DWORD d, DWORD e, - const DMO_PARTIAL_MEDIATYPE* f, - DWORD g, const DMO_PARTIAL_MEDIATYPE* h) +static const WCHAR szDMORootKey[] = { - FIXME("(%p,%p,%p,%lu,%lu,%p,%lu,%p),stub!\n",a,b,c,d,e,f,g,h); + 'D','i','r','e','c','t','S','h','o','w','\\', + 'M','e','d','i','a','O','b','j','e','c','t','s',0 +}; - return E_NOTIMPL; +static const WCHAR szDMOInputType[] = +{ + 'I','n','p','u','t','T','y','p','e','s',0 +}; + +static const WCHAR szDMOOutputType[] = +{ + 'O','u','t','p','u','t','T','y','p','e','s',0 +}; + +static const WCHAR szDMOKeyed[] = +{ + 'K','e','y','e','d',0 +}; + +static const WCHAR szDMOCategories[] = +{ + 'C','a','t','e','g','o','r','i','e','s',0 +}; + +static const WCHAR szGUIDFmt[] = +{ + '%','0','8','X','-','%','0','4','X','-','%','0','4','X','-','%','0', + '2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2', + 'X','%','0','2','X','%','0','2','X','%','0','2','X',0 +}; + +static const WCHAR szCat3Fmt[] = +{ + '%','s','\\','%','s','\\','%','s',0 +}; + +static const WCHAR szCat2Fmt[] = +{ + '%','s','\\','%','s',0 +}; + +typedef struct +{ + ICOM_VFIELD(IEnumDMO); + DWORD ref; + DWORD index; + const GUID* guidCategory; + DWORD dwFlags; + DWORD cInTypes; + DMO_PARTIAL_MEDIATYPE *pInTypes; + DWORD cOutTypes; + DMO_PARTIAL_MEDIATYPE *pOutTypes; + HKEY hkey; +} IEnumDMOImpl; + +const GUID IID_IEnumDMO = { 0x2c3cd98a, 0x2bfa, 0x4a53, + { 0x9c, 0x27, 0x52, 0x49, 0xba, 0x64, 0xba, 0x0f}}; + +static struct ICOM_VTABLE(IEnumDMO) edmovt; + +static LPWSTR GUIDToString(LPWSTR lpwstr, REFGUID lpcguid) +{ + wsprintfW(lpwstr, szGUIDFmt, lpcguid->Data1, lpcguid->Data2, + lpcguid->Data3, lpcguid->Data4[0], lpcguid->Data4[1], + lpcguid->Data4[2], lpcguid->Data4[3], lpcguid->Data4[4], + lpcguid->Data4[5], lpcguid->Data4[6], lpcguid->Data4[7]); + + return lpwstr; } -HRESULT WINAPI DMOUnregister(REFCLSID a,REFGUID b) +static BOOL IsMediaTypeEqual(DMO_PARTIAL_MEDIATYPE* mt1, DMO_PARTIAL_MEDIATYPE* mt2) { - FIXME("(%p,%p),stub!\n",a,b); - return E_NOTIMPL; + return (IsEqualCLSID(&mt1->type, &mt2->type) || + IsEqualCLSID(&mt2->type, &GUID_NULL) || + IsEqualCLSID(&mt1->type, &GUID_NULL)) && + (IsEqualCLSID(&mt1->subtype, &mt2->subtype) || + IsEqualCLSID(&mt2->subtype, &GUID_NULL) || + IsEqualCLSID(&mt1->subtype, &GUID_NULL)); +} + +/*************************************************************** + * DMORegister + * + * Register a DirectX Media Object. + */ +HRESULT WINAPI DMORegister( + LPCWSTR szName, + REFCLSID clsidDMO, + REFGUID guidCategory, + DWORD dwFlags, + DWORD cInTypes, + const DMO_PARTIAL_MEDIATYPE *pInTypes, + DWORD cOutTypes, + const DMO_PARTIAL_MEDIATYPE *pOutTypes +) +{ + WCHAR szguid[64]; + HRESULT hres; + HKEY hrkey = 0; + HKEY hkey = 0; + HKEY hckey = 0; + HKEY hclskey = 0; + + TRACE("%s\n", debugstr_w(szName)); + + hres = RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, KEY_WRITE, &hrkey); + if (ERROR_SUCCESS != hres) + goto lend; + + /* Create clsidDMO key under MediaObjects */ + hres = RegCreateKeyExW(hrkey, GUIDToString(szguid, clsidDMO), 0, NULL, + REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, NULL); + if (ERROR_SUCCESS != hres) + goto lend; + + /* Set default Name value */ + hres = RegSetValueExW(hkey, NULL, 0, REG_SZ, (LPBYTE) szName, + (strlenW(szName) + 1)) * sizeof(WCHAR); + /* Set InputTypes */ + hres = RegSetValueExW(hkey, szDMOInputType, 0, REG_BINARY, + (LPBYTE) pInTypes, cInTypes * sizeof(DMO_PARTIAL_MEDIATYPE)); + /* Set OutputTypes */ + hres = RegSetValueExW(hkey, szDMOOutputType, 0, REG_BINARY, + (LPBYTE) pOutTypes, cOutTypes * sizeof(DMO_PARTIAL_MEDIATYPE)); + + if (dwFlags & DMO_REGISTERF_IS_KEYED) + { + /* Create Keyed key */ + hres = RegCreateKeyExW(hkey, szDMOKeyed, 0, NULL, + REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hckey, NULL); + if (ERROR_SUCCESS != hres) + goto lend; + RegCloseKey(hckey); + } + + /* Register the category */ + hres = RegOpenKeyExW(hrkey, szDMOCategories, 0, KEY_WRITE, &hckey); + if (ERROR_SUCCESS != hres) + goto lend; + + RegCloseKey(hkey); + + hres = RegOpenKeyExW(hckey, GUIDToString(szguid, guidCategory), 0, KEY_WRITE, &hkey); + if (ERROR_SUCCESS != hres) + goto lend; + hres = RegCreateKeyExW(hkey, GUIDToString(szguid, clsidDMO), 0, NULL, + REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hclskey, NULL); + if (ERROR_SUCCESS != hres) + goto lend; + +lend: + if (hkey) + RegCloseKey(hkey); + if (hckey) + RegCloseKey(hckey); + if (hclskey) + RegCloseKey(hclskey); + if (hrkey) + RegCloseKey(hrkey); + + TRACE(" hresult=0x%08lx\n", hres); + return hres; +} + + +/*************************************************************** + * DMOUnregister + * + * Unregister a DirectX Media Object. + */ +HRESULT WINAPI DMOUnregister(REFCLSID clsidDMO, REFGUID guidCategory) +{ + HRESULT hres; + WCHAR szguid[64]; + HKEY hrkey = 0; + HKEY hckey = 0; + + GUIDToString(szguid, clsidDMO); + + TRACE("%s %p\n", debugstr_w(szguid), guidCategory); + + hres = RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, KEY_WRITE, &hrkey); + if (ERROR_SUCCESS != hres) + goto lend; + + hres = RegDeleteKeyW(hrkey, szguid); + if (ERROR_SUCCESS != hres) + goto lend; + + hres = RegOpenKeyExW(hrkey, szDMOCategories, 0, KEY_WRITE, &hckey); + if (ERROR_SUCCESS != hres) + goto lend; + + hres = RegDeleteKeyW(hckey, szguid); + if (ERROR_SUCCESS != hres) + goto lend; + +lend: + if (hckey) + RegCloseKey(hckey); + if (hrkey) + RegCloseKey(hrkey); + + return hres; +} + + +/*************************************************************** + * DMOGetName + * + * Get DMP Name from the registry + */ +HRESULT WINAPI DMOGetName(REFCLSID clsidDMO, WCHAR* szName) +{ + WCHAR szguid[64]; + HRESULT hres; + HKEY hrkey = 0; + HKEY hkey = 0; + DWORD count; + + TRACE("%s\n", debugstr_guid(clsidDMO)); + + hres = RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, + 0, KEY_READ, &hrkey); + if (ERROR_SUCCESS != hres) + goto lend; + + hres = RegOpenKeyExW(hrkey, GUIDToString(szguid, clsidDMO), + 0, KEY_READ, &hkey); + if (ERROR_SUCCESS != hres) + goto lend; + + count = 80 * sizeof(WCHAR); /* 80 by API definition */ + hres = RegQueryValueExW(hkey, NULL, NULL, NULL, + (LPBYTE) szName, &count); + + TRACE(" szName=%s\n", debugstr_w(szName)); +lend: + if (hkey) + RegCloseKey(hrkey); + if (hkey) + RegCloseKey(hkey); + + return hres; +} + + +/************************************************************************** +* IEnumDMO_Destructor +*/ +static BOOL IEnumDMO_Destructor(IEnumDMO* iface) +{ + ICOM_THIS(IEnumDMOImpl,iface); + + TRACE("%p\n", This); + + if (This->hkey) + RegCloseKey(This->hkey); + + if (This->pInTypes) + HeapFree(GetProcessHeap(), 0, This->pInTypes); + + if (This->pOutTypes) + HeapFree(GetProcessHeap(), 0, This->pOutTypes); + + return TRUE; +} + + +/************************************************************************** + * IEnumDMO_Constructor + */ +IEnumDMO * IEnumDMO_Constructor( + REFGUID guidCategory, + DWORD dwFlags, + DWORD cInTypes, + const DMO_PARTIAL_MEDIATYPE *pInTypes, + DWORD cOutTypes, + const DMO_PARTIAL_MEDIATYPE *pOutTypes) +{ + UINT size; + IEnumDMOImpl* lpedmo; + BOOL ret = FALSE; + + lpedmo = (IEnumDMOImpl*)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, sizeof(IEnumDMOImpl)); + + if (lpedmo) + { + lpedmo->ref = 1; + lpedmo->lpVtbl = &edmovt; + lpedmo->index = -1; + lpedmo->guidCategory = guidCategory; + lpedmo->dwFlags = dwFlags; + + size = cInTypes * sizeof(DMO_PARTIAL_MEDIATYPE); + lpedmo->pInTypes = HeapAlloc(GetProcessHeap(), 0, size); + if (!lpedmo->pInTypes) + goto lerr; + memcpy(lpedmo->pInTypes, pInTypes, size); + lpedmo->cInTypes = cInTypes; + + size = cOutTypes * sizeof(DMO_PARTIAL_MEDIATYPE); + lpedmo->pOutTypes = HeapAlloc(GetProcessHeap(), 0, size); + if (!lpedmo->pOutTypes) + goto lerr; + memcpy(lpedmo->pOutTypes, pOutTypes, size); + lpedmo->cOutTypes = cOutTypes; + + /* If not filtering by category enum from media objects root */ + if (IsEqualGUID(guidCategory, &GUID_NULL)) + { + if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, + 0, KEY_READ, &lpedmo->hkey)) + ret = TRUE; + } + else + { + WCHAR szguid[64]; + WCHAR szKey[MAX_PATH]; + + wsprintfW(szKey, szCat3Fmt, szDMORootKey, szDMOCategories, + GUIDToString(szguid, guidCategory)); + if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, + 0, KEY_READ, &lpedmo->hkey)) + ret = TRUE; + } + +lerr: + if(!ret) + { + IEnumDMO_Destructor((IEnumDMO*)lpedmo); + HeapFree(GetProcessHeap(),0,lpedmo); + lpedmo = NULL; + } + } + + TRACE("returning %p\n", lpedmo); + + return (IEnumDMO*)lpedmo; +} + + +/****************************************************************************** + * IEnumDMO_fnAddRef + */ +static ULONG WINAPI IEnumDMO_fnAddRef(IEnumDMO * iface) +{ + ICOM_THIS(IEnumDMOImpl,iface); + return ++(This->ref); +} + + +/************************************************************************** + * EnumDMO_QueryInterface + */ +static HRESULT WINAPI IEnumDMO_fnQueryInterface( + IEnumDMO* iface, + REFIID riid, + LPVOID *ppvObj) +{ + ICOM_THIS(IEnumDMOImpl,iface); + + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IUnknown)) + *ppvObj = This; + else if(IsEqualIID(riid, &IID_IEnumDMO)) + *ppvObj = (IEnumDMO*)This; + + if(*ppvObj) + { + IEnumDMO_fnAddRef((IEnumDMO*)*ppvObj); + return S_OK; + } + + return E_NOINTERFACE; +} + + +/****************************************************************************** + * IEnumDMO_fnRelease + */ +static ULONG WINAPI IEnumDMO_fnRelease(IEnumDMO * iface) +{ + ICOM_THIS(IEnumDMOImpl,iface); + + if (!--(This->ref)) + { + IEnumDMO_Destructor((IEnumDMO*)This); + HeapFree(GetProcessHeap(),0,This); + return 0; + } + + return This->ref; +} + + +/****************************************************************************** + * IEnumDMO_fnNext + */ +static HRESULT WINAPI IEnumDMO_fnNext( + IEnumDMO * iface, + DWORD cItemsToFetch, + CLSID * pCLSID, + WCHAR ** Names, + DWORD * pcItemsFetched) +{ + FILETIME ft; + HKEY hkey; + WCHAR szNextKey[MAX_PATH]; + WCHAR szKey[MAX_PATH]; + WCHAR szValue[MAX_PATH]; + DWORD len; + UINT count = 0; + HRESULT hres = S_OK; + + ICOM_THIS(IEnumDMOImpl,iface); + + TRACE("%ld\n", cItemsToFetch); + + if (!pCLSID || !Names || !pcItemsFetched) + return E_POINTER; + + while (count < (INT)cItemsToFetch) + { + This->index++; + + hres = RegEnumKeyExW(This->hkey, This->index, szNextKey, &len, NULL, NULL, NULL, &ft); + if (hres != ERROR_SUCCESS) + break; + + TRACE("found %s\n", debugstr_w(szNextKey)); + + if (This->dwFlags & DMO_REGISTERF_IS_KEYED) + { + wsprintfW(szKey, szCat3Fmt, szDMORootKey, szNextKey, szDMOKeyed); + hres = RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hkey); + if (ERROR_SUCCESS != hres) + continue; + RegCloseKey(hkey); + } + + wsprintfW(szKey, szCat2Fmt, szDMORootKey, szNextKey); + hres = RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hkey); + + if (This->pInTypes) + { + INT i, j; + DWORD cInTypes; + DMO_PARTIAL_MEDIATYPE* pInTypes; + + len = MAX_PATH * sizeof(WCHAR); + hres = RegQueryValueExW(hkey, szDMOInputType, NULL, NULL, (LPBYTE) szValue, &len); + if (ERROR_SUCCESS != hres) + { + RegCloseKey(hkey); + continue; + } + + cInTypes = len / sizeof(DMO_PARTIAL_MEDIATYPE); + pInTypes = (DMO_PARTIAL_MEDIATYPE*) szValue; + + for (i = 0; i < This->cInTypes; i++) + { + for (j = 0; j < cInTypes; j++) + { + if (IsMediaTypeEqual(&pInTypes[j], &This->pInTypes[i])) + break; + } + + if (j >= cInTypes) + break; + } + + if (i < This->cInTypes) + { + RegCloseKey(hkey); + continue; + } + } + + if (This->pOutTypes) + { + INT i, j; + DWORD cOutTypes; + DMO_PARTIAL_MEDIATYPE* pOutTypes; + + len = MAX_PATH * sizeof(WCHAR); + hres = RegQueryValueExW(hkey, szDMOOutputType, NULL, NULL, (LPBYTE) szValue, &len); + if (ERROR_SUCCESS != hres) + { + RegCloseKey(hkey); + continue; + } + + cOutTypes = len / sizeof(DMO_PARTIAL_MEDIATYPE); + pOutTypes = (DMO_PARTIAL_MEDIATYPE*) szValue; + + for (i = 0; i < This->cOutTypes; i++) + { + for (j = 0; j < cOutTypes; j++) + { + if (IsMediaTypeEqual(&pOutTypes[j], &This->pOutTypes[i])) + break; + } + + if (j >= cOutTypes) + break; + } + + if (i < This->cOutTypes) + { + RegCloseKey(hkey); + continue; + } + } + + /* Media object wasn't filtered so add it to return list */ + Names[count] = NULL; + len = MAX_PATH * sizeof(WCHAR); + hres = RegQueryValueExW(hkey, NULL, NULL, NULL, (LPBYTE) szValue, &len); + if (ERROR_SUCCESS == hres) + { + Names[count] = HeapAlloc(GetProcessHeap(), 0, strlenW(szValue) + 1); + if (Names[count]) + strcmpW(Names[count], szValue); + } + CLSIDFromString(szNextKey, &pCLSID[count]); + + TRACE("found match %s %s\n", debugstr_w(szValue), debugstr_w(szNextKey)); + RegCloseKey(hkey); + count++; + } + + *pcItemsFetched = count; + if (*pcItemsFetched < cItemsToFetch) + hres = S_FALSE; + + return hres; +} + + +/****************************************************************************** + * IEnumDMO_fnSkip + */ +static HRESULT WINAPI IEnumDMO_fnSkip(IEnumDMO * iface, DWORD cItemsToSkip) +{ + ICOM_THIS(IEnumDMOImpl,iface); + + This->index += cItemsToSkip; + + return S_OK; } -HRESULT WINAPI DMOEnum(REFGUID guidCategory, DWORD dwFlags, DWORD cInTypes, - const DMO_PARTIAL_MEDIATYPE*pInTypes, DWORD cOutTypes, - const DMO_PARTIAL_MEDIATYPE*pOutTypes,IEnumDMO**ppEnum) -{ - FIXME("(%s,0x%lX,%lu,%p,%lu,%p,%p),stub!\n",debugstr_guid(guidCategory), - dwFlags,cInTypes,pInTypes,cOutTypes,pOutTypes,ppEnum); - - if (guidCategory == NULL || ppEnum == NULL) - return E_FAIL; - if (dwFlags != 0 && dwFlags != DMO_ENUMF_INCLUDE_KEYED) - return E_FAIL; - *ppEnum = NULL; +/****************************************************************************** + * IEnumDMO_fnReset + */ +static HRESULT WINAPI IEnumDMO_fnReset(IEnumDMO * iface) +{ + ICOM_THIS(IEnumDMOImpl,iface); + + This->index = -1; + + return S_OK; +} + + +/****************************************************************************** + * IEnumDMO_fnClone + */ +static HRESULT WINAPI IEnumDMO_fnClone(IEnumDMO * iface, IEnumDMO **ppEnum) +{ + ICOM_THIS(IEnumDMOImpl,iface); + + FIXME("(%p)->() to (%p)->() E_NOTIMPL\n", This, ppEnum); return E_NOTIMPL; } + +/*************************************************************** + * DMOEnum + * + * Enumerate DirectX Media Objects in the registry. + */ +HRESULT WINAPI DMOEnum( + REFGUID guidCategory, + DWORD dwFlags, + DWORD cInTypes, + const DMO_PARTIAL_MEDIATYPE *pInTypes, + DWORD cOutTypes, + const DMO_PARTIAL_MEDIATYPE *pOutTypes, + IEnumDMO **ppEnum) +{ + HRESULT hres = E_FAIL; + + TRACE("guidCategory=%p dwFlags=0x%08lx cInTypes=%ld cOutTypes=%ld\n", + guidCategory, dwFlags, cInTypes, cOutTypes); + + *ppEnum = IEnumDMO_Constructor(guidCategory, dwFlags, cInTypes, + pInTypes, cOutTypes, pOutTypes); + if (*ppEnum) + hres = S_OK; + + return hres; +} + + +static ICOM_VTABLE (IEnumDMO) edmovt = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + IEnumDMO_fnQueryInterface, + IEnumDMO_fnAddRef, + IEnumDMO_fnRelease, + IEnumDMO_fnNext, + IEnumDMO_fnSkip, + IEnumDMO_fnReset, + IEnumDMO_fnClone, +}; + + HRESULT WINAPI DMOGetTypes(REFCLSID a, unsigned long b, unsigned long* c, DMO_PARTIAL_MEDIATYPE* d, unsigned long e, unsigned long* f, DMO_PARTIAL_MEDIATYPE* g) @@ -73,14 +669,5 @@ return E_NOTIMPL; } -HRESULT WINAPI DMOGetName(REFCLSID pclsid, WCHAR* pstr) -{ - FIXME("(%s,%p),stub!\n", debugstr_guid(pclsid), pstr); - - if (pclsid == NULL || pstr == NULL) - return E_FAIL; - pstr[0] = '\0'; - return E_NOTIMPL; -} Index: include/mediaobj.h =================================================================== RCS file: /home/wine/wine/include/mediaobj.h,v retrieving revision 1.4 diff -u -w -r1.4 mediaobj.h --- include/mediaobj.h 28 Aug 2003 21:43:35 -0000 1.4 +++ include/mediaobj.h 24 Nov 2003 16:17:56 -0000 @@ -49,4 +49,15 @@ BYTE *pbFormat; } DMO_MEDIA_TYPE; +#define INTERFACE IEnumDMO +#define IEnumDMO_METHODS \ + IUnknown_METHODS \ + STDMETHOD(Next)(THIS_ DWORD cItemsToFetch, CLSID * pCLSID, \ + WCHAR ** Names, DWORD * pcItemsFectched) PURE; \ + STDMETHOD(Skip)(THIS_ DWORD cItemsToSkip) PURE; \ + STDMETHOD(Reset)(THIS) PURE; \ + STDMETHOD(Clone)(THIS_ IEnumDMO ** ppEnum) PURE; +ICOM_DEFINE(IEnumDMO,IUnknown) +#undef INTERFACE + #endif /* __mediaobj_h__ */