Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- 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
September 2018
- 70 participants
- 1549 messages
[PATCH v2 2/8] user32/listbox: Make SetCount fail if LBS_NODATA is not set
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/user32/listbox.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c
index c8bd148..529a47b 100644
--- a/dlls/user32/listbox.c
+++ b/dlls/user32/listbox.c
@@ -1757,7 +1757,7 @@ static LRESULT LISTBOX_SetCount( LB_DESCR *descr, INT count )
{
LRESULT ret;
- if (HAS_STRINGS(descr))
+ if (!(descr->style & LBS_NODATA))
{
SetLastError(ERROR_SETCOUNT_ON_BAD_LB);
return LB_ERR;
@@ -2523,6 +2523,9 @@ static BOOL LISTBOX_Create( HWND hwnd, LPHEADCOMBO lphc )
if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT;
descr->item_height = LISTBOX_SetFont( descr, 0 );
+ if ((descr->style & (LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_SORT)) != LBS_OWNERDRAWFIXED)
+ descr->style &= ~LBS_NODATA;
+
if (descr->style & LBS_OWNERDRAWFIXED)
{
if( descr->lphc && (descr->lphc->dwStyle & CBS_DROPDOWN))
--
1.9.1
Sept. 20, 2018
[PATCH v2 1/8] comctl32/listbox: Make SetCount fail if LBS_NODATA is not set
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
Supersedes series starting with 151474.
v2: Looks like Windows accepts both LBS_OWNERDRAWFIXED and
LBS_OWNERDRAWVARIABLE at once, for some stupid reason, and only
LBS_OWNERDRAWFIXED takes effect (based on testing on Windows XP). So keep
LBS_NODATA if they're both set.
dlls/comctl32/listbox.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/comctl32/listbox.c b/dlls/comctl32/listbox.c
index 2137ef8..0a7c341 100644
--- a/dlls/comctl32/listbox.c
+++ b/dlls/comctl32/listbox.c
@@ -1752,7 +1752,7 @@ static LRESULT LISTBOX_SetCount( LB_DESCR *descr, INT count )
{
LRESULT ret;
- if (HAS_STRINGS(descr))
+ if (!(descr->style & LBS_NODATA))
{
SetLastError(ERROR_SETCOUNT_ON_BAD_LB);
return LB_ERR;
@@ -2518,6 +2518,9 @@ static BOOL LISTBOX_Create( HWND hwnd, LPHEADCOMBO lphc )
if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT;
descr->item_height = LISTBOX_SetFont( descr, 0 );
+ if ((descr->style & (LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_SORT)) != LBS_OWNERDRAWFIXED)
+ descr->style &= ~LBS_NODATA;
+
if (descr->style & LBS_OWNERDRAWFIXED)
{
if( descr->lphc && (descr->lphc->dwStyle & CBS_DROPDOWN))
--
1.9.1
Sept. 20, 2018
Re: [PATCH v2 8/8] shell32/tests: Handle WM_SETTEXT for autocompletion
by Gabriel Ivăncescu
Sorry, I messed up the component, this should NOT be shell32/tests but
shell32/autocomplete.
Sept. 20, 2018
Re: [PATCH v2 4/8] shell32/autocomplete: Don't autocomplete at all on most control characters
by Gabriel Ivăncescu
On Thu, Sep 20, 2018 at 3:51 PM, Nikolay Sivov <nsivov(a)codeweavers.com> wrote:
> Maybe filter with iscntrlW() with exceptions?
>
>
I only tried to avoid most of the CTRL+something control characters. I
see iscntrlW deals with Unicode table (probably some unicode-specific
control chars as well). So I think the current method has less
implications, but that depends on my understanding of it.
Do you think it's a better approach with iscntrlW? (and keep the range
between \b and \r then as the exceptions?). Unfortunately it would
still look like a semi-hack due to the exceptions which are needed, at
least for backspace and maybe tab. Not sure if it's better honestly.
Sept. 20, 2018
Re: [PATCH 5/5] quartz/filtergraph: Check pin name instead of id in connect_output_pin().
by Marvin
Hi,
While running your changed tests on Windows, 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=42327
Your paranoid android.
=== w864 (64 bit Windows report) ===
=== w864 (task log) ===
Task errors:
TestBot process got stuck or died unexpectedly
The previous 1 run(s) terminated abnormally
Sept. 20, 2018
[PATCH 5/5] quartz/filtergraph: Check pin name instead of id in connect_output_pin().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/filtergraph.c | 20 ++++++--------------
dlls/quartz/tests/filtergraph.c | 41 ++++++++++++++++++++++++++++++++++++++---
2 files changed, 44 insertions(+), 17 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index fb1bfc2..03d4091 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -1075,9 +1075,8 @@ static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPi
static HRESULT connect_output_pin(IFilterGraphImpl *graph, IBaseFilter *filter, IPin *sink)
{
IEnumPins *enumpins;
- PIN_DIRECTION dir;
+ PIN_INFO info;
HRESULT hr;
- WCHAR *id;
IPin *pin;
hr = IBaseFilter_EnumPins(filter, &enumpins);
@@ -1086,20 +1085,13 @@ static HRESULT connect_output_pin(IFilterGraphImpl *graph, IBaseFilter *filter,
while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
{
- IPin_QueryDirection(pin, &dir);
- if (dir == PINDIR_OUTPUT)
+ IPin_QueryPinInfo(pin, &info);
+ IBaseFilter_Release(info.pFilter);
+ if (info.dir == PINDIR_OUTPUT)
{
- hr = IPin_QueryId(pin, &id);
- if (FAILED(hr))
+ if (info.achName[0] == '~')
{
- IPin_Release(pin);
- IEnumPins_Release(enumpins);
- return hr;
- }
-
- if (id[0] == '~')
- {
- TRACE("Skipping non-rendered pin %s.\n", debugstr_w(id));
+ TRACE("Skipping non-rendered pin %s.\n", debugstr_w(info.achName));
IPin_Release(pin);
IEnumPins_Release(enumpins);
return E_FAIL;
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 76dfc16..d9dc66b 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -768,6 +768,8 @@ struct testpin
IBaseFilter *filter;
IPin *peer;
AM_MEDIA_TYPE *mt;
+ WCHAR name[10];
+ WCHAR id[10];
IEnumMediaTypes IEnumMediaTypes_iface;
const AM_MEDIA_TYPE *types;
@@ -928,7 +930,7 @@ static HRESULT WINAPI testpin_QueryPinInfo(IPin *iface, PIN_INFO *info)
info->pFilter = pin->filter;
IBaseFilter_AddRef(pin->filter);
info->dir = pin->dir;
- info->achName[0] = 0;
+ lstrcpyW(info->achName, pin->name);
return S_OK;
}
@@ -944,9 +946,10 @@ static HRESULT WINAPI testpin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
static HRESULT WINAPI testpin_QueryId(IPin *iface, WCHAR **id)
{
+ struct testpin *pin = impl_from_IPin(iface);
if (winetest_debug > 1) trace("%p->QueryId()\n", iface);
- *id = CoTaskMemAlloc(1);
- (*id)[0] = 0;
+ *id = CoTaskMemAlloc(11);
+ lstrcpyW(*id, pin->id);
return S_OK;
}
@@ -1770,6 +1773,38 @@ todo_wine
IFilterGraph2_Disconnect(graph, sink_pin.peer);
IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+ /* A pin whose name (not ID) begins with a tilde is not connected. */
+
+ parser1_pins[1].name[0] = '~';
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+todo_wine
+ ok(hr == VFW_E_CANNOT_CONNECT, "Got hr %#x.\n", hr);
+ ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
+
+ parser1.pin_count = 3;
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+todo_wine {
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &parser1_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(sink_pin.peer == &parser1_pins[2].IPin_iface, "Got peer %p.\n", sink_pin.peer);
+}
+ IFilterGraph2_Disconnect(graph, source_pin.peer);
+ IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+ IFilterGraph2_Disconnect(graph, sink_pin.peer);
+ IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+ parser1.pin_count = 2;
+
+ parser1_pins[1].name[0] = 0;
+ parser1_pins[1].id[0] = '~';
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &parser1_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(sink_pin.peer == &parser1_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
+ IFilterGraph2_Disconnect(graph, source_pin.peer);
+ IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+ IFilterGraph2_Disconnect(graph, sink_pin.peer);
+ IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+
ref = IFilterGraph2_Release(graph);
ok(!ref, "Got outstanding refcount %d.\n", ref);
--
2.7.4
Sept. 20, 2018
[PATCH 4/5] quartz/filtergraph: Try filters in the graph first in FilterGraph2_Connect().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/filtergraph.c | 35 ++++++++++++++++++++++++++++++++---
dlls/quartz/tests/filtergraph.c | 11 +----------
2 files changed, 33 insertions(+), 13 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index 6fe5b80..fb1bfc2 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -1123,7 +1123,9 @@ static HRESULT connect_output_pin(IFilterGraphImpl *graph, IBaseFilter *filter,
static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn)
{
IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
+ struct filter *filter;
HRESULT hr;
+ IPin *pin;
AM_MEDIA_TYPE* mt = NULL;
IEnumMediaTypes* penummt = NULL;
ULONG nbmt;
@@ -1131,7 +1133,6 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
IEnumMoniker* pEnumMoniker;
GUID tab[2];
IMoniker* pMoniker;
- ULONG pin;
PIN_INFO PinInfo;
CLSID FilterCLSID;
PIN_DIRECTION dir;
@@ -1194,6 +1195,34 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
TRACE("Direct connection failed, trying to render using extra filters\n");
+ LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
+ {
+ hr = IBaseFilter_EnumPins(filter->filter, &penumpins);
+ if (FAILED(hr))
+ goto out;
+
+ while (IEnumPins_Next(penumpins, 1, &pin, NULL) == S_OK)
+ {
+ IPin_QueryDirection(pin, &dir);
+ if (dir == PINDIR_INPUT && SUCCEEDED(IFilterGraph2_ConnectDirect(iface,
+ ppinOut, pin, NULL)))
+ {
+ if (SUCCEEDED(hr = connect_output_pin(This, filter->filter, ppinIn)))
+ {
+ IPin_Release(pin);
+ IEnumPins_Release(penumpins);
+ goto out;
+ }
+
+ IFilterGraph2_Disconnect(iface, pin);
+ IFilterGraph2_Disconnect(iface, ppinOut);
+ }
+ IPin_Release(pin);
+ }
+
+ IEnumPins_Release(penumpins);
+ }
+
hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
if (FAILED(hr))
goto out;
@@ -1324,14 +1353,14 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
goto error;
}
- hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
+ hr = IEnumPins_Next(penumpins, 1, &ppinfilter, NULL);
IEnumPins_Release(penumpins);
if (FAILED(hr)) {
WARN("Obtaining next pin: (%x)\n", hr);
goto error;
}
- if (pin == 0) {
+ if (hr == S_FALSE) {
WARN("Cannot use this filter: no pins\n");
goto error;
}
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 5bfe7b6..76dfc16 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -1701,11 +1701,9 @@ todo_wine
sink_pin.accept_mt = &sink_type;
hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
-todo_wine {
ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(source_pin.peer == &parser2_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
ok(sink_pin.peer == &parser2_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
-}
IFilterGraph2_Disconnect(graph, source_pin.peer);
IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
IFilterGraph2_Disconnect(graph, sink_pin.peer);
@@ -1715,11 +1713,9 @@ todo_wine {
IFilterGraph2_AddFilter(graph, &parser1.IBaseFilter_iface, NULL);
hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
-todo_wine {
ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(source_pin.peer == &parser1_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
ok(sink_pin.peer == &parser1_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
-}
IFilterGraph2_Disconnect(graph, source_pin.peer);
IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
IFilterGraph2_Disconnect(graph, sink_pin.peer);
@@ -1729,12 +1725,10 @@ todo_wine {
IFilterGraph2_AddFilter(graph, &parser3.IBaseFilter_iface, NULL);
hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
-todo_wine {
ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(source_pin.peer == &parser3_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
ok(parser3_pins[1].peer == &parser1_pins[0].IPin_iface, "Got peer %p.\n", parser3_pins[1].peer);
ok(sink_pin.peer == &parser1_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
-}
IFilterGraph2_Disconnect(graph, source_pin.peer);
IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
IFilterGraph2_Disconnect(graph, parser3_pins[0].peer);
@@ -1753,11 +1747,10 @@ todo_wine {
IFilterGraph2_AddFilter(graph, &sink2.IBaseFilter_iface, NULL);
hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
-todo_wine {
+todo_wine
ok(hr == VFW_S_PARTIAL_RENDER, "Got hr %#x.\n", hr);
ok(source_pin.peer == &parser1_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
ok(sink_pin.peer == &parser1_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
-}
ok(!parser1_pins[2].peer, "Got peer %p.\n", parser1_pins[2].peer);
IFilterGraph2_Disconnect(graph, source_pin.peer);
IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
@@ -1769,11 +1762,9 @@ todo_wine {
parser1_pins[1].QueryInternalConnections_hr = S_OK;
hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
-todo_wine {
ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(source_pin.peer == &parser1_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
ok(sink_pin.peer == &parser1_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
-}
IFilterGraph2_Disconnect(graph, source_pin.peer);
IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
IFilterGraph2_Disconnect(graph, sink_pin.peer);
--
2.7.4
Sept. 20, 2018
[PATCH 3/5] quartz/filtergraph: Don't use QueryInternalConnections() to find output pins in FilterGraph2_Connect().
by Zebediah Figura
The tests need the following patch in order to pass.
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/filtergraph.c | 102 +++++++++++++++++++++++-----------------------
1 file changed, 52 insertions(+), 50 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index 1fa6476..6fe5b80 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -1070,6 +1070,55 @@ static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPi
return S_OK;
}
+/* Attempt to connect one of the output pins on filter to sink. Helper for
+ * FilterGraph2_Connect(). */
+static HRESULT connect_output_pin(IFilterGraphImpl *graph, IBaseFilter *filter, IPin *sink)
+{
+ IEnumPins *enumpins;
+ PIN_DIRECTION dir;
+ HRESULT hr;
+ WCHAR *id;
+ IPin *pin;
+
+ hr = IBaseFilter_EnumPins(filter, &enumpins);
+ if (FAILED(hr))
+ return hr;
+
+ while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
+ {
+ IPin_QueryDirection(pin, &dir);
+ if (dir == PINDIR_OUTPUT)
+ {
+ hr = IPin_QueryId(pin, &id);
+ if (FAILED(hr))
+ {
+ IPin_Release(pin);
+ IEnumPins_Release(enumpins);
+ return hr;
+ }
+
+ if (id[0] == '~')
+ {
+ TRACE("Skipping non-rendered pin %s.\n", debugstr_w(id));
+ IPin_Release(pin);
+ IEnumPins_Release(enumpins);
+ return E_FAIL;
+ }
+
+ if (SUCCEEDED(IFilterGraph2_Connect(&graph->IFilterGraph2_iface, pin, sink)))
+ {
+ IPin_Release(pin);
+ IEnumPins_Release(enumpins);
+ return S_OK;
+ }
+ }
+ IPin_Release(pin);
+ }
+
+ IEnumPins_Release(enumpins);
+ return VFW_E_CANNOT_CONNECT;
+}
+
/*** IGraphBuilder methods ***/
static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn)
{
@@ -1081,13 +1130,11 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
IEnumPins* penumpins;
IEnumMoniker* pEnumMoniker;
GUID tab[2];
- ULONG nb = 0;
IMoniker* pMoniker;
ULONG pin;
PIN_INFO PinInfo;
CLSID FilterCLSID;
PIN_DIRECTION dir;
- unsigned int i = 0;
IFilterMapper2 *pFilterMapper2 = NULL;
TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
@@ -1196,11 +1243,10 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
}
hr = VFW_E_CANNOT_RENDER;
- while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
+ while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, NULL) == S_OK)
{
VARIANT var;
GUID clsid;
- IPin** ppins = NULL;
IPin* ppinfilter = NULL;
IBaseFilter* pfilter = NULL;
IAMGraphBuilderCallback *callback = NULL;
@@ -1297,52 +1343,10 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
}
TRACE("Successfully connected to filter, follow chain...\n");
- /* Render all output pins of the filter by calling IFilterGraph2_Connect on each of them */
- hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
-
- if (SUCCEEDED(hr)) {
- if (nb == 0) {
- IPin_Disconnect(ppinfilter);
- IPin_Disconnect(ppinOut);
- goto error;
- }
- TRACE("pins to consider: %d\n", nb);
- for(i = 0; i < nb; i++)
- {
- LPWSTR pinname = NULL;
-
- TRACE("Processing pin %u\n", i);
-
- hr = IPin_QueryId(ppins[i], &pinname);
- if (SUCCEEDED(hr))
- {
- if (pinname[0] == '~')
- {
- TRACE("Pinname=%s, skipping\n", debugstr_w(pinname));
- hr = E_FAIL;
- }
- else
- hr = IFilterGraph2_Connect(iface, ppins[i], ppinIn);
- CoTaskMemFree(pinname);
- }
-
- if (FAILED(hr)) {
- TRACE("Cannot connect pin %p (%x)\n", ppinfilter, hr);
- }
- IPin_Release(ppins[i]);
- if (SUCCEEDED(hr)) break;
- }
- while (++i < nb) IPin_Release(ppins[i]);
- CoTaskMemFree(ppins);
+ if (SUCCEEDED(hr = connect_output_pin(This, pfilter, ppinIn)))
+ {
IPin_Release(ppinfilter);
IBaseFilter_Release(pfilter);
- if (FAILED(hr))
- {
- IPin_Disconnect(ppinfilter);
- IPin_Disconnect(ppinOut);
- IFilterGraph2_RemoveFilter(iface, pfilter);
- continue;
- }
break;
}
@@ -1353,8 +1357,6 @@ error:
IFilterGraph2_RemoveFilter(iface, pfilter);
IBaseFilter_Release(pfilter);
}
- while (++i < nb) IPin_Release(ppins[i]);
- CoTaskMemFree(ppins);
}
IEnumMoniker_Release(pEnumMoniker);
--
2.7.4
Sept. 20, 2018
[PATCH 2/5] quartz/tests: Add some tests for IGraphBuilder_Connect().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/filtergraph.c | 375 +++++++++++++++++++++++++++++++++++++---
1 file changed, 354 insertions(+), 21 deletions(-)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index b1059ca..5bfe7b6 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -538,7 +538,7 @@ static void rungraph(IFilterGraph2 *graph)
test_media_event(graph);
}
-static HRESULT test_graph_builder_connect(WCHAR *filename)
+static HRESULT test_graph_builder_connect_file(WCHAR *filename)
{
static const WCHAR outputW[] = {'O','u','t','p','u','t',0};
static const WCHAR inW[] = {'I','n',0};
@@ -608,7 +608,7 @@ static void test_render_run(const WCHAR *file)
refs = IFilterGraph2_Release(graph);
ok(!refs, "Graph has %u references\n", refs);
- hr = test_graph_builder_connect(filename);
+ hr = test_graph_builder_connect_file(filename);
todo_wine
ok(hr == VFW_E_CANNOT_CONNECT, "got %#x\n", hr);
}
@@ -620,7 +620,7 @@ todo_wine
refs = IFilterGraph2_Release(graph);
ok(!refs, "Graph has %u references\n", refs);
- hr = test_graph_builder_connect(filename);
+ hr = test_graph_builder_connect_file(filename);
ok(hr == S_OK || hr == VFW_S_PARTIAL_RENDER, "got %#x\n", hr);
}
@@ -772,6 +772,9 @@ struct testpin
IEnumMediaTypes IEnumMediaTypes_iface;
const AM_MEDIA_TYPE *types;
unsigned int type_count, enum_idx;
+ AM_MEDIA_TYPE *request_mt, *accept_mt;
+
+ HRESULT QueryInternalConnections_hr;
};
static inline struct testpin *impl_from_IEnumMediaTypes(IEnumMediaTypes *iface)
@@ -942,7 +945,9 @@ static HRESULT WINAPI testpin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
static HRESULT WINAPI testpin_QueryId(IPin *iface, WCHAR **id)
{
if (winetest_debug > 1) trace("%p->QueryId()\n", iface);
- return E_NOTIMPL;
+ *id = CoTaskMemAlloc(1);
+ (*id)[0] = 0;
+ return S_OK;
}
static HRESULT WINAPI testpin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mt)
@@ -964,8 +969,11 @@ static HRESULT WINAPI testpin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **out)
static HRESULT WINAPI testpin_QueryInternalConnections(IPin *iface, IPin **out, ULONG *count)
{
- if (winetest_debug > 1) trace("%p->QueryInternalConnections()\n", iface);
- return E_NOTIMPL;
+ struct testpin *pin = impl_from_IPin(iface);
+ if (winetest_debug > 1) trace("%p->QueryInternalConnections()\n", pin);
+
+ *count = 0;
+ return pin->QueryInternalConnections_hr;
}
static HRESULT WINAPI testpin_BeginFlush(IPin *iface)
@@ -1015,6 +1023,9 @@ static HRESULT WINAPI testsink_ReceiveConnection(IPin *iface, IPin *peer, const
struct testpin *pin = impl_from_IPin(iface);
if (winetest_debug > 1) trace("%p->ReceiveConnection(%p)\n", pin, peer);
+ if (pin->accept_mt && memcmp(pin->accept_mt, mt, sizeof(*mt)))
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
pin->peer = peer;
IPin_AddRef(peer);
return S_OK;
@@ -1042,26 +1053,35 @@ static const IPinVtbl testsink_vtbl =
testpin_NewSegment
};
-static void testsink_init(struct testpin *pin)
+static void testpin_init(struct testpin *pin, const IPinVtbl *vtbl, PIN_DIRECTION dir)
{
memset(pin, 0, sizeof(*pin));
- pin->IPin_iface.lpVtbl = &testsink_vtbl;
- pin->ref = 1;
- pin->dir = PINDIR_INPUT;
-
+ pin->IPin_iface.lpVtbl = vtbl;
pin->IEnumMediaTypes_iface.lpVtbl = &testenummt_vtbl;
+ pin->ref = 1;
+ pin->dir = dir;
+ pin->QueryInternalConnections_hr = E_NOTIMPL;
+}
+
+static void testsink_init(struct testpin *pin)
+{
+ testpin_init(pin, &testsink_vtbl, PINDIR_INPUT);
}
static HRESULT WINAPI testsource_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
{
struct testpin *pin = impl_from_IPin(iface);
+ HRESULT hr;
if (winetest_debug > 1) trace("%p->Connect(%p)\n", pin, peer);
ok(!mt, "Got media type %p.\n", mt);
- pin->peer = peer;
- IPin_AddRef(peer);
- return IPin_ReceiveConnection(peer, &pin->IPin_iface, mt);
+ if (SUCCEEDED(hr = IPin_ReceiveConnection(peer, &pin->IPin_iface, pin->request_mt)))
+ {
+ pin->peer = peer;
+ IPin_AddRef(peer);
+ }
+ return hr;
}
static const IPinVtbl testsource_vtbl =
@@ -1088,12 +1108,7 @@ static const IPinVtbl testsource_vtbl =
static void testsource_init(struct testpin *pin, const AM_MEDIA_TYPE *types, int type_count)
{
- memset(pin, 0, sizeof(*pin));
- pin->IPin_iface.lpVtbl = &testsource_vtbl;
- pin->ref = 1;
- pin->dir = PINDIR_OUTPUT;
-
- pin->IEnumMediaTypes_iface.lpVtbl = &testenummt_vtbl;
+ testpin_init(pin, &testsource_vtbl, PINDIR_OUTPUT);
pin->types = types;
pin->type_count = type_count;
}
@@ -1224,7 +1239,7 @@ static ULONG WINAPI testfilter_Release(IBaseFilter *iface)
static HRESULT WINAPI testfilter_GetClassID(IBaseFilter *iface, CLSID *clsid)
{
if (winetest_debug > 1) trace("%p->GetClassID()\n", iface);
- return E_NOTIMPL;
+ return S_OK;
}
static HRESULT WINAPI testfilter_Stop(IBaseFilter *iface)
@@ -1608,6 +1623,292 @@ out:
ok(parser_pins[1].ref == 1, "Got outstanding refcount %d.\n", parser_pins[1].ref);
}
+static void test_graph_builder_connect(void)
+{
+ static const WCHAR testW[] = {'t','e','s','t',0};
+ static const GUID parser1_clsid = {0x12345678};
+ static const GUID parser2_clsid = {0x87654321};
+ AM_MEDIA_TYPE source_type = {{0}}, sink_type = {{0}}, parser3_type = {{0}};
+ struct testpin source_pin, sink_pin, sink2_pin, parser1_pins[3], parser2_pins[2], parser3_pins[2];
+ struct testfilter source, sink, sink2, parser1, parser2, parser3;
+ struct testfilter_cf parser1_cf = { {&testfilter_cf_vtbl}, &parser1 };
+ struct testfilter_cf parser2_cf = { {&testfilter_cf_vtbl}, &parser2 };
+
+ IFilterGraph2 *graph = create_graph();
+ REGFILTERPINS2 regpins[2] = {0};
+ REGPINTYPES regtypes = {0};
+ REGFILTER2 regfilter = {0};
+ IFilterMapper2 *mapper;
+ DWORD cookie1, cookie2;
+ HRESULT hr;
+ ULONG ref;
+
+ memset(&source_type.majortype, 0xcc, sizeof(GUID));
+ memset(&sink_type.majortype, 0x66, sizeof(GUID));
+ testsource_init(&source_pin, &source_type, 1);
+ source_pin.request_mt = &source_type;
+ testfilter_init(&source, &source_pin, 1);
+ testsink_init(&sink_pin);
+ testfilter_init(&sink, &sink_pin, 1);
+ testsink_init(&sink2_pin);
+ testfilter_init(&sink2, &sink2_pin, 1);
+
+ testsink_init(&parser1_pins[0]);
+ testsource_init(&parser1_pins[1], &sink_type, 1);
+ parser1_pins[1].request_mt = &sink_type;
+ testsource_init(&parser1_pins[2], &sink_type, 1);
+ parser1_pins[2].request_mt = &sink_type;
+ testfilter_init(&parser1, parser1_pins, 3);
+ parser1.pin_count = 2;
+
+ testsink_init(&parser2_pins[0]);
+ testsource_init(&parser2_pins[1], &sink_type, 1);
+ parser2_pins[1].request_mt = &sink_type;
+ testfilter_init(&parser2, parser2_pins, 2);
+
+ testsink_init(&parser3_pins[0]);
+ testsource_init(&parser3_pins[1], &sink_type, 1);
+ parser3_pins[1].request_mt = &parser3_type;
+ testfilter_init(&parser3, parser3_pins, 2);
+
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &sink.IBaseFilter_iface, NULL);
+
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+ IFilterGraph2_Disconnect(graph, source_pin.peer);
+ IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+
+ sink_pin.accept_mt = &sink_type;
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+todo_wine
+ ok(hr == VFW_E_CANNOT_CONNECT, "Got hr %#x.\n", hr);
+ ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
+
+ /* Test usage of intermediate filters. Similarly to Render(), filters are
+ * simply tried in enumeration order. */
+
+ IFilterGraph2_AddFilter(graph, &parser1.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &parser2.IBaseFilter_iface, NULL);
+
+ sink_pin.accept_mt = NULL;
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+ IFilterGraph2_Disconnect(graph, source_pin.peer);
+ IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+
+ sink_pin.accept_mt = &sink_type;
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+todo_wine {
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &parser2_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(sink_pin.peer == &parser2_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
+}
+ IFilterGraph2_Disconnect(graph, source_pin.peer);
+ IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+ IFilterGraph2_Disconnect(graph, sink_pin.peer);
+ IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+
+ IFilterGraph2_RemoveFilter(graph, &parser1.IBaseFilter_iface);
+ IFilterGraph2_AddFilter(graph, &parser1.IBaseFilter_iface, NULL);
+
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+todo_wine {
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &parser1_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(sink_pin.peer == &parser1_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
+}
+ IFilterGraph2_Disconnect(graph, source_pin.peer);
+ IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+ IFilterGraph2_Disconnect(graph, sink_pin.peer);
+ IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+
+ /* No preference is given to smaller chains. */
+
+ IFilterGraph2_AddFilter(graph, &parser3.IBaseFilter_iface, NULL);
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+todo_wine {
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &parser3_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(parser3_pins[1].peer == &parser1_pins[0].IPin_iface, "Got peer %p.\n", parser3_pins[1].peer);
+ ok(sink_pin.peer == &parser1_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
+}
+ IFilterGraph2_Disconnect(graph, source_pin.peer);
+ IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+ IFilterGraph2_Disconnect(graph, parser3_pins[0].peer);
+ IFilterGraph2_Disconnect(graph, &parser3_pins[0].IPin_iface);
+ IFilterGraph2_Disconnect(graph, sink_pin.peer);
+ IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+
+ IFilterGraph2_RemoveFilter(graph, &parser3.IBaseFilter_iface);
+ IFilterGraph2_RemoveFilter(graph, &parser2.IBaseFilter_iface);
+
+ /* Extra source pins on an intermediate filter are not rendered. */
+
+ IFilterGraph2_RemoveFilter(graph, &parser1.IBaseFilter_iface);
+ parser1.pin_count = 3;
+ IFilterGraph2_AddFilter(graph, &parser1.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &sink2.IBaseFilter_iface, NULL);
+
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+todo_wine {
+ ok(hr == VFW_S_PARTIAL_RENDER, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &parser1_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(sink_pin.peer == &parser1_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
+}
+ ok(!parser1_pins[2].peer, "Got peer %p.\n", parser1_pins[2].peer);
+ IFilterGraph2_Disconnect(graph, source_pin.peer);
+ IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+ IFilterGraph2_Disconnect(graph, sink_pin.peer);
+ IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+ parser1.pin_count = 2;
+
+ /* QueryInternalConnections is not used to find output pins. */
+
+ parser1_pins[1].QueryInternalConnections_hr = S_OK;
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+todo_wine {
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &parser1_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(sink_pin.peer == &parser1_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
+}
+ IFilterGraph2_Disconnect(graph, source_pin.peer);
+ IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+ IFilterGraph2_Disconnect(graph, sink_pin.peer);
+ IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ /* Test enumeration of filters from the registry. */
+
+ graph = create_graph();
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &sink.IBaseFilter_iface, NULL);
+
+ CoRegisterClassObject(&parser1_clsid, (IUnknown *)&parser1_cf.IClassFactory_iface,
+ CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie1);
+ CoRegisterClassObject(&parser2_clsid, (IUnknown *)&parser2_cf.IClassFactory_iface,
+ CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie2);
+
+ CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IFilterMapper2, (void **)&mapper);
+
+ regfilter.dwVersion = 2;
+ regfilter.dwMerit = MERIT_UNLIKELY;
+ regfilter.cPins2 = 2;
+ regfilter.rgPins2 = regpins;
+ regpins[0].dwFlags = 0;
+ regpins[0].cInstances = 1;
+ regpins[0].nMediaTypes = 1;
+ regpins[0].lpMediaType = ®types;
+ regpins[1].dwFlags = REG_PINFLAG_B_OUTPUT;
+ regpins[1].cInstances = 1;
+ regpins[1].nMediaTypes = 1;
+ regpins[1].lpMediaType = ®types;
+ regtypes.clsMajorType = &source_type.majortype;
+ regtypes.clsMinorType = &MEDIASUBTYPE_NULL;
+ hr = IFilterMapper2_RegisterFilter(mapper, &parser1_clsid, testW, NULL, NULL, NULL, ®filter);
+ if (hr == E_ACCESSDENIED)
+ {
+ skip("Not enough permission to register filters.\n");
+ goto out;
+ }
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IFilterMapper2_RegisterFilter(mapper, &parser2_clsid, testW, NULL, NULL, NULL, ®filter);
+
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &parser1_pins[0].IPin_iface
+ || source_pin.peer == &parser2_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(sink_pin.peer == &parser1_pins[1].IPin_iface
+ || sink_pin.peer == &parser2_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
+
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ /* Preference is given to filters already in the graph. */
+
+ graph = create_graph();
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &sink.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &parser1.IBaseFilter_iface, NULL);
+
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &parser1_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(sink_pin.peer == &parser1_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
+
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ /* Preference is given to filters with higher merit. */
+
+ graph = create_graph();
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &sink.IBaseFilter_iface, NULL);
+
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &parser1_clsid);
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &parser2_clsid);
+
+ regfilter.dwMerit = MERIT_UNLIKELY;
+ IFilterMapper2_RegisterFilter(mapper, &parser1_clsid, testW, NULL, NULL, NULL, ®filter);
+ regfilter.dwMerit = MERIT_PREFERRED;
+ IFilterMapper2_RegisterFilter(mapper, &parser2_clsid, testW, NULL, NULL, NULL, ®filter);
+
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &parser2_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(sink_pin.peer == &parser2_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
+
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ graph = create_graph();
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &sink.IBaseFilter_iface, NULL);
+
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &parser1_clsid);
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &parser2_clsid);
+
+ regfilter.dwMerit = MERIT_PREFERRED;
+ IFilterMapper2_RegisterFilter(mapper, &parser1_clsid, testW, NULL, NULL, NULL, ®filter);
+ regfilter.dwMerit = MERIT_UNLIKELY;
+ IFilterMapper2_RegisterFilter(mapper, &parser2_clsid, testW, NULL, NULL, NULL, ®filter);
+
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &parser1_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(sink_pin.peer == &parser1_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer);
+
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &parser1_clsid);
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &parser2_clsid);
+
+out:
+ CoRevokeClassObject(cookie1);
+ CoRevokeClassObject(cookie2);
+ IFilterMapper2_Release(mapper);
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ok(source.ref == 1, "Got outstanding refcount %d.\n", source.ref);
+ ok(source_pin.ref == 1, "Got outstanding refcount %d.\n", source_pin.ref);
+ ok(sink.ref == 1, "Got outstanding refcount %d.\n", sink.ref);
+ ok(sink_pin.ref == 1, "Got outstanding refcount %d.\n", sink_pin.ref);
+ ok(parser1.ref == 1, "Got outstanding refcount %d.\n", parser1.ref);
+ ok(parser1_pins[0].ref == 1, "Got outstanding refcount %d.\n", parser1_pins[0].ref);
+ ok(parser1_pins[1].ref == 1, "Got outstanding refcount %d.\n", parser1_pins[1].ref);
+ ok(parser1_pins[2].ref == 1, "Got outstanding refcount %d.\n", parser1_pins[2].ref);
+ ok(parser2.ref == 1, "Got outstanding refcount %d.\n", parser2.ref);
+ ok(parser2_pins[0].ref == 1, "Got outstanding refcount %d.\n", parser2_pins[0].ref);
+ ok(parser2_pins[1].ref == 1, "Got outstanding refcount %d.\n", parser2_pins[1].ref);
+ ok(parser3.ref == 1, "Got outstanding refcount %d.\n", parser3.ref);
+ ok(parser3_pins[0].ref == 1, "Got outstanding refcount %d.\n", parser3_pins[0].ref);
+ ok(parser3_pins[1].ref == 1, "Got outstanding refcount %d.\n", parser3_pins[1].ref);
+}
+
typedef struct IUnknownImpl
{
IUnknown IUnknown_iface;
@@ -1942,6 +2243,22 @@ static void test_connect_direct(void)
ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+ hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(!source_pin.mt, "Got mt %p.\n", source_pin.mt);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
+ hr = IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
+ hr = IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
/* Swap the pins when connecting. */
hr = IFilterGraph2_ConnectDirect(graph, &sink_pin.IPin_iface, &source_pin.IPin_iface, NULL);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -1958,6 +2275,21 @@ todo_wine
ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+ hr = IFilterGraph2_Connect(graph, &sink_pin.IPin_iface, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+todo_wine
+ ok(sink_pin.peer == &source_pin.IPin_iface, "Got peer %p.\n", sink_pin.peer);
+ ok(!sink_pin.mt, "Got mt %p.\n", sink_pin.mt);
+todo_wine
+ ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
+
+ hr = IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+todo_wine
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+todo_wine
+ ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
/* Disconnect() does not disconnect the peer. */
hr = IFilterGraph2_ConnectDirect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface, NULL);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -2024,6 +2356,7 @@ START_TEST(filtergraph)
test_render_run(mpegfile);
test_enum_filters();
test_graph_builder_render();
+ test_graph_builder_connect();
test_aggregate_filter_graph();
test_control_delegation();
test_add_remove_filter();
--
2.7.4
Sept. 20, 2018
[PATCH 1/5] quartz/tests: Add some tests for IFilterGraph_ConnectDirect() and IFilterGraph_Disconnect().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/filtergraph.c | 184 ++++++++++++++++++++++++++++++++++++----
1 file changed, 168 insertions(+), 16 deletions(-)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 5035f80..b1059ca 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -767,6 +767,7 @@ struct testpin
PIN_DIRECTION dir;
IBaseFilter *filter;
IPin *peer;
+ AM_MEDIA_TYPE *mt;
IEnumMediaTypes IEnumMediaTypes_iface;
const AM_MEDIA_TYPE *types;
@@ -991,7 +992,19 @@ static HRESULT WINAPI testpin_EndOfStream(IPin *iface)
return E_NOTIMPL;
}
-static HRESULT WINAPI testsink_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+static HRESULT WINAPI no_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI no_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI no_EnumMediaTypes(IPin *iface, IEnumMediaTypes **out)
{
ok(0, "Unexpected call.\n");
return E_NOTIMPL;
@@ -1007,18 +1020,12 @@ static HRESULT WINAPI testsink_ReceiveConnection(IPin *iface, IPin *peer, const
return S_OK;
}
-static HRESULT WINAPI testsink_EnumMediaTypes(IPin *iface, IEnumMediaTypes **out)
-{
- ok(0, "Unexpected call.\n");
- return E_NOTIMPL;
-}
-
static const IPinVtbl testsink_vtbl =
{
testpin_QueryInterface,
testpin_AddRef,
testpin_Release,
- testsink_Connect,
+ no_Connect,
testsink_ReceiveConnection,
testpin_Disconnect,
testpin_ConnectedTo,
@@ -1027,7 +1034,7 @@ static const IPinVtbl testsink_vtbl =
testpin_QueryDirection,
testpin_QueryId,
testpin_QueryAccept,
- testsink_EnumMediaTypes,
+ no_EnumMediaTypes,
testpin_QueryInternalConnections,
testpin_EndOfStream,
testpin_BeginFlush,
@@ -1057,19 +1064,13 @@ static HRESULT WINAPI testsource_Connect(IPin *iface, IPin *peer, const AM_MEDIA
return IPin_ReceiveConnection(peer, &pin->IPin_iface, mt);
}
-static HRESULT WINAPI testsource_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
-{
- ok(0, "Unexpected call.\n");
- return E_NOTIMPL;
-}
-
static const IPinVtbl testsource_vtbl =
{
testpin_QueryInterface,
testpin_AddRef,
testpin_Release,
testsource_Connect,
- testsource_ReceiveConnection,
+ no_ReceiveConnection,
testpin_Disconnect,
testpin_ConnectedTo,
testpin_ConnectionMediaType,
@@ -1864,6 +1865,156 @@ static void test_add_remove_filter(void)
ok(filter.ref == 1, "Got outstanding refcount %d.\n", filter.ref);
}
+static HRESULT WINAPI test_connect_direct_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+ struct testpin *pin = impl_from_IPin(iface);
+ if (winetest_debug > 1) trace("%p->Connect()\n", pin);
+
+ pin->peer = peer;
+ IPin_AddRef(peer);
+ pin->mt = (AM_MEDIA_TYPE *)mt;
+ return S_OK;
+}
+
+static const IPinVtbl test_connect_direct_vtbl =
+{
+ testpin_QueryInterface,
+ testpin_AddRef,
+ testpin_Release,
+ test_connect_direct_Connect,
+ no_ReceiveConnection,
+ testpin_Disconnect,
+ testpin_ConnectedTo,
+ testpin_ConnectionMediaType,
+ testpin_QueryPinInfo,
+ testpin_QueryDirection,
+ testpin_QueryId,
+ testpin_QueryAccept,
+ no_EnumMediaTypes,
+ testpin_QueryInternalConnections,
+ testpin_EndOfStream,
+ testpin_BeginFlush,
+ testpin_EndFlush,
+ testpin_NewSegment
+};
+
+static void test_connect_direct_init(struct testpin *pin, PIN_DIRECTION dir)
+{
+ memset(pin, 0, sizeof(*pin));
+ pin->IPin_iface.lpVtbl = &test_connect_direct_vtbl;
+ pin->ref = 1;
+ pin->dir = dir;
+}
+
+static void test_connect_direct(void)
+{
+ struct testpin source_pin, sink_pin;
+ struct testfilter source, sink;
+
+ IFilterGraph2 *graph = create_graph();
+ AM_MEDIA_TYPE mt;
+ HRESULT hr;
+
+ test_connect_direct_init(&source_pin, PINDIR_OUTPUT);
+ test_connect_direct_init(&sink_pin, PINDIR_INPUT);
+ testfilter_init(&source, &source_pin, 1);
+ testfilter_init(&sink, &sink_pin, 1);
+
+ hr = IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_AddFilter(graph, &sink.IBaseFilter_iface, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_ConnectDirect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(!source_pin.mt, "Got mt %p.\n", source_pin.mt);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
+ hr = IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
+ hr = IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
+ /* Swap the pins when connecting. */
+ hr = IFilterGraph2_ConnectDirect(graph, &sink_pin.IPin_iface, &source_pin.IPin_iface, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+todo_wine
+ ok(sink_pin.peer == &source_pin.IPin_iface, "Got peer %p.\n", sink_pin.peer);
+ ok(!sink_pin.mt, "Got mt %p.\n", sink_pin.mt);
+todo_wine
+ ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
+
+ hr = IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+todo_wine
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+todo_wine
+ ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
+ /* Disconnect() does not disconnect the peer. */
+ hr = IFilterGraph2_ConnectDirect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(!source_pin.mt, "Got mt %p.\n", source_pin.mt);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
+ sink_pin.peer = &source_pin.IPin_iface;
+ IPin_AddRef(sink_pin.peer);
+
+ hr = IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
+ hr = IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
+ /* Test specifying the media type. */
+ hr = IFilterGraph2_ConnectDirect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface, &mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(source_pin.mt == &mt, "Got mt %p.\n", source_pin.mt);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
+ /* Both pins are disconnected when a filter is removed. */
+ sink_pin.peer = &source_pin.IPin_iface;
+ IPin_AddRef(sink_pin.peer);
+ hr = IFilterGraph2_RemoveFilter(graph, &source.IBaseFilter_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+
+ /* Or when the graph is destroyed. */
+ hr = IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_ConnectDirect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(!source_pin.mt, "Got mt %p.\n", source_pin.mt);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+ IPin_AddRef(sink_pin.peer = &source_pin.IPin_iface);
+
+ hr = IFilterGraph2_Release(graph);
+ ok(!hr, "Got outstanding refcount %d.\n", hr);
+ ok(source.ref == 1, "Got outstanding refcount %d.\n", source.ref);
+ ok(sink.ref == 1, "Got outstanding refcount %d.\n", sink.ref);
+ ok(source_pin.ref == 1, "Got outstanding refcount %d.\n", source_pin.ref);
+todo_wine
+ ok(sink_pin.ref == 1, "Got outstanding refcount %d.\n", sink_pin.ref);
+ ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
+ ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
+}
+
START_TEST(filtergraph)
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
@@ -1876,6 +2027,7 @@ START_TEST(filtergraph)
test_aggregate_filter_graph();
test_control_delegation();
test_add_remove_filter();
+ test_connect_direct();
CoUninitialize();
test_render_with_multithread();
--
2.7.4
Sept. 20, 2018