[PATCH] test.patch

Fabian Maurer dark.shadow4 at web.de
Sun Sep 10 10:16:03 CDT 2017


---
 configure                  |   1 +
 configure.ac               |   1 +
 dlls/evr/Makefile.in       |   4 +
 dlls/evr/evr.c             | 240 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/evr/evr.spec          |   8 +-
 dlls/evr/evr_classes.idl   |  28 ++++++
 dlls/evr/evr_private.h     |  28 ++++++
 dlls/evr/main.c            | 158 +++++++++++++++++++++++++++++
 dlls/evr/tests/Makefile.in |   5 +
 dlls/evr/tests/filter.c    | 185 ++++++++++++++++++++++++++++++++++
 dlls/strmiids/strmiids.c   |   4 +
 include/Makefile.in        |   1 +
 include/dxva2api.idl       |  25 +++++
 include/evr.idl            |  94 ++++++++++++++++++
 include/mfidl.idl          |  40 ++++++++
 15 files changed, 818 insertions(+), 4 deletions(-)
 create mode 100644 dlls/evr/evr.c
 create mode 100644 dlls/evr/evr_classes.idl
 create mode 100644 dlls/evr/evr_private.h
 create mode 100644 dlls/evr/tests/Makefile.in
 create mode 100644 dlls/evr/tests/filter.c
 create mode 100644 include/evr.idl

diff --git a/configure b/configure
index 47a41cdfec..4be2161598 100755
--- a/configure
+++ b/configure
@@ -18325,6 +18325,7 @@ wine_fn_config_lib dxguid
 wine_fn_config_dll dxva2 enable_dxva2
 wine_fn_config_dll esent enable_esent
 wine_fn_config_dll evr enable_evr
+wine_fn_config_test dlls/evr/tests evr_test
 wine_fn_config_dll explorerframe enable_explorerframe clean
 wine_fn_config_test dlls/explorerframe/tests explorerframe_test
 wine_fn_config_dll ext-ms-win-authz-context-l1-1-0 enable_ext_ms_win_authz_context_l1_1_0
diff --git a/configure.ac b/configure.ac
index cd5a50bb02..2036aec6f9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3115,6 +3115,7 @@ WINE_CONFIG_LIB(dxguid)
 WINE_CONFIG_DLL(dxva2)
 WINE_CONFIG_DLL(esent)
 WINE_CONFIG_DLL(evr)
+WINE_CONFIG_TEST(dlls/evr/tests)
 WINE_CONFIG_DLL(explorerframe,,[clean])
 WINE_CONFIG_TEST(dlls/explorerframe/tests)
 WINE_CONFIG_DLL(ext-ms-win-authz-context-l1-1-0)
diff --git a/dlls/evr/Makefile.in b/dlls/evr/Makefile.in
index 25cc961270..9e4da8217b 100644
--- a/dlls/evr/Makefile.in
+++ b/dlls/evr/Makefile.in
@@ -1,4 +1,8 @@
 MODULE    = evr.dll
+IMPORTS   = strmiids strmbase uuid ole32 oleaut32
 
 C_SRCS = \
+	evr.c \
 	main.c
