Wine-devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
August 2019
- 66 participants
- 557 discussions
30 Aug '19
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
configure | 1 +
configure.ac | 1 +
dlls/mfmediaengine/Makefile.in | 3 +
dlls/mfmediaengine/main.c | 141 +++++++++++++++++++++
dlls/mfmediaengine/mediaengine.idl | 26 ++++
dlls/mfmediaengine/mediaengine_classes.idl | 26 ++++
dlls/mfmediaengine/mfmediaengine.spec | 4 +-
dlls/mfmediaengine/tests/Makefile.in | 5 +
dlls/mfmediaengine/tests/mfmediaengine.c | 65 ++++++++++
9 files changed, 270 insertions(+), 2 deletions(-)
create mode 100644 dlls/mfmediaengine/mediaengine.idl
create mode 100644 dlls/mfmediaengine/mediaengine_classes.idl
create mode 100644 dlls/mfmediaengine/tests/Makefile.in
create mode 100644 dlls/mfmediaengine/tests/mfmediaengine.c
diff --git a/configure b/configure
index 82c3611b40..db7db910c0 100755
--- a/configure
+++ b/configure
@@ -20380,6 +20380,7 @@ wine_fn_config_makefile dlls/mf/tests enable_tests
wine_fn_config_makefile dlls/mf3216 enable_mf3216
wine_fn_config_makefile dlls/mferror enable_mferror
wine_fn_config_makefile dlls/mfmediaengine enable_mfmediaengine
+wine_fn_config_makefile dlls/mfmediaengine/tests enable_tests
wine_fn_config_makefile dlls/mfplat enable_mfplat
wine_fn_config_makefile dlls/mfplat/tests enable_tests
wine_fn_config_makefile dlls/mfplay enable_mfplay
diff --git a/configure.ac b/configure.ac
index ef41e94df6..2dbcaebed4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3359,6 +3359,7 @@ WINE_CONFIG_MAKEFILE(dlls/mf/tests)
WINE_CONFIG_MAKEFILE(dlls/mf3216)
WINE_CONFIG_MAKEFILE(dlls/mferror)
WINE_CONFIG_MAKEFILE(dlls/mfmediaengine)
+WINE_CONFIG_MAKEFILE(dlls/mfmediaengine/tests)
WINE_CONFIG_MAKEFILE(dlls/mfplat)
WINE_CONFIG_MAKEFILE(dlls/mfplat/tests)
WINE_CONFIG_MAKEFILE(dlls/mfplay)
diff --git a/dlls/mfmediaengine/Makefile.in b/dlls/mfmediaengine/Makefile.in
index 1654130574..fc84c48a7e 100644
--- a/dlls/mfmediaengine/Makefile.in
+++ b/dlls/mfmediaengine/Makefile.in
@@ -1,7 +1,10 @@
MODULE = mfmediaengine.dll
IMPORTLIB = mfmediaengine
+IMPORTS = mfuuid uuid
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
main.c
+
+IDL_SRCS = mediaengine_classes.idl
diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c
index 81aaf77e2c..4bca0fe0ba 100644
--- a/dlls/mfmediaengine/main.c
+++ b/dlls/mfmediaengine/main.c
@@ -16,11 +16,19 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#define COBJMACROS
+
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
+#include "mfmediaengine.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
{
switch (reason)
@@ -34,3 +42,136 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
return TRUE;
}
+
+static HRESULT WINAPI media_engine_factory_QueryInterface(IMFMediaEngineClassFactory *iface, REFIID riid, void **obj)
+{
+ if (IsEqualIID(riid, &IID_IMFMediaEngineClassFactory) ||
+ IsEqualIID(riid, &IID_IUnknown))
+ {
+ *obj = iface;
+ IMFMediaEngineClassFactory_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("Unsupported interface %s.\n", debugstr_guid(riid));
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI media_engine_factory_AddRef(IMFMediaEngineClassFactory *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI media_engine_factory_Release(IMFMediaEngineClassFactory *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI media_engine_factory_CreateInstance(IMFMediaEngineClassFactory *iface, DWORD flags,
+ IMFAttributes *attributes, IMFMediaEngine **engine)
+{
+ FIXME("(%p, %#x, %p, %p): stub.\n", iface, flags, attributes, engine);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI media_engine_factory_CreateTimeRange(IMFMediaEngineClassFactory *iface,
+ IMFMediaTimeRange **range)
+{
+ FIXME("(%p, %p): stub.\n", iface, range);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI media_engine_factory_CreateError(IMFMediaEngineClassFactory *iface, IMFMediaError **error)
+{
+ FIXME("(%p, %p): stub.\n", iface, error);
+
+ return E_NOTIMPL;
+}
+
+static const IMFMediaEngineClassFactoryVtbl media_engine_factory_vtbl =
+{
+ media_engine_factory_QueryInterface,
+ media_engine_factory_AddRef,
+ media_engine_factory_Release,
+ media_engine_factory_CreateInstance,
+ media_engine_factory_CreateTimeRange,
+ media_engine_factory_CreateError,
+};
+
+static IMFMediaEngineClassFactory media_engine_factory = { &media_engine_factory_vtbl };
+
+static HRESULT WINAPI classfactory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
+{
+ TRACE("(%s, %p).\n", debugstr_guid(riid), obj);
+
+ if (IsEqualGUID(riid, &IID_IClassFactory) ||
+ IsEqualGUID(riid, &IID_IUnknown))
+ {
+ IClassFactory_AddRef(iface);
+ *obj = iface;
+ return S_OK;
+ }
+
+ WARN("interface %s not implemented.\n", debugstr_guid(riid));
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI classfactory_AddRef(IClassFactory *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI classfactory_Release(IClassFactory *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI classfactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **obj)
+{
+ TRACE("(%p, %s, %p).\n", outer, debugstr_guid(riid), obj);
+
+ *obj = NULL;
+
+ if (outer)
+ return CLASS_E_NOAGGREGATION;
+
+ return IMFMediaEngineClassFactory_QueryInterface(&media_engine_factory, riid, obj);
+}
+
+static HRESULT WINAPI classfactory_LockServer(IClassFactory *iface, BOOL dolock)
+{
+ FIXME("(%d): stub.\n", dolock);
+ return S_OK;
+}
+
+static const struct IClassFactoryVtbl class_factory_vtbl =
+{
+ classfactory_QueryInterface,
+ classfactory_AddRef,
+ classfactory_Release,
+ classfactory_CreateInstance,
+ classfactory_LockServer,
+};
+
+static IClassFactory classfactory = { &class_factory_vtbl };
+
+HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **obj)
+{
+ TRACE("(%s, %s, %p).\n", debugstr_guid(clsid), debugstr_guid(riid), obj);
+
+ if (IsEqualGUID(clsid, &CLSID_MFMediaEngineClassFactory))
+ return IClassFactory_QueryInterface(&classfactory, riid, obj);
+
+ WARN("Unsupported class %s.\n", debugstr_guid(clsid));
+ *obj = NULL;
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+HRESULT WINAPI DllCanUnloadNow(void)
+{
+ return S_FALSE;
+}
diff --git a/dlls/mfmediaengine/mediaengine.idl b/dlls/mfmediaengine/mediaengine.idl
new file mode 100644
index 0000000000..a04dabe6a8
--- /dev/null
+++ b/dlls/mfmediaengine/mediaengine.idl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * 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
+
+[
+ helpstring("Media Engine Class Factory"),
+ threading(both),
+ uuid(b44392da-499b-446b-a4cb-005fead0e6d5)
+]
+coclass MFMediaEngineClassFactory { interface IMFMediaEngineClassFactory; }
diff --git a/dlls/mfmediaengine/mediaengine_classes.idl b/dlls/mfmediaengine/mediaengine_classes.idl
new file mode 100644
index 0000000000..a04dabe6a8
--- /dev/null
+++ b/dlls/mfmediaengine/mediaengine_classes.idl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * 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
+
+[
+ helpstring("Media Engine Class Factory"),
+ threading(both),
+ uuid(b44392da-499b-446b-a4cb-005fead0e6d5)
+]
+coclass MFMediaEngineClassFactory { interface IMFMediaEngineClassFactory; }
diff --git a/dlls/mfmediaengine/mfmediaengine.spec b/dlls/mfmediaengine/mfmediaengine.spec
index a7e7cb9036..f216d235a3 100644
--- a/dlls/mfmediaengine/mfmediaengine.spec
+++ b/dlls/mfmediaengine/mfmediaengine.spec
@@ -1,3 +1,3 @@
-@ stub DllCanUnloadNow
+@ stdcall -private DllCanUnloadNow()
@ stub DllGetActivationFactory
-@ stub DllGetClassObject
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
diff --git a/dlls/mfmediaengine/tests/Makefile.in b/dlls/mfmediaengine/tests/Makefile.in
new file mode 100644
index 0000000000..3f2bb5a094
--- /dev/null
+++ b/dlls/mfmediaengine/tests/Makefile.in
@@ -0,0 +1,5 @@
+TESTDLL = mfmediaengine.dll
+IMPORTS = ole32 mfplat mfmediaengine mfuuid
+
+C_SRCS = \
+ mfmediaengine.c
diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c
new file mode 100644
index 0000000000..c7fc89f2b1
--- /dev/null
+++ b/dlls/mfmediaengine/tests/mfmediaengine.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * 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
+ */
+
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+
+#include "mfapi.h"
+#include "mfmediaengine.h"
+
+#include "wine/heap.h"
+#include "wine/test.h"
+
+static void test_factory(void)
+{
+ IMFMediaEngineClassFactory *factory, *factory2;
+ HRESULT hr;
+
+ CoInitialize(NULL);
+
+ hr = CoCreateInstance(&CLSID_MFMediaEngineClassFactory, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IMFMediaEngineClassFactory, (void **)&factory);
+ ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /* pre-win8 */,
+ "Failed to create class factory, hr %#x.\n", hr);
+
+ hr = CoCreateInstance(&CLSID_MFMediaEngineClassFactory, (IUnknown *)factory, CLSCTX_INPROC_SERVER,
+ &IID_IMFMediaEngineClassFactory, (void **)&factory2);
+ ok(hr == CLASS_E_NOAGGREGATION || broken(hr == REGDB_E_CLASSNOTREG) /* pre-win8 */,
+ "Unexpected hr %#x.\n", hr);
+
+ if (factory)
+ IMFMediaEngineClassFactory_Release(factory);
+
+ CoUninitialize();
+}
+
+START_TEST(mfmediaengine)
+{
+ HRESULT hr;
+
+ hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
+ ok(hr == S_OK, "MFStartup failed: %#x.\n", hr);
+
+ test_factory();
+
+ MFShutdown();
+}
--
2.23.0.rc1
3
2
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/mfuuid/mfuuid.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/mfuuid/mfuuid.c b/dlls/mfuuid/mfuuid.c
index 5bfd521aec..c4976d7dc9 100644
--- a/dlls/mfuuid/mfuuid.c
+++ b/dlls/mfuuid/mfuuid.c
@@ -31,3 +31,4 @@
#include "mfapi.h"
#include "mfidl.h"
#include "mfreadwrite.h"
+#include "mfmediaengine.h"
--
2.23.0.rc1
2
1
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
include/Makefile.in | 1 +
include/mfmediaengine.idl | 168 ++++++++++++++++++++++++++++++++++++++
2 files changed, 169 insertions(+)
create mode 100644 include/mfmediaengine.idl
diff --git a/include/Makefile.in b/include/Makefile.in
index 94dd8a0425..47a36ff91d 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -371,6 +371,7 @@ SOURCES = \
mfapi.h \
mferror.h \
mfidl.idl \
+ mfmediaengine.idl \
mfobjects.idl \
mfplay.idl \
mfreadwrite.idl \
diff --git a/include/mfmediaengine.idl b/include/mfmediaengine.idl
new file mode 100644
index 0000000000..8a654f0b59
--- /dev/null
+++ b/include/mfmediaengine.idl
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * 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 "mfidl.idl";
+
+cpp_quote("EXTERN_GUID(CLSID_MFMediaEngineClassFactory, 0xb44392da, 0x499b, 0x446b, 0xa4, 0xcb, 0x00, 0x5f, 0xea, 0xd0, 0xe6, 0xd5);")
+
+typedef enum MF_MEDIA_ENGINE_ERR
+{
+ MF_MEDIA_ENGINE_ERR_NOERROR = 0,
+ MF_MEDIA_ENGINE_ERR_ABORTED = 1,
+ MF_MEDIA_ENGINE_ERR_NETWORK = 2,
+ MF_MEDIA_ENGINE_ERR_DECODE = 3,
+ MF_MEDIA_ENGINE_ERR_SRC_NOT_SUPPORTED = 4,
+ MF_MEDIA_ENGINE_ERR_ENCRYPTED = 5
+} MF_MEDIA_ENGINE_ERR;
+
+typedef enum MF_MEDIA_ENGINE_PRELOAD
+{
+ MF_MEDIA_ENGINE_PRELOAD_MISSING = 0,
+ MF_MEDIA_ENGINE_PRELOAD_EMPTY = 1,
+ MF_MEDIA_ENGINE_PRELOAD_NONE = 2,
+ MF_MEDIA_ENGINE_PRELOAD_METADATA = 3,
+ MF_MEDIA_ENGINE_PRELOAD_AUTOMATIC = 4
+} MF_MEDIA_ENGINE_PRELOAD;
+
+typedef enum MF_MEDIA_ENGINE_CANPLAY
+{
+ MF_MEDIA_ENGINE_CANPLAY_NOT_SUPPORTED = 0,
+ MF_MEDIA_ENGINE_CANPLAY_MAYBE = 1,
+ MF_MEDIA_ENGINE_CANPLAY_PROBABLY = 2,
+} MF_MEDIA_ENGINE_CANPLAY;
+
+typedef struct MFVideoNormalizedRect
+{
+ float left;
+ float top;
+ float right;
+ float bottom;
+} MFVideoNormalizedRect;
+
+[
+ object,
+ uuid(fc0e10d2-ab2a-4501-a951-06bb1075184c),
+ local,
+ pointer_default(unique)
+]
+interface IMFMediaError : IUnknown
+{
+ USHORT GetErrorCode();
+ HRESULT GetExtendedErrorCode();
+ HRESULT SetErrorCode([in] MF_MEDIA_ENGINE_ERR error);
+ HRESULT SetExtendedErrorCode([in] HRESULT error);
+}
+
+[
+ object,
+ uuid(7a5e5354-b114-4c72-b991-3131d75032ea),
+ local,
+ pointer_default(unique)
+]
+interface IMFMediaEngineSrcElements : IUnknown
+{
+ DWORD GetLength();
+ HRESULT GetURL([in] DWORD index, [out] BSTR *url);
+ HRESULT GetType([in] DWORD index, [out] BSTR *type);
+ HRESULT GetMedia([in] DWORD index, [out] BSTR *media);
+ HRESULT AddElement([in] BSTR url, [in] BSTR type, [in] BSTR media);
+ HRESULT RemoveAllElements();
+}
+
+[
+ object,
+ uuid(db71a2fc-078a-414e-9df9-8c2531b0aa6c),
+ local,
+ pointer_default(unique)
+]
+interface IMFMediaTimeRange : IUnknown
+{
+ DWORD GetLength();
+ HRESULT GetStart([in] DWORD index, [out] double *start);
+ HRESULT GetEnd([in] DWORD index, [out] double *end);
+ BOOL ContainsTime([in] double time);
+ HRESULT AddRange([in] double start, [in] double end);
+ HRESULT Clear();
+}
+
+[
+ object,
+ uuid(98a1b0bb-03eb-4935-ae7c-93c1fa0e1c93),
+ local,
+ pointer_default(unique)
+]
+interface IMFMediaEngine : IUnknown
+{
+ HRESULT GetError([out] IMFMediaError **error);
+ HRESULT SetErrorCode([in] MF_MEDIA_ENGINE_ERR error);
+ HRESULT SetSourceElements([in] IMFMediaEngineSrcElements *elements);
+ HRESULT SetSource([in] BSTR url);
+ HRESULT GetCurrentSource([out] BSTR *url);
+ USHORT GetNetworkState();
+ MF_MEDIA_ENGINE_PRELOAD GetPreload();
+ HRESULT SetPreload([in] MF_MEDIA_ENGINE_PRELOAD preload);
+ HRESULT GetBuffered([out] IMFMediaTimeRange **buffered);
+ HRESULT Load();
+ HRESULT CanPlayType([in] BSTR type, [out] MF_MEDIA_ENGINE_CANPLAY *answer);
+ USHORT GetReadyState();
+ BOOL IsSeeking();
+ cpp_quote("#undef GetCurrentTime")
+ double GetCurrentTime();
+ HRESULT SetCurrentTime([in] double time);
+ double GetStartTime();
+ double GetDuration();
+ BOOL IsPaused();
+ double GetDefaultPlaybackRate();
+ HRESULT SetDefaultPlaybackRate([in] double rate);
+ double GetPlaybackRate();
+ HRESULT SetPlaybackRate([in] double rate);
+ HRESULT GetPlayed([out] IMFMediaTimeRange **played);
+ HRESULT GetSeekable([out] IMFMediaTimeRange **seekable);
+ BOOL IsEnded();
+ BOOL GetAutoPlay();
+ HRESULT SetAutoPlay([in] BOOL autoplay);
+ BOOL GetLoop();
+ HRESULT SetLoop([in] BOOL loop);
+ HRESULT Play();
+ HRESULT Pause();
+ BOOL GetMuted();
+ HRESULT SetMuted([in] BOOL muted);
+ double GetVolume();
+ HRESULT SetVolume([in] double volume);
+ BOOL HasVideo();
+ BOOL HasAudio();
+ HRESULT GetNativeVideoSize([out] DWORD *cx, [out] DWORD *cy);
+ HRESULT GetVideoAspectRatio([out] DWORD *cx, [out] DWORD *cy);
+ HRESULT Shutdown();
+ HRESULT TransferVideoFrame([in] IUnknown *surface, [in] const MFVideoNormalizedRect *src,
+ [in] const RECT *dst, [in] const MFARGB *color);
+ HRESULT OnVideoStreamTick([out] LONGLONG *time);
+}
+
+[
+ object,
+ uuid(4d645ace-26aa-4688-9be1-df3516990b93),
+ local,
+ pointer_default(unique)
+]
+interface IMFMediaEngineClassFactory : IUnknown
+{
+ HRESULT CreateInstance([in] DWORD flags, [in] IMFAttributes *attributes, [out] IMFMediaEngine **engine);
+ HRESULT CreateTimeRange([out] IMFMediaTimeRange **range);
+ HRESULT CreateError([out] IMFMediaError **error);
+}
--
2.23.0.rc1
2
1
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
configure | 2 ++
configure.ac | 1 +
dlls/mfmediaengine/Makefile.in | 7 ++++++
dlls/mfmediaengine/main.c | 36 +++++++++++++++++++++++++++
dlls/mfmediaengine/mfmediaengine.spec | 3 +++
5 files changed, 49 insertions(+)
create mode 100644 dlls/mfmediaengine/Makefile.in
create mode 100644 dlls/mfmediaengine/main.c
create mode 100644 dlls/mfmediaengine/mfmediaengine.spec
diff --git a/configure b/configure
index c06bc4f079..82c3611b40 100755
--- a/configure
+++ b/configure
@@ -1385,6 +1385,7 @@ enable_mciwave
enable_mf
enable_mf3216
enable_mferror
+enable_mfmediaengine
enable_mfplat
enable_mfplay
enable_mfreadwrite
@@ -20378,6 +20379,7 @@ wine_fn_config_makefile dlls/mf enable_mf
wine_fn_config_makefile dlls/mf/tests enable_tests
wine_fn_config_makefile dlls/mf3216 enable_mf3216
wine_fn_config_makefile dlls/mferror enable_mferror
+wine_fn_config_makefile dlls/mfmediaengine enable_mfmediaengine
wine_fn_config_makefile dlls/mfplat enable_mfplat
wine_fn_config_makefile dlls/mfplat/tests enable_tests
wine_fn_config_makefile dlls/mfplay enable_mfplay
diff --git a/configure.ac b/configure.ac
index e58a924239..ef41e94df6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3358,6 +3358,7 @@ WINE_CONFIG_MAKEFILE(dlls/mf)
WINE_CONFIG_MAKEFILE(dlls/mf/tests)
WINE_CONFIG_MAKEFILE(dlls/mf3216)
WINE_CONFIG_MAKEFILE(dlls/mferror)
+WINE_CONFIG_MAKEFILE(dlls/mfmediaengine)
WINE_CONFIG_MAKEFILE(dlls/mfplat)
WINE_CONFIG_MAKEFILE(dlls/mfplat/tests)
WINE_CONFIG_MAKEFILE(dlls/mfplay)
diff --git a/dlls/mfmediaengine/Makefile.in b/dlls/mfmediaengine/Makefile.in
new file mode 100644
index 0000000000..1654130574
--- /dev/null
+++ b/dlls/mfmediaengine/Makefile.in
@@ -0,0 +1,7 @@
+MODULE = mfmediaengine.dll
+IMPORTLIB = mfmediaengine
+
+EXTRADLLFLAGS = -mno-cygwin
+
+C_SRCS = \
+ main.c
diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c
new file mode 100644
index 0000000000..81aaf77e2c
--- /dev/null
+++ b/dlls/mfmediaengine/main.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * 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
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+ switch (reason)
+ {
+ case DLL_WINE_PREATTACH:
+ return FALSE; /* prefer native version */
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(instance);
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/dlls/mfmediaengine/mfmediaengine.spec b/dlls/mfmediaengine/mfmediaengine.spec
new file mode 100644
index 0000000000..a7e7cb9036
--- /dev/null
+++ b/dlls/mfmediaengine/mfmediaengine.spec
@@ -0,0 +1,3 @@
+@ stub DllCanUnloadNow
+@ stub DllGetActivationFactory
+@ stub DllGetClassObject
--
2.23.0.rc1
2
1
30 Aug '19
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/mfplat/main.c | 26 +++++++++++++++++++--
dlls/mfplat/tests/Makefile.in | 2 +-
dlls/mfplat/tests/mfplat.c | 44 +++++++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+), 3 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 706251b3e0..d213935c3a 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -31,6 +31,7 @@
#include "initguid.h"
#include "ole2.h"
#include "propsys.h"
+#include "dxgi.h"
#include "wine/debug.h"
#include "wine/list.h"
@@ -7623,6 +7624,7 @@ struct dxgi_device_manager
IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
LONG refcount;
UINT token;
+ IDXGIDevice *device;
};
static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
@@ -7666,6 +7668,8 @@ static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
if (!refcount)
{
+ if (manager->device)
+ IDXGIDevice_Release(manager->device);
heap_free(manager);
}
@@ -7704,9 +7708,26 @@ static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager
static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
{
- FIXME("(%p, %p, %u): stub.\n", iface, device, token);
+ struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
+ IDXGIDevice *dxgi_device;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("(%p, %p, %u).\n", iface, device, token);
+
+ if (!device || token != manager->token)
+ return E_INVALIDARG;
+
+ hr = IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
+ if (SUCCEEDED(hr))
+ {
+ if (manager->device)
+ IDXGIDevice_Release(manager->device);
+ manager->device = dxgi_device;
+ }
+ else
+ hr = E_INVALIDARG;
+
+ return hr;
}
static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE device)
@@ -7753,6 +7774,7 @@ HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **man
object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
object->refcount = 1;
object->token = GetTickCount();
+ object->device = NULL;
TRACE("Created device manager: %p, token: %u.\n", object, object->token);
diff --git a/dlls/mfplat/tests/Makefile.in b/dlls/mfplat/tests/Makefile.in
index c58a0463e5..dafb429142 100644
--- a/dlls/mfplat/tests/Makefile.in
+++ b/dlls/mfplat/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = mfplat.dll
-IMPORTS = ole32 mfplat mfuuid propsys uuid
+IMPORTS = ole32 mfplat mfuuid propsys uuid d3d11
C_SRCS = \
mfplat.c
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index e0029ab4ff..721ec120ef 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -38,7 +38,10 @@
#include "wine/test.h"
#include "wine/heap.h"
+#define D3D11_INIT_GUID
#include "initguid.h"
+#include "d3d11_4.h"
+
DEFINE_GUID(DUMMY_CLSID, 0x12345678,0x1234,0x1234,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19);
DEFINE_GUID(DUMMY_GUID1, 0x12345678,0x1234,0x1234,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21);
DEFINE_GUID(DUMMY_GUID2, 0x12345678,0x1234,0x1234,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22);
@@ -3709,6 +3712,7 @@ if (0)
static void test_dxgi_device_manager(void)
{
IMFDXGIDeviceManager *manager, *manager2;
+ ID3D11Device *d3d11_dev, *d3d11_dev2;
UINT token, token2;
HRESULT hr;
@@ -3740,7 +3744,47 @@ static void test_dxgi_device_manager(void)
ok(manager != manager2, "got wrong pointer: %p.\n", manager2);
EXPECT_REF(manager, 1);
+ hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
+ NULL, 0, D3D11_SDK_VERSION, &d3d11_dev, NULL, NULL);
+ ok(hr == S_OK, "D3D11CreateDevice failed: %#x.\n", hr);
+ EXPECT_REF(d3d11_dev, 1);
+
+ hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)d3d11_dev, token - 1);
+ ok(hr == E_INVALIDARG, "IMFDXGIDeviceManager_ResetDevice should failed: %#x.\n", hr);
+ EXPECT_REF(d3d11_dev, 1);
+
+ hr = IMFDXGIDeviceManager_ResetDevice(manager, NULL, token);
+ ok(hr == E_INVALIDARG, "IMFDXGIDeviceManager_ResetDevice should failed: %#x.\n", hr);
+
+ hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)d3d11_dev, token);
+ ok(hr == S_OK, "IMFDXGIDeviceManager_ResetDevice failed: %#x.\n", hr);
+ EXPECT_REF(manager, 1);
+ EXPECT_REF(d3d11_dev, 2);
+
+ hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)manager2, token);
+ ok(hr == E_INVALIDARG, "IMFDXGIDeviceManager_ResetDevice should failed: %#x.\n", hr);
+ EXPECT_REF(manager2, 1);
+ EXPECT_REF(d3d11_dev, 2);
+
+ hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)d3d11_dev, token);
+ ok(hr == S_OK, "IMFDXGIDeviceManager_ResetDevice failed: %#x.\n", hr);
+ EXPECT_REF(manager, 1);
+ EXPECT_REF(d3d11_dev, 2);
+
+ hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0,
+ NULL, 0, D3D11_SDK_VERSION, &d3d11_dev2, NULL, NULL);
+ ok(hr == S_OK, "D3D11CreateDevice failed: %#x.\n", hr);
+ EXPECT_REF(d3d11_dev2, 1);
+ hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)d3d11_dev2, token);
+ ok(hr == S_OK, "IMFDXGIDeviceManager_ResetDevice failed: %#x.\n", hr);
+ EXPECT_REF(manager, 1);
+ EXPECT_REF(d3d11_dev2, 2);
+ EXPECT_REF(d3d11_dev, 1);
+
IMFDXGIDeviceManager_Release(manager);
+ EXPECT_REF(d3d11_dev2, 1);
+ ID3D11Device_Release(d3d11_dev);
+ ID3D11Device_Release(d3d11_dev2);
IMFDXGIDeviceManager_Release(manager2);
}
--
2.23.0.rc1
2
1
Superseded patch 169212 to 169217.
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/mfplat/main.c | 144 +++++++++++++++++++++++++++++++++++++
dlls/mfplat/mfplat.spec | 1 +
dlls/mfplat/tests/mfplat.c | 41 +++++++++++
include/mfapi.h | 1 +
include/mfobjects.idl | 17 +++++
5 files changed, 204 insertions(+)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index f8f4b502a5..706251b3e0 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -7617,3 +7617,147 @@ HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
return S_OK;
}
+
+struct dxgi_device_manager
+{
+ IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
+ LONG refcount;
+ UINT token;
+};
+
+static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
+{
+ return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
+}
+
+static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
+{
+ TRACE("(%p, %s, %p).\n", iface, debugstr_guid(riid), obj);
+
+ if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) ||
+ IsEqualGUID(riid, &IID_IUnknown))
+ {
+ *obj = iface;
+ IMFDXGIDeviceManager_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("Unsupported %s.\n", debugstr_guid(riid));
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI dxgi_device_manager_AddRef(IMFDXGIDeviceManager *iface)
+{
+ struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
+ ULONG refcount = InterlockedIncrement(&manager->refcount);
+
+ TRACE("(%p) ref=%u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
+{
+ struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
+ ULONG refcount = InterlockedDecrement(&manager->refcount);
+
+ TRACE("(%p) ref=%u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ heap_free(manager);
+ }
+
+ return refcount;
+}
+
+static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE device)
+{
+ FIXME("(%p, %p): stub.\n", iface, device);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE device,
+ REFIID riid, void **service)
+{
+ FIXME("(%p, %p, %s, %p): stub.\n", iface, device, debugstr_guid(riid), service);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE device,
+ REFIID riid, void **ppv, BOOL block)
+{
+ FIXME("(%p, %p, %s, %p, %d): stub.\n", iface, device, wine_dbgstr_guid(riid), ppv, block);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *device)
+{
+ FIXME("(%p, %p): stub.\n", iface, device);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
+{
+ FIXME("(%p, %p, %u): stub.\n", iface, device, token);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE device)
+{
+ FIXME("(%p, %p): stub.\n", iface, device);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE device, BOOL state)
+{
+ FIXME("(%p, %p, %d): stub.\n", iface, device, state);
+
+ return E_NOTIMPL;
+}
+
+static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
+{
+ dxgi_device_manager_QueryInterface,
+ dxgi_device_manager_AddRef,
+ dxgi_device_manager_Release,
+ dxgi_device_manager_CloseDeviceHandle,
+ dxgi_device_manager_GetVideoService,
+ dxgi_device_manager_LockDevice,
+ dxgi_device_manager_OpenDeviceHandle,
+ dxgi_device_manager_ResetDevice,
+ dxgi_device_manager_TestDevice,
+ dxgi_device_manager_UnlockDevice,
+};
+
+HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
+{
+ struct dxgi_device_manager *object;
+
+ TRACE("(%p, %p).\n", token, manager);
+
+ if (!token || !manager)
+ return E_POINTER;
+
+ object = heap_alloc(sizeof(*object));
+ if (!object)
+ return E_OUTOFMEMORY;
+
+ object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
+ object->refcount = 1;
+ object->token = GetTickCount();
+
+ TRACE("Created device manager: %p, token: %u.\n", object, object->token);
+
+ *token = object->token;
+ *manager = &object->IMFDXGIDeviceManager_iface;
+
+ return S_OK;
+}
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec
index 2f16bbd197..cc440c5ee0 100644
--- a/dlls/mfplat/mfplat.spec
+++ b/dlls/mfplat/mfplat.spec
@@ -42,6 +42,7 @@
@ stdcall MFCreateAttributes(ptr long)
@ stub MFCreateAudioMediaType
@ stdcall MFCreateCollection(ptr)
+@ stdcall MFCreateDXGIDeviceManager(ptr ptr)
@ stdcall MFCreateEventQueue(ptr)
@ stdcall MFCreateFile(long long long wstr ptr)
@ stub MFCreateLegacyMediaBufferOnMFMediaBuffer
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index b4ba6b6c57..e0029ab4ff 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -58,6 +58,7 @@ static void _expect_ref(IUnknown *obj, ULONG ref, int line)
static HRESULT (WINAPI *pMFCopyImage)(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride,
DWORD width, DWORD lines);
+static HRESULT (WINAPI *pMFCreateDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager);
static HRESULT (WINAPI *pMFCreateSourceResolver)(IMFSourceResolver **resolver);
static HRESULT (WINAPI *pMFCreateMFByteStreamOnStream)(IStream *stream, IMFByteStream **bytestream);
static void* (WINAPI *pMFHeapAlloc)(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type);
@@ -510,6 +511,7 @@ static void init_functions(void)
X(MFAddPeriodicCallback);
X(MFAllocateSerialWorkQueue);
X(MFCopyImage);
+ X(MFCreateDXGIDeviceManager);
X(MFCreateSourceResolver);
X(MFCreateMFByteStreamOnStream);
X(MFHeapAlloc);
@@ -3704,6 +3706,44 @@ if (0)
ok(!refcount, "Unexpected refcount %u.\n", refcount);
}
+static void test_dxgi_device_manager(void)
+{
+ IMFDXGIDeviceManager *manager, *manager2;
+ UINT token, token2;
+ HRESULT hr;
+
+ if (!pMFCreateDXGIDeviceManager)
+ {
+ win_skip("MFCreateDXGIDeviceManager not found.\n");
+ return;
+ }
+
+ hr = pMFCreateDXGIDeviceManager(NULL, &manager);
+ ok(hr == E_POINTER, "MFCreateDXGIDeviceManager should failed: %#x.\n", hr);
+
+ token = 0;
+ hr = pMFCreateDXGIDeviceManager(&token, NULL);
+ ok(hr == E_POINTER, "MFCreateDXGIDeviceManager should failed: %#x.\n", hr);
+ ok(!token, "got wrong token: %u.\n", token);
+
+ hr = pMFCreateDXGIDeviceManager(&token, &manager);
+ ok(hr == S_OK, "MFCreateDXGIDeviceManager failed: %#x.\n", hr);
+ EXPECT_REF(manager, 1);
+ ok(!!token, "got wrong token: %u.\n", token);
+
+ Sleep(50);
+ token2 = 0;
+ hr = pMFCreateDXGIDeviceManager(&token2, &manager2);
+ ok(hr == S_OK, "MFCreateDXGIDeviceManager failed: %#x.\n", hr);
+ EXPECT_REF(manager2, 1);
+ ok(token2 && token2 != token, "got wrong token: %u, %u.\n", token2, token);
+ ok(manager != manager2, "got wrong pointer: %p.\n", manager2);
+ EXPECT_REF(manager, 1);
+
+ IMFDXGIDeviceManager_Release(manager);
+ IMFDXGIDeviceManager_Release(manager2);
+}
+
START_TEST(mfplat)
{
CoInitialize(NULL);
@@ -3741,6 +3781,7 @@ START_TEST(mfplat)
test_async_create_file();
test_local_handlers();
test_create_property_store();
+ test_dxgi_device_manager();
CoUninitialize();
}
diff --git a/include/mfapi.h b/include/mfapi.h
index 957fb0df9f..f84c051792 100644
--- a/include/mfapi.h
+++ b/include/mfapi.h
@@ -384,6 +384,7 @@ HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IM
HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size);
HRESULT WINAPI MFCreateAsyncResult(IUnknown *object, IMFAsyncCallback *callback, IUnknown *state, IMFAsyncResult **result);
HRESULT WINAPI MFCreateCollection(IMFCollection **collection);
+HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager);
HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue);
HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
LPCWSTR url, IMFByteStream **bytestream);
diff --git a/include/mfobjects.idl b/include/mfobjects.idl
index 0cc8f422da..203acc770f 100644
--- a/include/mfobjects.idl
+++ b/include/mfobjects.idl
@@ -727,3 +727,20 @@ interface IMFMediaEventQueue : IUnknown
[in] HRESULT status, [in, unique] IUnknown *unk);
HRESULT Shutdown();
}
+
+[
+ object,
+ uuid(eb533d5d-2db6-40f8-97a9-494692014f07),
+ local,
+ pointer_default(unique)
+]
+interface IMFDXGIDeviceManager : IUnknown
+{
+ HRESULT CloseDeviceHandle([in] HANDLE device);
+ HRESULT GetVideoService([in] HANDLE device, [in] REFIID riid, [out] void **service);
+ HRESULT LockDevice([in] HANDLE device, [in] REFIID riid, [out] void **ppv, [in] BOOL block);
+ HRESULT OpenDeviceHandle([out] HANDLE *device);
+ HRESULT ResetDevice([in] IUnknown *device, [in] UINT token);
+ HRESULT TestDevice([in] HANDLE device);
+ HRESULT UnlockDevice([in] HANDLE device, [in] BOOL state);
+}
--
2.23.0.rc1
2
1
Some print monitors are very sensitive to loads/unloads being done
in a quick succession like AddMonitor() does, and that even leads to
crashes because the monitor I have here creates a thread on load and
when the thread starts - the monitor dll is already unloaded.
A solution to this is moving the monitor unloading to DeleteMonitor.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/localspl/provider.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c
index 2b3f9bac6e..4f373392ae 100644
--- a/dlls/localspl/provider.c
+++ b/dlls/localspl/provider.c
@@ -1572,8 +1572,6 @@ static BOOL WINAPI fpAddMonitor(LPWSTR pName, DWORD Level, LPBYTE pMonitors)
if ((pm = monitor_load(mi2w->pName, mi2w->pDLLName)) == NULL)
res = FALSE;
- monitor_unload(pm);
-
RegCloseKey(hentry);
if (!res)
@@ -1890,6 +1888,7 @@ static BOOL WINAPI fpConfigurePort(LPWSTR pName, HWND hWnd, LPWSTR pPortName)
static BOOL WINAPI fpDeleteMonitor(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pMonitorName)
{
+ monitor_t *pm;
HKEY hroot = NULL;
LONG lres;
@@ -1910,6 +1909,18 @@ static BOOL WINAPI fpDeleteMonitor(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pMo
return FALSE;
}
+ /* Unload the monitor if it's loaded */
+ EnterCriticalSection(&monitor_handles_cs);
+ LIST_FOR_EACH_ENTRY(pm, &monitor_handles, monitor_t, entry)
+ {
+ if (pm->name && !lstrcmpW(pMonitorName, pm->name))
+ {
+ monitor_unload(pm);
+ break;
+ }
+ }
+ LeaveCriticalSection(&monitor_handles_cs);
+
if(RegCreateKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) != ERROR_SUCCESS) {
ERR("unable to create key %s\n", debugstr_w(monitorsW));
return FALSE;
--
2.20.1
1
0
[PATCH v2 1/5] amstream/tests: Separate and expand tests for IAMMultiMediaStream::AddMediaStream().
by Zebediah Figura 30 Aug '19
by Zebediah Figura 30 Aug '19
30 Aug '19
From: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
v2: fix test failures on systems without audio hardware
dlls/amstream/tests/amstream.c | 626 ++++++++++++++++++++++++++++-----
1 file changed, 547 insertions(+), 79 deletions(-)
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c
index 1089de5e90f..7ee3c375943 100644
--- a/dlls/amstream/tests/amstream.c
+++ b/dlls/amstream/tests/amstream.c
@@ -305,13 +305,558 @@ error:
IAMMultiMediaStream_Release(pams);
}
+static const GUID test_mspid = {0x88888888};
+static IAMMediaStream teststream;
+static LONG teststream_refcount = 1;
+static IAMMultiMediaStream *teststream_mmstream;
+static IMediaStreamFilter *teststream_filter;
+static IFilterGraph *teststream_graph;
+
+static HRESULT WINAPI pin_QueryInterface(IPin *iface, REFIID iid, void **out)
+{
+ return IAMMediaStream_QueryInterface(&teststream, iid, out);
+}
+
+static ULONG WINAPI pin_AddRef(IPin *iface)
+{
+ return IAMMediaStream_AddRef(&teststream);
+}
+
+static ULONG WINAPI pin_Release(IPin *iface)
+{
+ return IAMMediaStream_Release(&teststream);
+}
+
+static HRESULT WINAPI pin_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_Disconnect(IPin *iface)
+{
+ if (winetest_debug > 1) trace("Disconnect\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_ConnectedTo(IPin *iface, IPin **peer)
+{
+ if (winetest_debug > 1) trace("ConnectedTo\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_QueryPinInfo(IPin *iface, PIN_INFO *info)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
+{
+ if (winetest_debug > 1) trace("QueryDirection\n");
+ *dir = PINDIR_INPUT;
+ return S_OK;
+}
+
+static HRESULT WINAPI pin_QueryId(IPin *iface, WCHAR **id)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **out)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *count)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_EndOfStream(IPin *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_BeginFlush(IPin *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_EndFlush(IPin *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_NewSegment(IPin *iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static const IPinVtbl pin_vtbl =
+{
+ pin_QueryInterface,
+ pin_AddRef,
+ pin_Release,
+ pin_Connect,
+ pin_ReceiveConnection,
+ pin_Disconnect,
+ pin_ConnectedTo,
+ pin_ConnectionMediaType,
+ pin_QueryPinInfo,
+ pin_QueryDirection,
+ pin_QueryId,
+ pin_QueryAccept,
+ pin_EnumMediaTypes,
+ pin_QueryInternalConnections,
+ pin_EndOfStream,
+ pin_BeginFlush,
+ pin_EndFlush,
+ pin_NewSegment
+};
+
+static IPin testpin = {&pin_vtbl};
+
+static HRESULT WINAPI stream_QueryInterface(IAMMediaStream *iface, REFIID iid, void **out)
+{
+ if (winetest_debug > 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid));
+
+ if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IMediaStream) || IsEqualGUID(iid, &IID_IAMMediaStream))
+ {
+ IAMMediaStream_AddRef(iface);
+ *out = iface;
+ return S_OK;
+ }
+ else if (IsEqualGUID(iid, &IID_IPin))
+ {
+ IAMMediaStream_AddRef(iface);
+ *out = &testpin;
+ return S_OK;
+ }
+
+ ok(0, "Unexpected interface %s.\n", wine_dbgstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI stream_AddRef(IAMMediaStream *iface)
+{
+ return InterlockedIncrement(&teststream_refcount);
+}
+
+static ULONG WINAPI stream_Release(IAMMediaStream *iface)
+{
+ return InterlockedDecrement(&teststream_refcount);
+}
+
+static HRESULT WINAPI stream_GetMultiMediaStream(IAMMediaStream *iface, IMultiMediaStream **mmstream)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_GetInformation(IAMMediaStream *iface, MSPID *id, STREAM_TYPE *type)
+{
+ if (winetest_debug > 1) trace("GetInformation(%p, %p)\n", id, type);
+ *id = test_mspid;
+ ok(!type, "Got unexpected type %p.\n", type);
+ return S_OK;
+}
+
+static HRESULT WINAPI stream_SetSameFormat(IAMMediaStream *iface, IMediaStream *ref, DWORD flags)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_AllocateSample(IAMMediaStream *iface, DWORD flags, IStreamSample **sample)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_CreateSharedSample(IAMMediaStream *iface,
+ IStreamSample *existing, DWORD flags, IStreamSample **out)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_SendEndOfStream(IAMMediaStream *iface, DWORD flags)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Initialize(IAMMediaStream *iface, IUnknown *source,
+ DWORD flags, REFMSPID id, const STREAM_TYPE type)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_SetState(IAMMediaStream *iface, FILTER_STATE state)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_JoinAMMultiMediaStream(IAMMediaStream *iface, IAMMultiMediaStream *mmstream)
+{
+ if (winetest_debug > 1) trace("JoinAMMultiMediaStream(%p)\n", mmstream);
+ teststream_mmstream = mmstream;
+ return S_OK;
+}
+
+static HRESULT WINAPI stream_JoinFilter(IAMMediaStream *iface, IMediaStreamFilter *filter)
+{
+ if (winetest_debug > 1) trace("JoinFilter(%p)\n", filter);
+ teststream_filter = filter;
+ return S_OK;
+}
+
+static HRESULT WINAPI stream_JoinFilterGraph(IAMMediaStream *iface, IFilterGraph *graph)
+{
+ if (winetest_debug > 1) trace("JoinFilterGraph(%p)\n", graph);
+ teststream_graph = graph;
+ return S_OK;
+}
+
+static const IAMMediaStreamVtbl stream_vtbl =
+{
+ stream_QueryInterface,
+ stream_AddRef,
+ stream_Release,
+ stream_GetMultiMediaStream,
+ stream_GetInformation,
+ stream_SetSameFormat,
+ stream_AllocateSample,
+ stream_CreateSharedSample,
+ stream_SendEndOfStream,
+ stream_Initialize,
+ stream_SetState,
+ stream_JoinAMMultiMediaStream,
+ stream_JoinFilter,
+ stream_JoinFilterGraph,
+};
+
+static IAMMediaStream teststream = {&stream_vtbl};
+
+#define check_enum_stream(a,b,c,d) check_enum_stream_(__LINE__,a,b,c,d)
+static void check_enum_stream_(int line, IAMMultiMediaStream *mmstream,
+ IMediaStreamFilter *filter, LONG index, IMediaStream *expect)
+{
+ IMediaStream *stream = NULL, *stream2 = NULL;
+ HRESULT hr;
+
+ hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, index, &stream);
+ todo_wine ok_(__FILE__, line)(hr == (expect ? S_OK : S_FALSE),
+ "IAMMultiMediaStream::EnumMediaStreams() returned %#x.\n", hr);
+ hr = IMediaStreamFilter_EnumMediaStreams(filter, index, &stream2);
+ todo_wine ok_(__FILE__, line)(hr == (expect ? S_OK : S_FALSE),
+ "IMediaStreamFilter::EnumMediaStreams() returned %#x.\n", hr);
+ if (hr == S_OK)
+ {
+ ok_(__FILE__, line)(stream == expect, "Expected stream %p, got %p.\n", expect, stream);
+ ok_(__FILE__, line)(stream2 == expect, "Expected stream %p, got %p.\n", expect, stream2);
+ }
+
+ if (stream) IMediaStream_Release(stream);
+ if (stream2) IMediaStream_Release(stream2);
+}
+
+#define check_get_stream(a,b,c,d) check_get_stream_(__LINE__,a,b,c,d)
+static void check_get_stream_(int line, IAMMultiMediaStream *mmstream,
+ IMediaStreamFilter *filter, const GUID *mspid, IMediaStream *expect)
+{
+ IMediaStream *stream = NULL, *stream2 = NULL;
+ HRESULT hr;
+
+ hr = IAMMultiMediaStream_GetMediaStream(mmstream, mspid, &stream);
+ ok_(__FILE__, line)(hr == (expect ? S_OK : MS_E_NOSTREAM),
+ "IAMMultiMediaStream::GetMediaStream() returned %#x.\n", hr);
+ hr = IMediaStreamFilter_GetMediaStream(filter, mspid, &stream2);
+ ok_(__FILE__, line)(hr == (expect ? S_OK : MS_E_NOSTREAM),
+ "IMediaStreamFilter::GetMediaStream() returned %#x.\n", hr);
+ if (hr == S_OK)
+ {
+ ok_(__FILE__, line)(stream == expect, "Expected stream %p, got %p.\n", expect, stream);
+ ok_(__FILE__, line)(stream2 == expect, "Expected stream %p, got %p.\n", expect, stream2);
+ }
+
+ if (stream) IMediaStream_Release(stream);
+ if (stream2) IMediaStream_Release(stream2);
+}
+
+static void test_add_stream(void)
+{
+ IAMMultiMediaStream *mmstream = create_ammultimediastream();
+ IMediaStream *video_stream, *audio_stream, *stream;
+ IDirectDrawMediaStream *ddraw_stream;
+ IMediaStreamFilter *stream_filter;
+ IDirectDraw *ddraw, *ddraw2;
+ IEnumFilters *enum_filters;
+ IBaseFilter *filters[3];
+ IGraphBuilder *graph;
+ ULONG ref, count;
+ CLSID clsid;
+ HRESULT hr;
+
+ hr = IAMMultiMediaStream_GetFilter(mmstream, &stream_filter);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, 0, NULL);
+ todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ hr = IMediaStreamFilter_EnumMediaStreams(stream_filter, 0, NULL);
+ todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_GetMediaStream(mmstream, &MSPID_PrimaryAudio, NULL);
+ todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+ hr = IMediaStreamFilter_GetMediaStream(stream_filter, &MSPID_PrimaryAudio, NULL);
+ todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+
+ check_enum_stream(mmstream, stream_filter, 0, NULL);
+
+ check_get_stream(mmstream, stream_filter, NULL, NULL);
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, NULL);
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, NULL);
+ check_get_stream(mmstream, stream_filter, &test_mspid, NULL);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &test_mspid, 0, &stream);
+ ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &video_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
+ todo_wine ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, 0, NULL);
+ todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+ hr = IMediaStreamFilter_EnumMediaStreams(stream_filter, 0, NULL);
+ todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+ hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, 1, NULL);
+ todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ hr = IMediaStreamFilter_EnumMediaStreams(stream_filter, 1, NULL);
+ todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ check_enum_stream(mmstream, stream_filter, 0, video_stream);
+ check_enum_stream(mmstream, stream_filter, 1, NULL);
+
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, video_stream);
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, NULL);
+ check_get_stream(mmstream, stream_filter, &test_mspid, NULL);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &audio_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ check_enum_stream(mmstream, stream_filter, 0, video_stream);
+ check_enum_stream(mmstream, stream_filter, 1, audio_stream);
+ check_enum_stream(mmstream, stream_filter, 2, NULL);
+
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, video_stream);
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, audio_stream);
+ check_get_stream(mmstream, stream_filter, &test_mspid, NULL);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)&teststream, &IID_IUnknown, 0, &stream);
+ ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)&teststream, &test_mspid, 0, &stream);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(stream == (IMediaStream *)&teststream, "Streams didn't match.\n");
+ if (hr == S_OK) IMediaStream_Release(stream);
+ todo_wine ok(teststream_mmstream == mmstream, "IAMMultiMediaStream objects didn't match.\n");
+ todo_wine ok(teststream_filter == stream_filter, "IMediaStreamFilter objects didn't match.\n");
+ todo_wine ok(!!teststream_graph, "Expected a non-NULL graph.\n");
+
+ check_enum_stream(mmstream, stream_filter, 0, video_stream);
+ check_enum_stream(mmstream, stream_filter, 1, audio_stream);
+ check_enum_stream(mmstream, stream_filter, 2, (IMediaStream *)&teststream);
+ check_enum_stream(mmstream, stream_filter, 3, NULL);
+
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, video_stream);
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, audio_stream);
+ todo_wine check_get_stream(mmstream, stream_filter, &test_mspid, (IMediaStream *)&teststream);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
+ todo_wine ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(!!graph, "Expected a non-NULL graph.\n");
+ if (graph)
+ {
+ hr = IGraphBuilder_EnumFilters(graph, &enum_filters);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IEnumFilters_Next(enum_filters, 3, filters, &count);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ ok(count == 1, "Got count %u.\n", count);
+ ok(filters[0] == (IBaseFilter *)stream_filter,
+ "Expected filter %p, got %p.\n", stream_filter, filters[0]);
+ IBaseFilter_Release(filters[0]);
+ IEnumFilters_Release(enum_filters);
+ IGraphBuilder_Release(graph);
+ }
+
+ IMediaStreamFilter_Release(stream_filter);
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IMediaStream_Release(video_stream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IMediaStream_Release(audio_stream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ok(teststream_refcount == 1, "Got outstanding refcount %d.\n", ref);
+
+ /* The return parameter is optional. */
+
+ mmstream = create_ammultimediastream();
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_GetMediaStream(mmstream, &MSPID_PrimaryVideo, &stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ IMediaStream_Release(stream);
+
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ /* Test supplying a DirectDraw object with the primary video stream. */
+
+ hr = DirectDrawCreate(NULL, &ddraw, NULL);
+ ok(hr == DD_OK, "Got hr %#x.\n", hr);
+ mmstream = create_ammultimediastream();
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw, &MSPID_PrimaryVideo, 0, &video_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaStream_QueryInterface(video_stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(ddraw2 == ddraw, "Expected IDirectDraw %p, got %p.\n", ddraw, ddraw2);
+ IDirectDraw_Release(ddraw2);
+ IDirectDrawMediaStream_Release(ddraw_stream);
+
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IMediaStream_Release(video_stream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IDirectDraw_Release(ddraw);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ mmstream = create_ammultimediastream();
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &video_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaStream_QueryInterface(video_stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!!ddraw, "Expected a non-NULL IDirectDraw.\n");
+ IDirectDraw_Release(ddraw);
+ IDirectDrawMediaStream_Release(ddraw_stream);
+
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IMediaStream_Release(video_stream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ /* Test the AMMSF_ADDDEFAULTRENDERER flag. No stream is added; however, a
+ * new filter will be added to the graph. */
+
+ mmstream = create_ammultimediastream();
+ hr = IAMMultiMediaStream_GetFilter(mmstream, &stream_filter);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ /* FIXME: This call should not be necessary. */
+ hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo,
+ AMMSF_ADDDEFAULTRENDERER, &video_stream);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo,
+ AMMSF_ADDDEFAULTRENDERER, NULL);
+ ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio,
+ AMMSF_ADDDEFAULTRENDERER, &audio_stream);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio,
+ AMMSF_ADDDEFAULTRENDERER, NULL);
+ ok(hr == S_OK || hr == VFW_E_NO_AUDIO_HARDWARE, "Got hr %#x.\n", hr);
+
+ check_enum_stream(mmstream, stream_filter, 0, NULL);
+
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, NULL);
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, NULL);
+
+ if (hr == S_OK)
+ {
+ hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!!graph, "Got graph %p.\n", graph);
+ hr = IAMMultiMediaStream_GetFilter(mmstream, &stream_filter);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IGraphBuilder_EnumFilters(graph, &enum_filters);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IEnumFilters_Next(enum_filters, 3, filters, &count);
+ todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ todo_wine ok(count == 2, "Got count %u.\n", count);
+ todo_wine ok(filters[1] == (IBaseFilter *)stream_filter,
+ "Expected filter %p, got %p.\n", stream_filter, filters[1]);
+ hr = IBaseFilter_GetClassID(filters[0], &clsid);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(IsEqualGUID(&clsid, &CLSID_DSoundRender), "Got unexpected filter %s.\n", wine_dbgstr_guid(&clsid));
+ IBaseFilter_Release(filters[0]);
+ IMediaStreamFilter_Release(stream_filter);
+ IEnumFilters_Release(enum_filters);
+ IGraphBuilder_Release(graph);
+ }
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &test_mspid,
+ AMMSF_ADDDEFAULTRENDERER, &audio_stream);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ IMediaStreamFilter_Release(stream_filter);
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
static void test_media_streams(void)
{
IAMMultiMediaStream *pams;
HRESULT hr;
IMediaStream *video_stream = NULL;
IMediaStream *audio_stream = NULL;
- IMediaStream *dummy_stream;
IMediaStreamFilter* media_stream_filter = NULL;
if (!(pams = create_ammultimediastream()))
@@ -331,42 +876,11 @@ static void test_media_streams(void)
hr = IAMMultiMediaStream_GetFilter(pams, &media_stream_filter);
ok(hr == S_OK, "IAMMultiMediaStream_GetFilter returned: %x\n", hr);
- /* Verify behaviour with invalid purpose id */
- hr = IAMMultiMediaStream_GetMediaStream(pams, &IID_IUnknown, &dummy_stream);
- ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
- hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &IID_IUnknown, 0, NULL);
- ok(hr == MS_E_PURPOSEID, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
-
- /* Verify there is no video media stream */
- hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
- ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
-
- /* Verify there is no default renderer for video stream */
- hr = IAMMultiMediaStream_AddMediaStream(pams, (IUnknown*)pdd7, &MSPID_PrimaryVideo, AMMSF_ADDDEFAULTRENDERER, NULL);
- ok(hr == MS_E_PURPOSEID, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
- hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
- ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
- hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryVideo, AMMSF_ADDDEFAULTRENDERER, NULL);
- ok(hr == MS_E_PURPOSEID, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
- hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
- ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
-
- /* Verify normal case for video stream */
hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryVideo, 0, NULL);
ok(hr == S_OK, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
- /* Verify the video stream has been added to the media stream filter */
- if (media_stream_filter)
- {
- hr = IMediaStreamFilter_GetMediaStream(media_stream_filter, &MSPID_PrimaryVideo, &dummy_stream);
- ok(hr == S_OK, "IMediaStreamFilter_GetMediaStream returned: %x\n", hr);
- ok(dummy_stream == video_stream, "Got wrong returned pointer %p, expected %p\n", dummy_stream, video_stream);
- if (SUCCEEDED(hr))
- IMediaStream_Release(dummy_stream);
- }
-
/* Check interfaces and samples for video */
if (video_stream)
{
@@ -431,58 +945,11 @@ static void test_media_streams(void)
IDirectDrawMediaStream_Release(ddraw_stream);
}
- /* Verify there is no audio media stream */
- hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream);
- ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
-
- /* Verify no stream is created when using the default renderer for audio stream */
- hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL);
- ok((hr == S_OK) || (hr == VFW_E_NO_AUDIO_HARDWARE), "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
- if (hr == S_OK)
- {
- IGraphBuilder* filtergraph = NULL;
- IBaseFilter* filter = NULL;
- const WCHAR name[] = {'0','0','0','1',0};
- CLSID clsid;
-
- hr = IAMMultiMediaStream_GetFilterGraph(pams, &filtergraph);
- ok(hr == S_OK, "IAMMultiMediaStream_GetFilterGraph returned: %x\n", hr);
- if (hr == S_OK)
- {
- hr = IGraphBuilder_FindFilterByName(filtergraph, name, &filter);
- ok(hr == S_OK, "IGraphBuilder_FindFilterByName returned: %x\n", hr);
- }
- if (hr == S_OK)
- {
- hr = IBaseFilter_GetClassID(filter, &clsid);
- ok(hr == S_OK, "IGraphBuilder_FindFilterByName returned: %x\n", hr);
- }
- if (hr == S_OK)
- ok(IsEqualGUID(&clsid, &CLSID_DSoundRender), "Got wrong CLSID\n");
- if (filter)
- IBaseFilter_Release(filter);
- if (filtergraph)
- IGraphBuilder_Release(filtergraph);
- }
- hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream);
- ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
-
- /* Verify a stream is created when no default renderer is used */
hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryAudio, 0, NULL);
ok(hr == S_OK, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream);
ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
- /* verify the audio stream has been added to the media stream filter */
- if (media_stream_filter)
- {
- hr = IMediaStreamFilter_GetMediaStream(media_stream_filter, &MSPID_PrimaryAudio, &dummy_stream);
- ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
- ok(dummy_stream == audio_stream, "Got wrong returned pointer %p, expected %p\n", dummy_stream, audio_stream);
- if (SUCCEEDED(hr))
- IMediaStream_Release(dummy_stream);
- }
-
/* Check interfaces and samples for audio */
if (audio_stream)
{
@@ -1201,6 +1668,7 @@ START_TEST(amstream)
CoInitializeEx(NULL, COINIT_MULTITHREADED);
test_interfaces();
+ test_add_stream();
test_media_streams();
test_enum_pins();
test_find_pin();
--
2.22.0
1
4
[PATCH 1/5] amstream/tests: Separate and expand tests for IAMMultiMediaStream::AddMediaStream().
by Zebediah Figura 30 Aug '19
by Zebediah Figura 30 Aug '19
30 Aug '19
From: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/amstream/tests/amstream.c | 623 ++++++++++++++++++++++++++++-----
1 file changed, 544 insertions(+), 79 deletions(-)
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c
index 1089de5e90f..289e936e18d 100644
--- a/dlls/amstream/tests/amstream.c
+++ b/dlls/amstream/tests/amstream.c
@@ -305,13 +305,555 @@ error:
IAMMultiMediaStream_Release(pams);
}
+static const GUID test_mspid = {0x88888888};
+static IAMMediaStream teststream;
+static LONG teststream_refcount = 1;
+static IAMMultiMediaStream *teststream_mmstream;
+static IMediaStreamFilter *teststream_filter;
+static IFilterGraph *teststream_graph;
+
+static HRESULT WINAPI pin_QueryInterface(IPin *iface, REFIID iid, void **out)
+{
+ return IAMMediaStream_QueryInterface(&teststream, iid, out);
+}
+
+static ULONG WINAPI pin_AddRef(IPin *iface)
+{
+ return IAMMediaStream_AddRef(&teststream);
+}
+
+static ULONG WINAPI pin_Release(IPin *iface)
+{
+ return IAMMediaStream_Release(&teststream);
+}
+
+static HRESULT WINAPI pin_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_Disconnect(IPin *iface)
+{
+ if (winetest_debug > 1) trace("Disconnect\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_ConnectedTo(IPin *iface, IPin **peer)
+{
+ if (winetest_debug > 1) trace("ConnectedTo\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_QueryPinInfo(IPin *iface, PIN_INFO *info)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
+{
+ if (winetest_debug > 1) trace("QueryDirection\n");
+ *dir = PINDIR_INPUT;
+ return S_OK;
+}
+
+static HRESULT WINAPI pin_QueryId(IPin *iface, WCHAR **id)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **out)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *count)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_EndOfStream(IPin *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_BeginFlush(IPin *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_EndFlush(IPin *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pin_NewSegment(IPin *iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static const IPinVtbl pin_vtbl =
+{
+ pin_QueryInterface,
+ pin_AddRef,
+ pin_Release,
+ pin_Connect,
+ pin_ReceiveConnection,
+ pin_Disconnect,
+ pin_ConnectedTo,
+ pin_ConnectionMediaType,
+ pin_QueryPinInfo,
+ pin_QueryDirection,
+ pin_QueryId,
+ pin_QueryAccept,
+ pin_EnumMediaTypes,
+ pin_QueryInternalConnections,
+ pin_EndOfStream,
+ pin_BeginFlush,
+ pin_EndFlush,
+ pin_NewSegment
+};
+
+static IPin testpin = {&pin_vtbl};
+
+static HRESULT WINAPI stream_QueryInterface(IAMMediaStream *iface, REFIID iid, void **out)
+{
+ if (winetest_debug > 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid));
+
+ if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IMediaStream) || IsEqualGUID(iid, &IID_IAMMediaStream))
+ {
+ IAMMediaStream_AddRef(iface);
+ *out = iface;
+ return S_OK;
+ }
+ else if (IsEqualGUID(iid, &IID_IPin))
+ {
+ IAMMediaStream_AddRef(iface);
+ *out = &testpin;
+ return S_OK;
+ }
+
+ ok(0, "Unexpected interface %s.\n", wine_dbgstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI stream_AddRef(IAMMediaStream *iface)
+{
+ return InterlockedIncrement(&teststream_refcount);
+}
+
+static ULONG WINAPI stream_Release(IAMMediaStream *iface)
+{
+ return InterlockedDecrement(&teststream_refcount);
+}
+
+static HRESULT WINAPI stream_GetMultiMediaStream(IAMMediaStream *iface, IMultiMediaStream **mmstream)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_GetInformation(IAMMediaStream *iface, MSPID *id, STREAM_TYPE *type)
+{
+ if (winetest_debug > 1) trace("GetInformation(%p, %p)\n", id, type);
+ *id = test_mspid;
+ ok(!type, "Got unexpected type %p.\n", type);
+ return S_OK;
+}
+
+static HRESULT WINAPI stream_SetSameFormat(IAMMediaStream *iface, IMediaStream *ref, DWORD flags)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_AllocateSample(IAMMediaStream *iface, DWORD flags, IStreamSample **sample)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_CreateSharedSample(IAMMediaStream *iface,
+ IStreamSample *existing, DWORD flags, IStreamSample **out)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_SendEndOfStream(IAMMediaStream *iface, DWORD flags)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Initialize(IAMMediaStream *iface, IUnknown *source,
+ DWORD flags, REFMSPID id, const STREAM_TYPE type)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_SetState(IAMMediaStream *iface, FILTER_STATE state)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_JoinAMMultiMediaStream(IAMMediaStream *iface, IAMMultiMediaStream *mmstream)
+{
+ if (winetest_debug > 1) trace("JoinAMMultiMediaStream(%p)\n", mmstream);
+ teststream_mmstream = mmstream;
+ return S_OK;
+}
+
+static HRESULT WINAPI stream_JoinFilter(IAMMediaStream *iface, IMediaStreamFilter *filter)
+{
+ if (winetest_debug > 1) trace("JoinFilter(%p)\n", filter);
+ teststream_filter = filter;
+ return S_OK;
+}
+
+static HRESULT WINAPI stream_JoinFilterGraph(IAMMediaStream *iface, IFilterGraph *graph)
+{
+ if (winetest_debug > 1) trace("JoinFilterGraph(%p)\n", graph);
+ teststream_graph = graph;
+ return S_OK;
+}
+
+static const IAMMediaStreamVtbl stream_vtbl =
+{
+ stream_QueryInterface,
+ stream_AddRef,
+ stream_Release,
+ stream_GetMultiMediaStream,
+ stream_GetInformation,
+ stream_SetSameFormat,
+ stream_AllocateSample,
+ stream_CreateSharedSample,
+ stream_SendEndOfStream,
+ stream_Initialize,
+ stream_SetState,
+ stream_JoinAMMultiMediaStream,
+ stream_JoinFilter,
+ stream_JoinFilterGraph,
+};
+
+static IAMMediaStream teststream = {&stream_vtbl};
+
+#define check_enum_stream(a,b,c,d) check_enum_stream_(__LINE__,a,b,c,d)
+static void check_enum_stream_(int line, IAMMultiMediaStream *mmstream,
+ IMediaStreamFilter *filter, LONG index, IMediaStream *expect)
+{
+ IMediaStream *stream = NULL, *stream2 = NULL;
+ HRESULT hr;
+
+ hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, index, &stream);
+ todo_wine ok_(__FILE__, line)(hr == (expect ? S_OK : S_FALSE),
+ "IAMMultiMediaStream::EnumMediaStreams() returned %#x.\n", hr);
+ hr = IMediaStreamFilter_EnumMediaStreams(filter, index, &stream2);
+ todo_wine ok_(__FILE__, line)(hr == (expect ? S_OK : S_FALSE),
+ "IMediaStreamFilter::EnumMediaStreams() returned %#x.\n", hr);
+ if (hr == S_OK)
+ {
+ ok_(__FILE__, line)(stream == expect, "Expected stream %p, got %p.\n", expect, stream);
+ ok_(__FILE__, line)(stream2 == expect, "Expected stream %p, got %p.\n", expect, stream2);
+ }
+
+ if (stream) IMediaStream_Release(stream);
+ if (stream2) IMediaStream_Release(stream2);
+}
+
+#define check_get_stream(a,b,c,d) check_get_stream_(__LINE__,a,b,c,d)
+static void check_get_stream_(int line, IAMMultiMediaStream *mmstream,
+ IMediaStreamFilter *filter, const GUID *mspid, IMediaStream *expect)
+{
+ IMediaStream *stream = NULL, *stream2 = NULL;
+ HRESULT hr;
+
+ hr = IAMMultiMediaStream_GetMediaStream(mmstream, mspid, &stream);
+ ok_(__FILE__, line)(hr == (expect ? S_OK : MS_E_NOSTREAM),
+ "IAMMultiMediaStream::GetMediaStream() returned %#x.\n", hr);
+ hr = IMediaStreamFilter_GetMediaStream(filter, mspid, &stream2);
+ ok_(__FILE__, line)(hr == (expect ? S_OK : MS_E_NOSTREAM),
+ "IMediaStreamFilter::GetMediaStream() returned %#x.\n", hr);
+ if (hr == S_OK)
+ {
+ ok_(__FILE__, line)(stream == expect, "Expected stream %p, got %p.\n", expect, stream);
+ ok_(__FILE__, line)(stream2 == expect, "Expected stream %p, got %p.\n", expect, stream2);
+ }
+
+ if (stream) IMediaStream_Release(stream);
+ if (stream2) IMediaStream_Release(stream2);
+}
+
+static void test_add_stream(void)
+{
+ IAMMultiMediaStream *mmstream = create_ammultimediastream();
+ IMediaStream *video_stream, *audio_stream, *stream;
+ IDirectDrawMediaStream *ddraw_stream;
+ IMediaStreamFilter *stream_filter;
+ IDirectDraw *ddraw, *ddraw2;
+ IEnumFilters *enum_filters;
+ IBaseFilter *filters[3];
+ IGraphBuilder *graph;
+ ULONG ref, count;
+ CLSID clsid;
+ HRESULT hr;
+
+ hr = IAMMultiMediaStream_GetFilter(mmstream, &stream_filter);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, 0, NULL);
+ todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ hr = IMediaStreamFilter_EnumMediaStreams(stream_filter, 0, NULL);
+ todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_GetMediaStream(mmstream, &MSPID_PrimaryAudio, NULL);
+ todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+ hr = IMediaStreamFilter_GetMediaStream(stream_filter, &MSPID_PrimaryAudio, NULL);
+ todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+
+ check_enum_stream(mmstream, stream_filter, 0, NULL);
+
+ check_get_stream(mmstream, stream_filter, NULL, NULL);
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, NULL);
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, NULL);
+ check_get_stream(mmstream, stream_filter, &test_mspid, NULL);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &test_mspid, 0, &stream);
+ ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &video_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
+ todo_wine ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, 0, NULL);
+ todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+ hr = IMediaStreamFilter_EnumMediaStreams(stream_filter, 0, NULL);
+ todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+ hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, 1, NULL);
+ todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ hr = IMediaStreamFilter_EnumMediaStreams(stream_filter, 1, NULL);
+ todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ check_enum_stream(mmstream, stream_filter, 0, video_stream);
+ check_enum_stream(mmstream, stream_filter, 1, NULL);
+
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, video_stream);
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, NULL);
+ check_get_stream(mmstream, stream_filter, &test_mspid, NULL);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &audio_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ check_enum_stream(mmstream, stream_filter, 0, video_stream);
+ check_enum_stream(mmstream, stream_filter, 1, audio_stream);
+ check_enum_stream(mmstream, stream_filter, 2, NULL);
+
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, video_stream);
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, audio_stream);
+ check_get_stream(mmstream, stream_filter, &test_mspid, NULL);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)&teststream, &IID_IUnknown, 0, &stream);
+ ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)&teststream, &test_mspid, 0, &stream);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(stream == (IMediaStream *)&teststream, "Streams didn't match.\n");
+ if (hr == S_OK) IMediaStream_Release(stream);
+ todo_wine ok(teststream_mmstream == mmstream, "IAMMultiMediaStream objects didn't match.\n");
+ todo_wine ok(teststream_filter == stream_filter, "IMediaStreamFilter objects didn't match.\n");
+ todo_wine ok(!!teststream_graph, "Expected a non-NULL graph.\n");
+
+ check_enum_stream(mmstream, stream_filter, 0, video_stream);
+ check_enum_stream(mmstream, stream_filter, 1, audio_stream);
+ check_enum_stream(mmstream, stream_filter, 2, (IMediaStream *)&teststream);
+ check_enum_stream(mmstream, stream_filter, 3, NULL);
+
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, video_stream);
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, audio_stream);
+ todo_wine check_get_stream(mmstream, stream_filter, &test_mspid, (IMediaStream *)&teststream);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
+ todo_wine ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(!!graph, "Expected a non-NULL graph.\n");
+ if (graph)
+ {
+ hr = IGraphBuilder_EnumFilters(graph, &enum_filters);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IEnumFilters_Next(enum_filters, 3, filters, &count);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ ok(count == 1, "Got count %u.\n", count);
+ ok(filters[0] == (IBaseFilter *)stream_filter,
+ "Expected filter %p, got %p.\n", stream_filter, filters[0]);
+ IBaseFilter_Release(filters[0]);
+ IEnumFilters_Release(enum_filters);
+ IGraphBuilder_Release(graph);
+ }
+
+ IMediaStreamFilter_Release(stream_filter);
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IMediaStream_Release(video_stream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IMediaStream_Release(audio_stream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ok(teststream_refcount == 1, "Got outstanding refcount %d.\n", ref);
+
+ /* The return parameter is optional. */
+
+ mmstream = create_ammultimediastream();
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_GetMediaStream(mmstream, &MSPID_PrimaryVideo, &stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ IMediaStream_Release(stream);
+
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ /* Test supplying a DirectDraw object with the primary video stream. */
+
+ hr = DirectDrawCreate(NULL, &ddraw, NULL);
+ ok(hr == DD_OK, "Got hr %#x.\n", hr);
+ mmstream = create_ammultimediastream();
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw, &MSPID_PrimaryVideo, 0, &video_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaStream_QueryInterface(video_stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(ddraw2 == ddraw, "Expected IDirectDraw %p, got %p.\n", ddraw, ddraw2);
+ IDirectDraw_Release(ddraw2);
+ IDirectDrawMediaStream_Release(ddraw_stream);
+
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IMediaStream_Release(video_stream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IDirectDraw_Release(ddraw);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ mmstream = create_ammultimediastream();
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &video_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaStream_QueryInterface(video_stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!!ddraw, "Expected a non-NULL IDirectDraw.\n");
+ IDirectDraw_Release(ddraw);
+ IDirectDrawMediaStream_Release(ddraw_stream);
+
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IMediaStream_Release(video_stream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ /* Test the AMMSF_ADDDEFAULTRENDERER flag. No stream is added; however, a
+ * new filter will be added to the graph. */
+
+ mmstream = create_ammultimediastream();
+ hr = IAMMultiMediaStream_GetFilter(mmstream, &stream_filter);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ /* FIXME: This call should not be necessary. */
+ hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo,
+ AMMSF_ADDDEFAULTRENDERER, &video_stream);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo,
+ AMMSF_ADDDEFAULTRENDERER, NULL);
+ ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio,
+ AMMSF_ADDDEFAULTRENDERER, &audio_stream);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio,
+ AMMSF_ADDDEFAULTRENDERER, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ check_enum_stream(mmstream, stream_filter, 0, NULL);
+
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, NULL);
+ check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, NULL);
+
+ hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!!graph, "Got graph %p.\n", graph);
+ hr = IAMMultiMediaStream_GetFilter(mmstream, &stream_filter);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IGraphBuilder_EnumFilters(graph, &enum_filters);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IEnumFilters_Next(enum_filters, 3, filters, &count);
+ todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ todo_wine ok(count == 2, "Got count %u.\n", count);
+ todo_wine ok(filters[1] == (IBaseFilter *)stream_filter,
+ "Expected filter %p, got %p.\n", stream_filter, filters[1]);
+ hr = IBaseFilter_GetClassID(filters[0], &clsid);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(IsEqualGUID(&clsid, &CLSID_DSoundRender), "Got unexpected filter %s.\n", wine_dbgstr_guid(&clsid));
+ IBaseFilter_Release(filters[0]);
+ IMediaStreamFilter_Release(stream_filter);
+ IEnumFilters_Release(enum_filters);
+ IGraphBuilder_Release(graph);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &test_mspid,
+ AMMSF_ADDDEFAULTRENDERER, &audio_stream);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ IMediaStreamFilter_Release(stream_filter);
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
static void test_media_streams(void)
{
IAMMultiMediaStream *pams;
HRESULT hr;
IMediaStream *video_stream = NULL;
IMediaStream *audio_stream = NULL;
- IMediaStream *dummy_stream;
IMediaStreamFilter* media_stream_filter = NULL;
if (!(pams = create_ammultimediastream()))
@@ -331,42 +873,11 @@ static void test_media_streams(void)
hr = IAMMultiMediaStream_GetFilter(pams, &media_stream_filter);
ok(hr == S_OK, "IAMMultiMediaStream_GetFilter returned: %x\n", hr);
- /* Verify behaviour with invalid purpose id */
- hr = IAMMultiMediaStream_GetMediaStream(pams, &IID_IUnknown, &dummy_stream);
- ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
- hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &IID_IUnknown, 0, NULL);
- ok(hr == MS_E_PURPOSEID, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
-
- /* Verify there is no video media stream */
- hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
- ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
-
- /* Verify there is no default renderer for video stream */
- hr = IAMMultiMediaStream_AddMediaStream(pams, (IUnknown*)pdd7, &MSPID_PrimaryVideo, AMMSF_ADDDEFAULTRENDERER, NULL);
- ok(hr == MS_E_PURPOSEID, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
- hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
- ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
- hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryVideo, AMMSF_ADDDEFAULTRENDERER, NULL);
- ok(hr == MS_E_PURPOSEID, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
- hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
- ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
-
- /* Verify normal case for video stream */
hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryVideo, 0, NULL);
ok(hr == S_OK, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
- /* Verify the video stream has been added to the media stream filter */
- if (media_stream_filter)
- {
- hr = IMediaStreamFilter_GetMediaStream(media_stream_filter, &MSPID_PrimaryVideo, &dummy_stream);
- ok(hr == S_OK, "IMediaStreamFilter_GetMediaStream returned: %x\n", hr);
- ok(dummy_stream == video_stream, "Got wrong returned pointer %p, expected %p\n", dummy_stream, video_stream);
- if (SUCCEEDED(hr))
- IMediaStream_Release(dummy_stream);
- }
-
/* Check interfaces and samples for video */
if (video_stream)
{
@@ -431,58 +942,11 @@ static void test_media_streams(void)
IDirectDrawMediaStream_Release(ddraw_stream);
}
- /* Verify there is no audio media stream */
- hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream);
- ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
-
- /* Verify no stream is created when using the default renderer for audio stream */
- hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL);
- ok((hr == S_OK) || (hr == VFW_E_NO_AUDIO_HARDWARE), "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
- if (hr == S_OK)
- {
- IGraphBuilder* filtergraph = NULL;
- IBaseFilter* filter = NULL;
- const WCHAR name[] = {'0','0','0','1',0};
- CLSID clsid;
-
- hr = IAMMultiMediaStream_GetFilterGraph(pams, &filtergraph);
- ok(hr == S_OK, "IAMMultiMediaStream_GetFilterGraph returned: %x\n", hr);
- if (hr == S_OK)
- {
- hr = IGraphBuilder_FindFilterByName(filtergraph, name, &filter);
- ok(hr == S_OK, "IGraphBuilder_FindFilterByName returned: %x\n", hr);
- }
- if (hr == S_OK)
- {
- hr = IBaseFilter_GetClassID(filter, &clsid);
- ok(hr == S_OK, "IGraphBuilder_FindFilterByName returned: %x\n", hr);
- }
- if (hr == S_OK)
- ok(IsEqualGUID(&clsid, &CLSID_DSoundRender), "Got wrong CLSID\n");
- if (filter)
- IBaseFilter_Release(filter);
- if (filtergraph)
- IGraphBuilder_Release(filtergraph);
- }
- hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream);
- ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
-
- /* Verify a stream is created when no default renderer is used */
hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryAudio, 0, NULL);
ok(hr == S_OK, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream);
ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
- /* verify the audio stream has been added to the media stream filter */
- if (media_stream_filter)
- {
- hr = IMediaStreamFilter_GetMediaStream(media_stream_filter, &MSPID_PrimaryAudio, &dummy_stream);
- ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
- ok(dummy_stream == audio_stream, "Got wrong returned pointer %p, expected %p\n", dummy_stream, audio_stream);
- if (SUCCEEDED(hr))
- IMediaStream_Release(dummy_stream);
- }
-
/* Check interfaces and samples for audio */
if (audio_stream)
{
@@ -1201,6 +1665,7 @@ START_TEST(amstream)
CoInitializeEx(NULL, COINIT_MULTITHREADED);
test_interfaces();
+ test_add_stream();
test_media_streams();
test_enum_pins();
test_find_pin();
--
2.22.0
1
4
30 Aug '19
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/httpapi/httpapi.spec | 1 +
dlls/httpapi/httpapi_main.c | 25 +++++++++++++++++++++++++
include/http.h | 28 ++++++++++++++++++++++++++++
3 files changed, 54 insertions(+)
diff --git a/dlls/httpapi/httpapi.spec b/dlls/httpapi/httpapi.spec
index aad5d58437c..b3f3148acbc 100644
--- a/dlls/httpapi/httpapi.spec
+++ b/dlls/httpapi/httpapi.spec
@@ -49,6 +49,7 @@
@ stub HttpSetControlChannelInformation
@ stub HttpSetServerContextInformation
@ stdcall HttpSetServiceConfiguration(ptr long ptr long ptr)
+@ stdcall HttpSetUrlGroupProperty(int64 long ptr long)
@ stub HttpShutdownAppPool
@ stub HttpShutdownFilter
@ stdcall HttpTerminate(long ptr)
diff --git a/dlls/httpapi/httpapi_main.c b/dlls/httpapi/httpapi_main.c
index c7d95c9fbad..29a8e70301f 100644
--- a/dlls/httpapi/httpapi_main.c
+++ b/dlls/httpapi/httpapi_main.c
@@ -474,6 +474,7 @@ ULONG WINAPI HttpSendHttpResponse(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags,
struct url_group
{
struct list entry, session_entry;
+ HANDLE queue;
};
static struct list url_groups = LIST_INIT(url_groups);
@@ -598,3 +599,27 @@ ULONG WINAPI HttpCloseUrlGroup(HTTP_URL_GROUP_ID id)
return ERROR_SUCCESS;
}
+
+/***********************************************************************
+ * HttpSetUrlGroupProperty (HTTPAPI.@)
+ */
+ULONG WINAPI HttpSetUrlGroupProperty(HTTP_URL_GROUP_ID id, HTTP_SERVER_PROPERTY property, void *value, ULONG length)
+{
+ struct url_group *group = get_url_group(id);
+ const HTTP_BINDING_INFO *info = value;
+
+ TRACE("id %s, property %u, value %p, length %u.\n",
+ wine_dbgstr_longlong(id), property, value, length);
+
+ if (property != HttpServerBindingProperty)
+ {
+ FIXME("Unhandled property %u.\n", property);
+ return ERROR_CALL_NOT_IMPLEMENTED;
+ }
+
+ TRACE("Binding to queue %p.\n", info->RequestQueueHandle);
+
+ group->queue = info->RequestQueueHandle;
+
+ return ERROR_SUCCESS;
+}
diff --git a/include/http.h b/include/http.h
index b07c3b03f93..60494a130f9 100644
--- a/include/http.h
+++ b/include/http.h
@@ -397,6 +397,33 @@ typedef struct _HTTP_LOG_DATA
HTTP_LOG_DATA_TYPE Type;
} HTTP_LOG_DATA, *PHTTP_LOG_DATA;
+typedef enum _HTTP_SERVER_PROPERTY
+{
+ HttpServerAuthenticationProperty,
+ HttpServerLoggingProperty,
+ HttpServerQosProperty,
+ HttpServerTimeoutsProperty,
+ HttpServerQueueLengthProperty,
+ HttpServerStateProperty,
+ HttpServer503VerbosityProperty,
+ HttpServerBindingProperty,
+ HttpServerExtendedAuthenticationProperty,
+ HttpServerListenEndpointProperty,
+ HttpServerChannelBindProperty,
+ HttpServerProtectionLevelProperty,
+} HTTP_SERVER_PROPERTY, *PHTTP_SERVER_PROPERTY;
+
+typedef struct _HTTP_PROPERTY_FLAGS
+{
+ ULONG Present : 1;
+} HTTP_PROPERTY_FLAGS, *PHTTP_PROPERTY_FLAGS;
+
+typedef struct _HTTP_BINDING_INFO
+{
+ HTTP_PROPERTY_FLAGS Flags;
+ HANDLE RequestQueueHandle;
+} HTTP_BINDING_INFO, *PHTTP_BINDING_INFO;
+
ULONG WINAPI HttpAddUrl(HANDLE,PCWSTR,PVOID);
ULONG WINAPI HttpCloseServerSession(HTTP_SERVER_SESSION_ID id);
ULONG WINAPI HttpCloseUrlGroup(HTTP_URL_GROUP_ID id);
@@ -411,6 +438,7 @@ ULONG WINAPI HttpReceiveHttpRequest(HANDLE queue, HTTP_REQUEST_ID id, ULONG flag
ULONG WINAPI HttpRemoveUrl(HANDLE queue, const WCHAR *url);
ULONG WINAPI HttpSendHttpResponse(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags, HTTP_RESPONSE *response, HTTP_CACHE_POLICY *cache_policy, ULONG *ret_size, void *reserved1, ULONG reserved2, OVERLAPPED *ovl, HTTP_LOG_DATA *log_data);
ULONG WINAPI HttpSetServiceConfiguration(HANDLE,HTTP_SERVICE_CONFIG_ID,PVOID,ULONG,LPOVERLAPPED);
+ULONG WINAPI HttpSetUrlGroupProperty(HTTP_URL_GROUP_ID id, HTTP_SERVER_PROPERTY property, void *value, ULONG length);
#ifdef __cplusplus
}
--
2.22.0
2
7