Signed-off-by: Jactry Zeng jzeng@codeweavers.com --- dlls/qasf/Makefile.in | 3 +- dlls/qasf/qasf_classes.idl | 7 ++ dlls/qasf/qasf_main.c | 3 + dlls/qasf/qasf_private.h | 1 + dlls/qasf/tests/Makefile.in | 3 +- dlls/qasf/tests/wmasf.c | 182 ++++++++++++++++++++++++++++++++++++ dlls/qasf/wmasf.c | 67 +++++++++++++ 7 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 dlls/qasf/tests/wmasf.c create mode 100644 dlls/qasf/wmasf.c
diff --git a/dlls/qasf/Makefile.in b/dlls/qasf/Makefile.in index dd02f5a344..d7e0168fab 100644 --- a/dlls/qasf/Makefile.in +++ b/dlls/qasf/Makefile.in @@ -5,7 +5,8 @@ EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \ dmowrapper.c \ - qasf_main.c + qasf_main.c \ + wmasf.c
IDL_SRCS = \ qasf_classes.idl diff --git a/dlls/qasf/qasf_classes.idl b/dlls/qasf/qasf_classes.idl index 0acf380691..b6f6c58fed 100644 --- a/dlls/qasf/qasf_classes.idl +++ b/dlls/qasf/qasf_classes.idl @@ -25,3 +25,10 @@ uuid(94297043-bd82-4dfd-b0de-8177739c6d20), ] coclass DMOWrapperFilter {} + +[ + helpstring("WM ASF Reader"), + threading(both), + uuid(187463a0-5bb7-11d3-acbe-0080c75e246e), +] +coclass WMAsfReader {} diff --git a/dlls/qasf/qasf_main.c b/dlls/qasf/qasf_main.c index 5df23649f0..17301b2494 100644 --- a/dlls/qasf/qasf_main.c +++ b/dlls/qasf/qasf_main.c @@ -99,6 +99,7 @@ static const IClassFactoryVtbl class_factory_vtbl = };
static struct class_factory dmo_wrapper_cf = {{&class_factory_vtbl}, dmo_wrapper_create}; +static struct class_factory wmasf_reader_cf = {{&class_factory_vtbl}, wmasf_reader_create};
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) { @@ -116,6 +117,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out)
if (IsEqualGUID(clsid, &CLSID_DMOWrapperFilter)) return IClassFactory_QueryInterface(&dmo_wrapper_cf.IClassFactory_iface, iid, out); + if (IsEqualIID(clsid, &CLSID_WMAsfReader)) + return IClassFactory_QueryInterface(&wmasf_reader_cf.IClassFactory_iface, iid, out);
FIXME("%s not available, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(clsid)); return CLASS_E_CLASSNOTAVAILABLE; diff --git a/dlls/qasf/qasf_private.h b/dlls/qasf/qasf_private.h index bdb2e433b2..6564194c9e 100644 --- a/dlls/qasf/qasf_private.h +++ b/dlls/qasf/qasf_private.h @@ -30,5 +30,6 @@ #include "wine/strmbase.h"
HRESULT dmo_wrapper_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN; +HRESULT wmasf_reader_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
#endif /* QASF_PRIVATE_H */ diff --git a/dlls/qasf/tests/Makefile.in b/dlls/qasf/tests/Makefile.in index 793f0d2c4b..b622ccf599 100644 --- a/dlls/qasf/tests/Makefile.in +++ b/dlls/qasf/tests/Makefile.in @@ -2,4 +2,5 @@ TESTDLL = qasf.dll IMPORTS = strmbase dmoguids strmiids uuid msdmo ole32
C_SRCS = \ - dmowrapper.c + dmowrapper.c \ + wmasf.c diff --git a/dlls/qasf/tests/wmasf.c b/dlls/qasf/tests/wmasf.c new file mode 100644 index 0000000000..b82aa3a053 --- /dev/null +++ b/dlls/qasf/tests/wmasf.c @@ -0,0 +1,182 @@ +/* + * WM ASF reader unit tests + * + * Copyright 2019 Zebediah Figura + * Copyright 2020 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 + */ + +#define COBJMACROS + +#include "dshow.h" +#include "wine/strmbase.h" +#include "wine/test.h" + +static IBaseFilter *create_wmasf_reader(void) +{ + IBaseFilter *filter = NULL; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_WMAsfReader, NULL, CLSCTX_INPROC_SERVER, + &IID_IBaseFilter, (void **)&filter); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + return filter; +} + +#define expected_ref(obj,ref) expect_ref_((IUnknown*)obj, ref, __LINE__) +static void expect_ref_(IUnknown* obj, ULONG expected_refcount, int line) +{ + ULONG refcount; + IUnknown_AddRef(obj); + refcount = IUnknown_Release(obj); + ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %d, expected %d.\n", + refcount, expected_refcount); +} + +#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c) +static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported) +{ + IUnknown *iface = iface_ptr; + HRESULT hr, expected_hr; + IUnknown *unk; + + expected_hr = supported ? S_OK : E_NOINTERFACE; + + hr = IUnknown_QueryInterface(iface, iid, (void **)&unk); + ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr); + if (SUCCEEDED(hr)) + IUnknown_Release(unk); +} + +static void test_interfaces(void) +{ + IBaseFilter *filter = create_wmasf_reader(); + + check_interface(filter, &IID_IBaseFilter, TRUE); + check_interface(filter, &IID_IMediaFilter, TRUE); + todo_wine check_interface(filter, &IID_IFileSourceFilter, TRUE); + check_interface(filter, &IID_IPersist, TRUE); + check_interface(filter, &IID_IUnknown, TRUE); + + check_interface(filter, &IID_IAMFilterMiscFlags, FALSE); + check_interface(filter, &IID_IMediaSeeking, FALSE); + + IBaseFilter_Release(filter); +} + +static const GUID test_iid = {0x33333333}; +static LONG outer_ref = 1; + +static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID iid, void **out) +{ + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IBaseFilter) || + IsEqualGUID(iid, &test_iid)) + { + *out = (IUnknown *)0xdeadbeef; + return S_OK; + } + ok(0, "Unexpected call %s.\n", wine_dbgstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI outer_AddRef(IUnknown *iface) +{ + return InterlockedIncrement(&outer_ref); +} + +static ULONG WINAPI outer_Release(IUnknown *iface) +{ + return InterlockedDecrement(&outer_ref); +} + +static const IUnknownVtbl outer_vtbl = +{ + outer_QueryInterface, + outer_AddRef, + outer_Release, +}; + +static IUnknown test_outer = {&outer_vtbl}; + +static void test_aggregation(void) +{ + IBaseFilter *filter, *filter2; + IUnknown *unk, *unk2; + HRESULT hr; + ULONG ref; + + filter = (IBaseFilter *)0xdeadbeef; + hr = CoCreateInstance(&CLSID_WMAsfReader, &test_outer, CLSCTX_INPROC_SERVER, + &IID_IBaseFilter, (void **)&filter); + ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr); + ok(!filter, "Got interface %p.\n", filter); + + hr = CoCreateInstance(&CLSID_WMAsfReader, &test_outer, CLSCTX_INPROC_SERVER, + &IID_IUnknown, (void **)&unk); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref); + ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n"); + expected_ref(unk, 1); + + ref = IUnknown_AddRef(unk); + ok(ref == 2, "Got unexpected refcount %d.\n", ref); + ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref); + + ref = IUnknown_Release(unk); + ok(ref == 1, "Got unexpected refcount %d.\n", ref); + ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref); + + hr = IUnknown_QueryInterface(unk, &IID_IUnknown, (void **)&unk2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(unk2 == unk, "Got unexpected IUnknown %p.\n", unk2); + IUnknown_Release(unk2); + + hr = IUnknown_QueryInterface(unk, &IID_IBaseFilter, (void **)&filter); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IBaseFilter_QueryInterface(filter, &IID_IUnknown, (void **)&unk2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2); + + hr = IBaseFilter_QueryInterface(filter, &IID_IBaseFilter, (void **)&filter2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(filter2 == (IBaseFilter *)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2); + + hr = IUnknown_QueryInterface(unk, &test_iid, (void **)&unk2); + ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr); + ok(!unk2, "Got unexpected IUnknown %p.\n", unk2); + + hr = IBaseFilter_QueryInterface(filter, &test_iid, (void **)&unk2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2); + + IBaseFilter_Release(filter); + ref = IUnknown_Release(unk); + ok(!ref, "Got unexpected refcount %d.\n", ref); + ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref); +} + +START_TEST(wmasf) +{ + CoInitializeEx(NULL, COINIT_MULTITHREADED); + + test_interfaces(); + test_aggregation(); + + CoUninitialize(); +} diff --git a/dlls/qasf/wmasf.c b/dlls/qasf/wmasf.c new file mode 100644 index 0000000000..04aaf21367 --- /dev/null +++ b/dlls/qasf/wmasf.c @@ -0,0 +1,67 @@ +/* + * WM ASF reader + * + * Copyright 2020 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 "qasf_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(qasf); + +struct wmasf_reader +{ + struct strmbase_filter filter; +}; + +static inline struct wmasf_reader *impl_reader_from_strmbase_filter(struct strmbase_filter *iface) +{ + return CONTAINING_RECORD(iface, struct wmasf_reader, filter); +} + +static struct strmbase_pin *wmasf_reader_get_pin(struct strmbase_filter *iface, unsigned int index) +{ + return NULL; +} + +static void wmasf_reader_destroy(struct strmbase_filter *iface) +{ + struct wmasf_reader *filter = impl_reader_from_strmbase_filter(iface); + + strmbase_filter_cleanup(&filter->filter); + free(filter); +} + +static struct strmbase_filter_ops filter_ops = +{ + .filter_get_pin = wmasf_reader_get_pin, + .filter_destroy = wmasf_reader_destroy, +}; + +HRESULT wmasf_reader_create(IUnknown *outer, IUnknown **out) +{ + struct wmasf_reader *object; + + if (!(object = calloc(sizeof(*object), 1))) + return E_OUTOFMEMORY; + + strmbase_filter_init(&object->filter, outer, &CLSID_WMAsfReader, &filter_ops); + + TRACE("Created WM ASF reader %p.\n", object); + *out = &object->filter.IUnknown_inner; + + return S_OK; +}
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=68580
Your paranoid android.
=== debiant (32 bit report) ===
qasf: wmasf.c:35: Test failed: Got hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x0040c28e).
Report validation errors: qasf:wmasf crashed (c0000005)
=== debiant (32 bit French report) ===
qasf: wmasf.c:35: Test failed: Got hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x0040c28e).
Report validation errors: qasf:wmasf crashed (c0000005)
=== debiant (32 bit Japanese:Japan report) ===
qasf: wmasf.c:35: Test failed: Got hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x0040c28e).
Report validation errors: qasf:wmasf crashed (c0000005)
=== debiant (32 bit Chinese:China report) ===
qasf: wmasf.c:35: Test failed: Got hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x0040c28e).
Report validation errors: qasf:wmasf crashed (c0000005)
=== debiant (32 bit WoW report) ===
qasf: wmasf.c:35: Test failed: Got hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x0040c28e).
Report validation errors: qasf:wmasf crashed (c0000005)
=== debiant (64 bit WoW report) ===
qasf: wmasf.c:35: Test failed: Got hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x0040c28e).
Report validation errors: qasf:wmasf crashed (c0000005)
On 3/31/20 7:01 PM, Jactry Zeng wrote:
- if (!(object = calloc(sizeof(*object), 1)))
return E_OUTOFMEMORY;
Hi,
arguments are swapped here.
On 3/31/20 11:01 AM, Jactry Zeng wrote:
Signed-off-by: Jactry Zeng jzeng@codeweavers.com
dlls/qasf/Makefile.in | 3 +- dlls/qasf/qasf_classes.idl | 7 ++ dlls/qasf/qasf_main.c | 3 + dlls/qasf/qasf_private.h | 1 + dlls/qasf/tests/Makefile.in | 3 +- dlls/qasf/tests/wmasf.c | 182 ++++++++++++++++++++++++++++++++++++ dlls/qasf/wmasf.c | 67 +++++++++++++ 7 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 dlls/qasf/tests/wmasf.c create mode 100644 dlls/qasf/wmasf.c
diff --git a/dlls/qasf/Makefile.in b/dlls/qasf/Makefile.in index dd02f5a344..d7e0168fab 100644 --- a/dlls/qasf/Makefile.in +++ b/dlls/qasf/Makefile.in @@ -5,7 +5,8 @@ EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \ dmowrapper.c \
- qasf_main.c
- qasf_main.c \
- wmasf.c
Would you mind renaming this to asfreader.c? "wm" is kind of redundant, and I think we want to distinguish the ASF reader from the ASF writer (if we ever do implement the latter).
Similarly "wmasf" can be shortened to "asf" in most places below.
Otherwise I think this patch looks good.
IDL_SRCS = \ qasf_classes.idl diff --git a/dlls/qasf/qasf_classes.idl b/dlls/qasf/qasf_classes.idl index 0acf380691..b6f6c58fed 100644 --- a/dlls/qasf/qasf_classes.idl +++ b/dlls/qasf/qasf_classes.idl @@ -25,3 +25,10 @@ uuid(94297043-bd82-4dfd-b0de-8177739c6d20), ] coclass DMOWrapperFilter {}
+[
- helpstring("WM ASF Reader"),
- threading(both),
- uuid(187463a0-5bb7-11d3-acbe-0080c75e246e),
+] +coclass WMAsfReader {} diff --git a/dlls/qasf/qasf_main.c b/dlls/qasf/qasf_main.c index 5df23649f0..17301b2494 100644 --- a/dlls/qasf/qasf_main.c +++ b/dlls/qasf/qasf_main.c @@ -99,6 +99,7 @@ static const IClassFactoryVtbl class_factory_vtbl = };
static struct class_factory dmo_wrapper_cf = {{&class_factory_vtbl}, dmo_wrapper_create}; +static struct class_factory wmasf_reader_cf = {{&class_factory_vtbl}, wmasf_reader_create};
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) { @@ -116,6 +117,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out)
if (IsEqualGUID(clsid, &CLSID_DMOWrapperFilter)) return IClassFactory_QueryInterface(&dmo_wrapper_cf.IClassFactory_iface, iid, out);
if (IsEqualIID(clsid, &CLSID_WMAsfReader))
return IClassFactory_QueryInterface(&wmasf_reader_cf.IClassFactory_iface, iid, out);
FIXME("%s not available, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(clsid)); return CLASS_E_CLASSNOTAVAILABLE;
diff --git a/dlls/qasf/qasf_private.h b/dlls/qasf/qasf_private.h index bdb2e433b2..6564194c9e 100644 --- a/dlls/qasf/qasf_private.h +++ b/dlls/qasf/qasf_private.h @@ -30,5 +30,6 @@ #include "wine/strmbase.h"
HRESULT dmo_wrapper_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN; +HRESULT wmasf_reader_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
#endif /* QASF_PRIVATE_H */ diff --git a/dlls/qasf/tests/Makefile.in b/dlls/qasf/tests/Makefile.in index 793f0d2c4b..b622ccf599 100644 --- a/dlls/qasf/tests/Makefile.in +++ b/dlls/qasf/tests/Makefile.in @@ -2,4 +2,5 @@ TESTDLL = qasf.dll IMPORTS = strmbase dmoguids strmiids uuid msdmo ole32
C_SRCS = \
- dmowrapper.c
- dmowrapper.c \
- wmasf.c
diff --git a/dlls/qasf/tests/wmasf.c b/dlls/qasf/tests/wmasf.c new file mode 100644 index 0000000000..b82aa3a053 --- /dev/null +++ b/dlls/qasf/tests/wmasf.c @@ -0,0 +1,182 @@ +/*
- WM ASF reader unit tests
- Copyright 2019 Zebediah Figura
- Copyright 2020 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
- */
+#define COBJMACROS
+#include "dshow.h" +#include "wine/strmbase.h" +#include "wine/test.h"
+static IBaseFilter *create_wmasf_reader(void) +{
- IBaseFilter *filter = NULL;
- HRESULT hr;
- hr = CoCreateInstance(&CLSID_WMAsfReader, NULL, CLSCTX_INPROC_SERVER,
&IID_IBaseFilter, (void **)&filter);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- return filter;
+}
+#define expected_ref(obj,ref) expect_ref_((IUnknown*)obj, ref, __LINE__) +static void expect_ref_(IUnknown* obj, ULONG expected_refcount, int line) +{
- ULONG refcount;
- IUnknown_AddRef(obj);
- refcount = IUnknown_Release(obj);
- ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %d, expected %d.\n",
refcount, expected_refcount);
+}
Style nitpick: I'd prefer "check_refcount" here, or alternatively to use the same get_refcount() helper as in other tests. If not, you might also want to change "IUnknown *" to "void *".
+#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c) +static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported) +{
- IUnknown *iface = iface_ptr;
- HRESULT hr, expected_hr;
- IUnknown *unk;
- expected_hr = supported ? S_OK : E_NOINTERFACE;
- hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
- ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr);
- if (SUCCEEDED(hr))
IUnknown_Release(unk);
+}
+static void test_interfaces(void) +{
- IBaseFilter *filter = create_wmasf_reader();
- check_interface(filter, &IID_IBaseFilter, TRUE);
- check_interface(filter, &IID_IMediaFilter, TRUE);
- todo_wine check_interface(filter, &IID_IFileSourceFilter, TRUE);
- check_interface(filter, &IID_IPersist, TRUE);
- check_interface(filter, &IID_IUnknown, TRUE);
- check_interface(filter, &IID_IAMFilterMiscFlags, FALSE);
- check_interface(filter, &IID_IMediaSeeking, FALSE);
In general I try to check for all of the interfaces that the filter graph or capture graph automatically queries, plus any that the filter is documented to expose. Not that I expect the ASF reader to expose IBasicAudio, but I do think it's worth checking for IReferenceClock and IQualityControl at least. The DirectX 9 documentation lists also that this filter supports IAMExtendedSeeking (though we have no header for it, so I don't object to leaving that one out for now), IServiceProvider, IWMHeaderInfo, IWMReaderAdvanced, IWMReaderAdvanced2.
- IBaseFilter_Release(filter);
+}
+static const GUID test_iid = {0x33333333}; +static LONG outer_ref = 1;
+static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID iid, void **out) +{
- if (IsEqualGUID(iid, &IID_IUnknown) ||
IsEqualGUID(iid, &IID_IBaseFilter) ||
IsEqualGUID(iid, &test_iid))
- {
*out = (IUnknown *)0xdeadbeef;
return S_OK;
- }
- ok(0, "Unexpected call %s.\n", wine_dbgstr_guid(iid));
- return E_NOINTERFACE;
+}
+static ULONG WINAPI outer_AddRef(IUnknown *iface) +{
- return InterlockedIncrement(&outer_ref);
+}
+static ULONG WINAPI outer_Release(IUnknown *iface) +{
- return InterlockedDecrement(&outer_ref);
+}
+static const IUnknownVtbl outer_vtbl = +{
- outer_QueryInterface,
- outer_AddRef,
- outer_Release,
+};
+static IUnknown test_outer = {&outer_vtbl};
+static void test_aggregation(void) +{
- IBaseFilter *filter, *filter2;
- IUnknown *unk, *unk2;
- HRESULT hr;
- ULONG ref;
- filter = (IBaseFilter *)0xdeadbeef;
- hr = CoCreateInstance(&CLSID_WMAsfReader, &test_outer, CLSCTX_INPROC_SERVER,
&IID_IBaseFilter, (void **)&filter);
- ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
- ok(!filter, "Got interface %p.\n", filter);
- hr = CoCreateInstance(&CLSID_WMAsfReader, &test_outer, CLSCTX_INPROC_SERVER,
&IID_IUnknown, (void **)&unk);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
- ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n");
- expected_ref(unk, 1);
- ref = IUnknown_AddRef(unk);
- ok(ref == 2, "Got unexpected refcount %d.\n", ref);
- ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
- ref = IUnknown_Release(unk);
- ok(ref == 1, "Got unexpected refcount %d.\n", ref);
- ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
- hr = IUnknown_QueryInterface(unk, &IID_IUnknown, (void **)&unk2);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(unk2 == unk, "Got unexpected IUnknown %p.\n", unk2);
- IUnknown_Release(unk2);
- hr = IUnknown_QueryInterface(unk, &IID_IBaseFilter, (void **)&filter);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IBaseFilter_QueryInterface(filter, &IID_IUnknown, (void **)&unk2);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
- hr = IBaseFilter_QueryInterface(filter, &IID_IBaseFilter, (void **)&filter2);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(filter2 == (IBaseFilter *)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2);
- hr = IUnknown_QueryInterface(unk, &test_iid, (void **)&unk2);
- ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
- ok(!unk2, "Got unexpected IUnknown %p.\n", unk2);
- hr = IBaseFilter_QueryInterface(filter, &test_iid, (void **)&unk2);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
- IBaseFilter_Release(filter);
- ref = IUnknown_Release(unk);
- ok(!ref, "Got unexpected refcount %d.\n", ref);
- ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
+}
+START_TEST(wmasf) +{
- CoInitializeEx(NULL, COINIT_MULTITHREADED);
- test_interfaces();
- test_aggregation();
- CoUninitialize();
+} diff --git a/dlls/qasf/wmasf.c b/dlls/qasf/wmasf.c new file mode 100644 index 0000000000..04aaf21367 --- /dev/null +++ b/dlls/qasf/wmasf.c @@ -0,0 +1,67 @@ +/*
- WM ASF reader
- Copyright 2020 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 "qasf_private.h"
+WINE_DEFAULT_DEBUG_CHANNEL(qasf);
+struct wmasf_reader +{
- struct strmbase_filter filter;
+};
+static inline struct wmasf_reader *impl_reader_from_strmbase_filter(struct strmbase_filter *iface) +{
- return CONTAINING_RECORD(iface, struct wmasf_reader, filter);
+}
+static struct strmbase_pin *wmasf_reader_get_pin(struct strmbase_filter *iface, unsigned int index) +{
- return NULL;
+}
+static void wmasf_reader_destroy(struct strmbase_filter *iface) +{
- struct wmasf_reader *filter = impl_reader_from_strmbase_filter(iface);
- strmbase_filter_cleanup(&filter->filter);
- free(filter);
+}
+static struct strmbase_filter_ops filter_ops = +{
- .filter_get_pin = wmasf_reader_get_pin,
- .filter_destroy = wmasf_reader_destroy,
+};
+HRESULT wmasf_reader_create(IUnknown *outer, IUnknown **out) +{
- struct wmasf_reader *object;
- if (!(object = calloc(sizeof(*object), 1)))
return E_OUTOFMEMORY;
- strmbase_filter_init(&object->filter, outer, &CLSID_WMAsfReader, &filter_ops);
- TRACE("Created WM ASF reader %p.\n", object);
- *out = &object->filter.IUnknown_inner;
- return S_OK;
+}
Thank you, Nikolay and Zebediah. I sent a v2.