+
+IDL_SRCS = evr_classes.idl
diff --git a/dlls/evr/evr.c b/dlls/evr/evr.c
new file mode 100644
index 0000000000..f5df08a17b
--- /dev/null
+++ b/dlls/evr/evr.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2017 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include "config.h"
+#include "wine/debug.h"
+
+#include <stdio.h>
+
+#include "evr_private.h"
+#include "d3d9.h"
+#include "wine/strmbase.h"
+
+#include "initguid.h"
+#include "dxva2api.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(evr);
+
+typedef struct
+{
+    BaseFilter basefilter;
+
+    IUnknown IUnknown_inner;
+    LONG ref;
+} evr_impl;
+
+static inline evr_impl *impl_from_inner_IUnknown(IUnknown *iface)
+{
+    return CONTAINING_RECORD(iface, evr_impl, IUnknown_inner);
+}
+
+static HRESULT WINAPI impl_inner_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+{
+    evr_impl *This = impl_from_inner_IUnknown(iface);
+    TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
+
+    *ppv = NULL;
+
+     if (IsEqualIID(riid, &IID_IUnknown))
+         *ppv = &This->IUnknown_inner;
+
+     else if (IsEqualIID(riid, &IID_IAMCertifiedOutputProtection))
+         FIXME("No interface for IID_IAMCertifiedOutputProtection\n");
+     else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
+         FIXME("No interface for IID_IAMFilterMiscFlags\n");
+     else if (IsEqualIID(riid, &IID_IBaseFilter))
+         *ppv =&This->basefilter.IBaseFilter_iface;
+     else if (IsEqualIID(riid, &IID_IMediaFilter))
+         *ppv =&This->basefilter.IBaseFilter_iface;
+     else if (IsEqualIID(riid, &IID_IPersist))
+         *ppv =&This->basefilter.IBaseFilter_iface;
+     else if (IsEqualIID(riid, &IID_IKsPropertySet))
+         FIXME("No interface for IID_IKsPropertySet\n");
+     else if (IsEqualIID(riid, &IID_IMediaEventSink))
+         FIXME("No interface for IID_IMediaEventSink\n");
+     else if (IsEqualIID(riid, &IID_IMediaSeeking))
+         FIXME("No interface for IID_IMediaSeeking\n");
+     else if (IsEqualIID(riid, &IID_IQualityControl))
+         FIXME("No interface for IID_IQualityControl\n");
+     else if (IsEqualIID(riid, &IID_IQualProp))
+         FIXME("No interface for IID_IQualProp\n");
+
+     else if (IsEqualIID(riid, &IID_IEVRFilterConfig))
+         FIXME("No interface for IID_IEVRFilterConfig\n");
+     else if (IsEqualIID(riid, &IID_IMFGetService))
+         FIXME("No interface for IID_IMFGetService\n");
+     else if (IsEqualIID(riid, &IID_IMFVideoPositionMapper))
+         FIXME("No interface for IID_IMFVideoPositionMapper\n");
+     else if (IsEqualIID(riid, &IID_IMFVideoRenderer))
+         FIXME("No interface for IID_IMFVideoRenderer\n");
+
+     else if (IsEqualIID(riid, &IID_IMemInputPin))
+         FIXME("No interface for IID_IMemInputPin\n");
+     else if (IsEqualIID(riid, &IID_IPin))
+         FIXME("No interface for IID_IPin\n");
+     else if (IsEqualIID(riid, &IID_IQualityControl))
+         FIXME("No interface for IID_IQualityControl\n");
+
+     else if (IsEqualIID(riid, &IID_IDirectXVideoMemoryConfiguration))
+         FIXME("No interface for IID_IDirectXVideoMemoryConfiguration\n");
+
+    if (*ppv)
+    {
+        IUnknown_AddRef((IUnknown *)(*ppv));
+        return S_OK;
+    }
+
+    ERR("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppv);
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI impl_inner_AddRef(IUnknown *iface)
+{
+    evr_impl *This = impl_from_inner_IUnknown(iface);
+    ULONG ref = InterlockedIncrement(&This->ref);
+
+    TRACE("(%p, %p)->(): new ref %d\n", iface, This, ref);
+
+    return ref;
+}
+
+static ULONG WINAPI impl_inner_Release(IUnknown *iface)
+{
+    evr_impl *This = impl_from_inner_IUnknown(iface);
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p, %p)->(): new ref %d\n", iface, This, ref);
+
+    if (!ref)
+    {
+        BaseFilter_Destroy(&This->basefilter);
+        CoTaskMemFree(This);
+    }
+
+    return ref;
+}
+
+static const IUnknownVtbl evr_inner_vtbl =
+{
+    impl_inner_QueryInterface,
+    impl_inner_AddRef,
+    impl_inner_Release
+};
+
+static inline evr_impl *impl_from_IBaseFilter(IBaseFilter *iface)
+{
+    return CONTAINING_RECORD(iface, evr_impl, basefilter);
+}
+
+static HRESULT WINAPI filter_QueryInterface(IBaseFilter *iface, REFIID riid, void **ppv)
+{
+    evr_impl *This = impl_from_IBaseFilter(iface);
+    return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
+}
+
+static ULONG WINAPI filter_AddRef(IBaseFilter *iface)
+{
+    evr_impl *This = impl_from_IBaseFilter(iface);
+    LONG ret;
+
+    ret = IUnknown_AddRef(&This->IUnknown_inner);
+
+    TRACE("(%p)->AddRef from %d\n", iface, ret - 1);
+
+    return ret;
+}
+
+static ULONG WINAPI filter_Release(IBaseFilter *iface)
+{
+    evr_impl *This = impl_from_IBaseFilter(iface);
+    LONG ret;
+
+    ret = IUnknown_Release(&This->IUnknown_inner);
+
+    TRACE("(%p)->Release from %d\n", iface, ret + 1);
+
+    return ret;
+}
+
+static const IBaseFilterVtbl basefilter_vtbl =
+{
+    filter_QueryInterface,
+    filter_AddRef,
+    filter_Release,
+    BaseFilterImpl_GetClassID,
+    BaseRendererImpl_Stop,
+    BaseRendererImpl_Pause,
+    BaseRendererImpl_Run,
+    BaseRendererImpl_GetState,
+    BaseRendererImpl_SetSyncSource,
+    BaseFilterImpl_GetSyncSource,
+    BaseFilterImpl_EnumPins,
+    BaseRendererImpl_FindPin,
+    BaseFilterImpl_QueryFilterInfo,
+    BaseFilterImpl_JoinFilterGraph,
+    BaseFilterImpl_QueryVendorInfo
+};
+
+static IPin* WINAPI filter_GetPin(BaseFilter *iface, int position)
+{
+    FIXME("(%p, %d): stub!\n", iface, position);
+    return NULL;
+}
+
+static LONG WINAPI filter_GetPinCount(BaseFilter *iface)
+{
+    FIXME("(%p): stub!\n", iface);
+    return 0;
+}
+
+static const BaseFilterFuncTable basefilter_functable =
+{
+    filter_GetPin,
+    filter_GetPinCount,
+};
+
+HRESULT evr_impl_create(IUnknown *outer_unk, void **ppv)
+{
+    evr_impl *object;
+
+    TRACE("(%p, %p)\n", outer_unk, ppv);
+
+    *ppv = NULL;
+
+    if(outer_unk != NULL)
+    {
+        FIXME("Aggregation yet unsupported!\n");
+        return E_NOINTERFACE;
+    }
+
+    object = CoTaskMemAlloc(sizeof(evr_impl));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    BaseFilter_Init(&object->basefilter, &basefilter_vtbl, &CLSID_EnhancedVideoRenderer,
+                    (DWORD_PTR)(__FILE__ ": EVR.csFilter"), &basefilter_functable);
+
+    object->IUnknown_inner.lpVtbl = &evr_inner_vtbl;
+    object->ref = 1;
+
+    *ppv = &object->IUnknown_inner;
+
+    return S_OK;
+}
diff --git a/dlls/evr/evr.spec b/dlls/evr/evr.spec
index 3f609b6037..c78900c576 100644
--- a/dlls/evr/evr.spec
+++ b/dlls/evr/evr.spec
@@ -1,7 +1,7 @@
-@ stub DllCanUnloadNow
-@ stub DllGetClassObject
-@ stub DllRegisterServer
-@ stub DllUnregisterServer
+@ stdcall -private DllCanUnloadNow()
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
+@ stdcall -private DllRegisterServer()
+@ stdcall -private DllUnregisterServer()
 @ stub MFConvertColorInfoFromDXVA
 @ stub MFConvertColorInfoToDXVA
 @ stub MFConvertFromFP16Array
diff --git a/dlls/evr/evr_classes.idl b/dlls/evr/evr_classes.idl
new file mode 100644
index 0000000000..20a346ac67
--- /dev/null
+++ b/dlls/evr/evr_classes.idl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#pragma makedep register
+
+#include "strmif.idl"
+
+[
+    helpstring("Enhanced Video Renderer"),
+    threading(both),
+    uuid(fa10746c-9b63-4b6c-bc49-fc300ea5f256)
+]
+coclass EnhancedVideoRenderer { interface IBaseFilter; }
diff --git a/dlls/evr/evr_private.h b/dlls/evr/evr_private.h
new file mode 100644
index 0000000000..32a0e94cbe
--- /dev/null
+++ b/dlls/evr/evr_private.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __EVR_PRIVATE_INCLUDED__
+#define __EVR_PRIVATE_INCLUDED__
+
+#include "dshow.h"
+#include "evr.h"
+
+HRESULT evr_impl_create(IUnknown *outer_unk, void **ppv) DECLSPEC_HIDDEN;
+
+
+#endif /* __EVR_PRIVATE_INCLUDED__ */
diff --git a/dlls/evr/main.c b/dlls/evr/main.c
index 1b223adc11..acc5c923eb 100644
--- a/dlls/evr/main.c
+++ b/dlls/evr/main.c
@@ -15,6 +15,9 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
+
+#define COBJMACROS
+
 #include "config.h"
 
 #include <stdarg.h>
@@ -22,16 +25,171 @@
 #include "windef.h"
 #include "winbase.h"
 
+#include "ole2.h"
+#include "rpcproxy.h"
+
+#include "evr_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(evr);
+
+static HINSTANCE instance_evr;
+
 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
 {
+    TRACE("(%p, %d, %p)\n", instance, reason, reserved);
+
     switch (reason)
     {
         case DLL_WINE_PREATTACH:
             return FALSE;    /* prefer native version */
         case DLL_PROCESS_ATTACH:
+            instance_evr = instance;
             DisableThreadLibraryCalls(instance);
             break;
     }
 
     return TRUE;
 }
+
+typedef struct {
+    IClassFactory IClassFactory_iface;
+
+    LONG ref;
+    HRESULT (*pfnCreateInstance)(IUnknown *unk_outer, void **ppobj);
+} IClassFactoryImpl;
+
+static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
+{
+    return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
+}
+
+struct object_creation_info
+{
+    const CLSID *clsid;
+    HRESULT (*pfnCreateInstance)(IUnknown *unk_outer, void **ppobj);
+};
+
+static const struct object_creation_info object_creation[] =
+{
+    { &CLSID_EnhancedVideoRenderer, evr_impl_create },
+};
+
+static HRESULT WINAPI classfactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
+{
+    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
+
+    if (IsEqualGUID(riid, &IID_IUnknown)
+        || IsEqualGUID(riid, &IID_IClassFactory))
+    {
+        IClassFactory_AddRef(iface);
+        *ppobj = &This->IClassFactory_iface;
+        return S_OK;
+    }
+
+    WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI classfactory_AddRef(IClassFactory *iface)
+{
+    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI classfactory_Release(IClassFactory *iface)
+{
+    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    if (ref == 0)
+        HeapFree(GetProcessHeap(), 0, This);
+
+    return ref;
+}
+
+static HRESULT WINAPI classfactory_CreateInstance(IClassFactory *iface, IUnknown *outer_unk, REFIID riid, void **ppobj)
+{
+    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
+    HRESULT hres;
+    IUnknown *unk;
+
+    TRACE("(%p)->(%p,%s,%p)\n", This, outer_unk, debugstr_guid(riid), ppobj);
+
+    *ppobj = NULL;
+    hres = This->pfnCreateInstance(outer_unk, (void **) &unk);
+    if (SUCCEEDED(hres))
+    {
+        hres = IUnknown_QueryInterface(unk, riid, ppobj);
+        IUnknown_Release(unk);
+    }
+    return hres;
+}
+
+static HRESULT WINAPI classfactory_LockServer(IClassFactory *iface, BOOL dolock)
+{
+    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
+    FIXME("(%p)->(%d), stub!\n", This, dolock);
+    return S_OK;
+}
+
+static const IClassFactoryVtbl classfactory_Vtbl =
+{
+    classfactory_QueryInterface,
+    classfactory_AddRef,
+    classfactory_Release,
+    classfactory_CreateInstance,
+    classfactory_LockServer
+};
+
+HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
+{
+    unsigned int i;
+    IClassFactoryImpl *factory;
+
+    TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+
+    if (!IsEqualGUID(&IID_IClassFactory, riid)
+         && !IsEqualGUID( &IID_IUnknown, riid))
+        return E_NOINTERFACE;
+
+    for (i = 0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
+    {
+        if (IsEqualGUID(object_creation[i].clsid, rclsid))
+            break;
+    }
+
+    if (i == sizeof(object_creation)/sizeof(object_creation[0]))
+    {
+        FIXME("%s: no class found.\n", debugstr_guid(rclsid));
+        return CLASS_E_CLASSNOTAVAILABLE;
+    }
+
+    factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
+    if (factory == NULL)
+        return E_OUTOFMEMORY;
+
+    factory->IClassFactory_iface.lpVtbl = &classfactory_Vtbl;
+    factory->ref = 1;
+
+    factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
+
+    *ppv = &(factory->IClassFactory_iface);
+    return S_OK;
+}
+
+HRESULT WINAPI DllCanUnloadNow(void)
+{
+    return S_FALSE;
+}
+
+HRESULT WINAPI DllRegisterServer(void)
+{
+    return __wine_register_resources(instance_evr);
+}
+
+HRESULT WINAPI DllUnregisterServer(void)
+{
+    return __wine_unregister_resources(instance_evr);
+}
diff --git a/dlls/evr/tests/Makefile.in b/dlls/evr/tests/Makefile.in
new file mode 100644
index 0000000000..11ae496390
--- /dev/null
+++ b/dlls/evr/tests/Makefile.in
@@ -0,0 +1,5 @@
+TESTDLL   = evr.dll
+IMPORTS   = strmiids strmbase uuid ole32 oleaut32
+
+C_SRCS = \
+	filter.c
diff --git a/dlls/evr/tests/filter.c b/dlls/evr/tests/filter.c
new file mode 100644
index 0000000000..4f82b14ddd
--- /dev/null
+++ b/dlls/evr/tests/filter.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2017 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include <stdio.h>
+
+#include "dshow.h"
+#include "evr.h"
+#include "d3d9.h"
+#include "initguid.h"
+#include "dxva2api.h"
+
+#include "wine/test.h"
+
+#define QI_SUCCEED(iface, riid, ppv) hr = IUnknown_QueryInterface(iface, &riid, (LPVOID*)&ppv); \
+    ok(hr == S_OK, "%s: run %d: IUnknown_QueryInterface returned %x\n", testid, testrun, hr); \
+    ok(ppv != NULL, "%s: run %d: Pointer is NULL\n", testid, testrun);
+
+#define QI_FAIL(iface, riid, ppv) hr = IUnknown_QueryInterface(iface, &riid, (LPVOID*)&ppv); \
+    ok(hr == E_NOINTERFACE, "%s: run %d: IUnknown_QueryInterface returned %x\n", testid, testrun, hr); \
+    ok(ppv == NULL, "%s: run %d: Pointer is %p\n", testid, testrun, ppv);
+
+#define ADDREF_EXPECT(iface, num) if (iface) { \
+    refCount = IUnknown_AddRef(iface); \
+    ok(refCount == num, "%s: run %d: IUnknown_AddRef should return %d, got %d\n", testid, testrun, num, refCount); \
+}
+
+#define RELEASE_EXPECT(iface, num) if (iface) { \
+    refCount = IUnknown_Release(iface); \
+    ok(refCount == num, "%s: run %d: IUnknown_Release should return %d, got %d\n", testid, testrun, num, refCount); \
+}
+
+static void test_aggregation(const CLSID clsid_inner, const IID iid_inner, const char *testid, int testrun)
+{
+    const CLSID clsid_outer = CLSID_SystemClock;
+    const IID iid_outer = IID_IReferenceClock;
+    HRESULT hr;
+    ULONG refCount;
+    IUnknown *unk_outer = NULL;
+    IUnknown *unk_inner = NULL;
+    IUnknown *unk_inner_fail = NULL;
+    IUnknown *unk_outer_test = NULL;
+    IUnknown *unk_inner_test = NULL;
+    IUnknown *unk_aggregatee = NULL;
+    IUnknown *unk_aggregator = NULL;
+    IUnknown *unk_test = NULL;
+
+    hr = CoCreateInstance(&clsid_outer, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (LPVOID*)&unk_outer);
+    ok(hr == S_OK, "%s: run %d: First CoCreateInstance failed with %x\n", testid, testrun, hr);
+    ok(unk_outer != NULL, "%s: run %d: unk_outer is NULL\n", testid, testrun);
+
+    if (!unk_outer)
+    {
+        skip("%s: run %d: unk_outer is NULL\n", testid, testrun);
+        return;
+    }
+
+    /* for aggregation, we should only be able to request IUnknown */
+    hr = CoCreateInstance(&clsid_inner, unk_outer, CLSCTX_INPROC_SERVER, &iid_inner, (LPVOID*)&unk_inner_fail);
+    if (hr == REGDB_E_CLASSNOTREG)
+    {
+        skip("%s: run %d: Class not registered\n", testid, testrun);
+        return;
+    }
+    ok(hr == E_NOINTERFACE, "%s: run %d: Second CoCreateInstance returned %x\n", testid, testrun, hr);
+    ok(unk_inner_fail == NULL, "%s: run %d: unk_inner_fail is not NULL\n", testid, testrun);
+
+    /* aggregation, request IUnknown */
+    hr = CoCreateInstance(&clsid_inner, unk_outer, CLSCTX_INPROC_SERVER, &IID_IUnknown, (LPVOID*)&unk_inner);
+    ok(hr == S_OK, "%s: run %d: Third CoCreateInstance returned %x\n", testid, testrun, hr);
+    ok(unk_inner != NULL, "%s: run %d: unk_inner is NULL\n", testid, testrun);
+
+    if (!unk_inner)
+    {
+        skip("%s: run %d: unk_inner is NULL\n", testid, testrun);
+        return;
+    }
+
+    ADDREF_EXPECT(unk_outer, 2);
+    ADDREF_EXPECT(unk_inner, 2);
+    RELEASE_EXPECT(unk_outer, 1);
+    RELEASE_EXPECT(unk_inner, 1);
+
+    QI_FAIL(unk_outer, iid_inner, unk_aggregatee);
+    QI_FAIL(unk_inner, iid_outer, unk_aggregator);
+
+    QI_SUCCEED(unk_outer, iid_outer, unk_aggregator);
+    QI_SUCCEED(unk_outer, IID_IUnknown, unk_outer_test);
+    QI_SUCCEED(unk_inner, iid_inner, unk_aggregatee);
+    QI_SUCCEED(unk_inner, IID_IUnknown, unk_inner_test);
+
+    if (!unk_aggregator || !unk_outer_test || !unk_aggregatee || !unk_inner_test)
+    {
+        skip("%s: run %d: One of the required interfaces is NULL\n", testid, testrun);
+        return;
+    }
+
+    ADDREF_EXPECT(unk_aggregator, 5);
+    ADDREF_EXPECT(unk_outer_test, 6);
+    ADDREF_EXPECT(unk_aggregatee, 7);
+    ADDREF_EXPECT(unk_inner_test, 3);
+    RELEASE_EXPECT(unk_aggregator, 6);
+    RELEASE_EXPECT(unk_outer_test, 5);
+    RELEASE_EXPECT(unk_aggregatee, 4);
+    RELEASE_EXPECT(unk_inner_test, 2);
+
+    QI_SUCCEED(unk_aggregator, IID_IUnknown, unk_test);
+    QI_SUCCEED(unk_outer_test, IID_IUnknown, unk_test);
+    QI_SUCCEED(unk_aggregatee, IID_IUnknown, unk_test);
+    QI_SUCCEED(unk_inner_test, IID_IUnknown, unk_test);
+
+    QI_FAIL(unk_aggregator, iid_inner, unk_test);
+    QI_FAIL(unk_outer_test, iid_inner, unk_test);
+    QI_FAIL(unk_aggregatee, iid_inner, unk_test);
+    QI_SUCCEED(unk_inner_test, iid_inner, unk_test);
+
+    QI_SUCCEED(unk_aggregator, iid_outer, unk_test);
+    QI_SUCCEED(unk_outer_test, iid_outer, unk_test);
+    QI_SUCCEED(unk_aggregatee, iid_outer, unk_test);
+    QI_FAIL(unk_inner_test, iid_outer, unk_test);
+
+    RELEASE_EXPECT(unk_aggregator, 10);
+    RELEASE_EXPECT(unk_outer_test, 9);
+    RELEASE_EXPECT(unk_aggregatee, 8);
+    RELEASE_EXPECT(unk_inner_test, 2);
+    RELEASE_EXPECT(unk_outer, 7);
+    RELEASE_EXPECT(unk_inner, 1);
+
+    do
+    {
+        refCount = IUnknown_Release(unk_inner);
+    } while (refCount);
+
+    do
+    {
+        refCount = IUnknown_Release(unk_outer);
+    } while (refCount);
+}
+
+static void test_evr_filter_aggregations(void)
+{
+    const IID * iids[] = {
+        &IID_IAMCertifiedOutputProtection, &IID_IAMFilterMiscFlags, &IID_IBaseFilter,
+        &IID_IKsPropertySet, &IID_IMediaEventSink, &IID_IMediaSeeking, &IID_IQualityControl,
+        &IID_IQualProp, &IID_IEVRFilterConfig, &IID_IMFGetService, &IID_IMFVideoPositionMapper,
+        &IID_IMFVideoRenderer, &IID_IQualityControl
+    };
+    int i;
+
+    if(!strcmp(winetest_platform, "wine"))
+    {
+        skip("Not supported yet.\n");
+        return;
+    }
+
+    for (i = 0; i < sizeof(iids) / sizeof(iids[0]); i++)
+    {
+        test_aggregation(CLSID_EnhancedVideoRenderer, *iids[i], "filter", i);
+    }
+}
+
+START_TEST(filter)
+{
+    CoInitialize(NULL);
+
+    test_evr_filter_aggregations();
+
+    CoUninitialize();
+}
diff --git a/dlls/strmiids/strmiids.c b/dlls/strmiids/strmiids.c
index a257a23e9a..7659f52e74 100644
--- a/dlls/strmiids/strmiids.c
+++ b/dlls/strmiids/strmiids.c
@@ -31,6 +31,9 @@
 #include "olectl.h"
 #include "d3d9.h"
 
+/* Don't define those GUIDs here */
+#include "propsys.h"
+
 #include "initguid.h"
 
 #include "uuids.h"
@@ -39,3 +42,4 @@
 #include "amstream.h"
 #include "qedit.h"
 #include "vmr9.h"
+#include "evr.h"
diff --git a/include/Makefile.in b/include/Makefile.in
index 8a774e9b0e..2bd41e976c 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -70,6 +70,7 @@ IDL_SRCS = \
 	dyngraph.idl \
 	endpointvolume.idl \
 	errrec.idl \
+	evr.idl \
 	exdisp.idl \
 	fusion.idl \
 	gameux.idl \
diff --git a/include/dxva2api.idl b/include/dxva2api.idl
index 7a29157036..35cbf828bb 100644
--- a/include/dxva2api.idl
+++ b/include/dxva2api.idl
@@ -292,6 +292,13 @@ typedef struct _DXVA2_VideoSample
     DWORD SampleData;
 } DXVA2_VideoSample;
 
+typedef enum _DXVA2_SurfaceType
+{
+    DXVA2_SurfaceType_DecoderRenderTarget    = 0,
+    DXVA2_SurfaceType_ProcessorRenderTarget  = 1,
+    DXVA2_SurfaceType_D3DRenderTargetTexture = 2,
+} DXVA2_SurfaceType;
+
 interface IDirectXVideoDecoder;
 interface IDirectXVideoProcessor;
 
@@ -525,3 +532,21 @@ interface IDirectXVideoProcessor : IUnknown
         [in] UINT NumSamples,
         [out] HANDLE* pHandleCompleteIDirect3DDeviceManager9);
 };
+
+/*****************************************************************************
+ * IDirectXVideoMemoryConfiguration interface
+ */
+[
+    object,
+    uuid(b7f916dd-db3b-49c1-84d7-e45ef99ec726),
+    local
+]
+interface IDirectXVideoMemoryConfiguration : IUnknown
+{
+    HRESULT GetAvailableSurfaceTypeByIndex(
+        [in] DWORD wTypeIndex,
+        [out] DXVA2_SurfaceType *pdwType);
+
+    HRESULT SetSurfaceType(
+        [in] DXVA2_SurfaceType dwType);
+}
diff --git a/include/evr.idl b/include/evr.idl
new file mode 100644
index 0000000000..e4e036af1a
--- /dev/null
+++ b/include/evr.idl
@@ -0,0 +1,94 @@
+/*
+ * COM Classes for evr
+ *
+ * Copyright 2017 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "strmif.idl";
+import "mfidl.idl";
+
+typedef enum _MFVP_MESSAGE_TYPE {
+    MFVP_MESSAGE_FLUSH               = 0x00000000,
+    MFVP_MESSAGE_INVALIDATEMEDIATYPE = 0x00000001,
+    MFVP_MESSAGE_PROCESSINPUTNOTIFY  = 0x00000002,
+    MFVP_MESSAGE_BEGINSTREAMING      = 0x00000003,
+    MFVP_MESSAGE_ENDSTREAMING        = 0x00000004,
+    MFVP_MESSAGE_ENDOFSTREAM         = 0x00000005,
+    MFVP_MESSAGE_STEP                = 0x00000006,
+    MFVP_MESSAGE_CANCELSTEP          = 0x00000007,
+} MFVP_MESSAGE_TYPE;
+
+[
+    object,
+    uuid(29aff080-182a-4a5d-af3b-448f3a6346cb),
+    local
+]
+interface IMFVideoPresenter : IMFClockStateSink
+{
+    HRESULT ProcessMessage(
+        [in] MFVP_MESSAGE_TYPE eMessage,
+        [in] ULONG_PTR ulParam
+    );
+    HRESULT GetCurrentMediaType(
+        [out] IMFVideoMediaType **ppMediaType
+    );
+}
+
+[
+    object,
+    uuid(83e91e85-82c1-4ea7-801d-85dc50b75086),
+    local
+]
+interface IEVRFilterConfig : IUnknown
+{
+    HRESULT SetNumberOfStreams(
+        [in] DWORD dwMaxStreams
+    );
+    HRESULT GetNumberOfStreams(
+        [out] DWORD *pdwMaxStreams
+    );
+}
+
+[
+    object,
+    uuid(1f6a9f17-e70b-4e24-8ae4-0b2c3ba7a4ae),
+    local
+]
+interface IMFVideoPositionMapper : IUnknown
+{
+    HRESULT MapOutputCoordinateToInputStream(
+        [in] float xOut,
+        [in] float yOut,
+        [in] DWORD dwOutputStreamIndex,
+        [in] DWORD dwInputStreamIndex,
+        [out] float *pxIn,
+        [out] float *pyIn
+    );
+}
+
+[
+    object,
+    uuid(dfdfd197-a9ca-43d8-b341-6af3503792cd),
+    local
+]
+interface IMFVideoRenderer : IUnknown
+{
+    HRESULT InitializeRenderer(
+        [in] IMFTransform *pVideoMixer,
+        [in] IMFVideoPresenter *pVideoPresenter
+    );
+}
diff --git a/include/mfidl.idl b/include/mfidl.idl
index b0fadbada7..10730ccca3 100644
--- a/include/mfidl.idl
+++ b/include/mfidl.idl
@@ -212,6 +212,46 @@ interface IMFStreamDescriptor : IMFAttributes
     HRESULT GetMediaTypeHandler([out] IMFMediaTypeHandler **handler);
 }
 
+[
+    object,
+    uuid(f6696e82-74f7-4f3d-a178-8a5e09c3659f),
+    local
+]
+interface IMFClockStateSink : IUnknown
+{
+    HRESULT OnClockStart(
+        [in] MFTIME hnsSystemTime,
+        [in] LONGLONG llClockStartOffset
+    );
+    HRESULT OnClockStop(
+        [in] MFTIME hnssSystemTime
+    );
+    HRESULT OnClockPause(
+        [in] MFTIME hnsSystemTime
+    );
+    HRESULT OnClockRestart(
+        [in] MFTIME hnsSystemTime
+    );
+    HRESULT OnClockSetRate(
+        [in] MFTIME hnsSystemTime,
+        [in] float flRate
+    );
+}
+
+[
+    object,
+    uuid(fa993888-4383-415a-a930-dd472a8cf6f7),
+    local
+]
+interface IMFGetService : IUnknown
+{
+    HRESULT GetService(
+        [in] REFGUID guidService,
+        [in] REFIID riid,
+        [out] LPVOID *ppvObject
+    );
+}
+
 cpp_quote("HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **session);")
 cpp_quote("HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver);")
 cpp_quote("HRESULT WINAPI MFCreateTopology(IMFTopology **topology);")
-- 
2.14.1




More information about the wine-patches mailing list