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
December 2019
- 73 participants
- 1394 messages
Re: [PATCH 3/4] quartz/tests: Port IVideoWindow tests to the VMR.
by Marvin
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=61441
Your paranoid android.
=== wxppro (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== wvistau64 (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w2008s64 (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w7u (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w8 (32 bit report) ===
quartz:
vmr7.c:2063: Test failed: Thread should not block.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w8adm (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w864 (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1507 (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809 (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_2scr (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_ar (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_he (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_ja (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_zh_CN (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== wvistau64 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w2008s64 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w864 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1507 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w8 (32 bit report) ===
quartz:
vmr9.c:2066: Test failed: Got unexpected status 0x80000.
=== w1064v1507 (32 bit report) ===
quartz:
vmr9.c:2066: Test failed: Got unexpected status 0x80000.
=== w864 (64 bit report) ===
quartz:
vmr9.c:2066: Test failed: Got unexpected status 0x80000.
Dec. 6, 2019
Re: [PATCH 1/4] strmbase: Correctly implement IVideoWindow::NotifyOwnerMessage().
by Marvin
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=61439
Your paranoid android.
=== wxppro (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w2003std (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== wvistau64 (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w2008s64 (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w7u (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w8 (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w8adm (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w1064v1809 (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w1064v1809_2scr (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w1064v1809_ar (32 bit report) ===
quartz:
videorenderer.c:969: Test failed: Thread should block in Receive().
=== w1064v1809_he (32 bit report) ===
quartz:
videorenderer.c:969: Test failed: Thread should block in Receive().
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w1064v1809_ja (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w1064v1809_zh_CN (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== wvistau64 (64 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w2008s64 (64 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w864 (64 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w1064v1507 (64 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
Dec. 6, 2019
[PATCH 4/4] strmbase: Create the video window with the correct styles.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/videorenderer.c | 8 ++++----
dlls/quartz/tests/vmr7.c | 8 ++++----
dlls/quartz/tests/vmr9.c | 8 ++++----
dlls/strmbase/window.c | 3 ++-
4 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c
index 320d8920d1..1c64bedbee 100644
--- a/dlls/quartz/tests/videorenderer.c
+++ b/dlls/quartz/tests/videorenderer.c
@@ -1467,11 +1467,11 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
@@ -1490,10 +1490,10 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c
index fa1ae99856..d6d51decec 100644
--- a/dlls/quartz/tests/vmr7.c
+++ b/dlls/quartz/tests/vmr7.c
@@ -1629,11 +1629,11 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
@@ -1652,10 +1652,10 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index 3c5986e1f5..c91f9a3527 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -1626,11 +1626,11 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
@@ -1649,10 +1649,10 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
diff --git a/dlls/strmbase/window.c b/dlls/strmbase/window.c
index 04132aaab1..07a12eca26 100644
--- a/dlls/strmbase/window.c
+++ b/dlls/strmbase/window.c
@@ -118,7 +118,8 @@ HRESULT WINAPI BaseWindowImpl_PrepareWindow(BaseWindow *This)
return E_FAIL;
}
- This->hWnd = CreateWindowExW(0, class_nameW, windownameW, WS_SIZEBOX,
+ This->hWnd = CreateWindowExW(0, class_nameW, windownameW,
+ WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL, NULL);
--
2.24.0
Dec. 6, 2019
[PATCH 3/4] quartz/tests: Port IVideoWindow tests to the VMR.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/vmr7.c | 808 +++++++++++++++++++++++++++++++++++++++
dlls/quartz/tests/vmr9.c | 807 ++++++++++++++++++++++++++++++++++++++
2 files changed, 1615 insertions(+)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c
index 93c16caede..fa1ae99856 100644
--- a/dlls/quartz/tests/vmr7.c
+++ b/dlls/quartz/tests/vmr7.c
@@ -1565,6 +1565,813 @@ static void test_overlay(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+/* try to make sure pending X events have been processed before continuing */
+static void flush_events(void)
+{
+ int diff = 200;
+ DWORD time;
+ MSG msg;
+
+ time = GetTickCount() + diff;
+ while (diff > 0)
+ {
+ if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
+ break;
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ DispatchMessageA(&msg);
+ diff = time - GetTickCount();
+ }
+}
+
+static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (winetest_debug > 1)
+ trace("hwnd %p, msg %#x, wparam %#lx, lparam %#lx.\n", hwnd, msg, wparam, lparam);
+
+ if (wparam == 0xdeadbeef)
+ return 0;
+
+ return DefWindowProcA(hwnd, msg, wparam, lparam);
+}
+
+static void test_video_window_caption(IVideoWindow *window, HWND hwnd)
+{
+ WCHAR text[50];
+ BSTR caption;
+ HRESULT hr;
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!wcscmp(caption, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(caption));
+ SysFreeString(caption);
+
+ GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ ok(!wcscmp(text, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(text));
+
+ caption = SysAllocString(L"foo");
+ hr = IVideoWindow_put_Caption(window, caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ SysFreeString(caption);
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!wcscmp(caption, L"foo"), "Got caption %s.\n", wine_dbgstr_w(caption));
+ SysFreeString(caption);
+
+ GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ ok(!wcscmp(text, L"foo"), "Got caption %s.\n", wine_dbgstr_w(text));
+}
+
+static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HRESULT hr;
+ LONG style;
+
+ hr = IVideoWindow_get_WindowStyle(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_HSCROLL);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_VSCROLL);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_MAXIMIZE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_MINIMIZE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_WindowStyle(window, style & ~WS_CLIPCHILDREN);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyle(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_get_WindowStyleEx(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_EXSTYLE);
+ ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_WindowStyleEx(window, style | WS_EX_TRANSPARENT);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyleEx(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_EXSTYLE);
+ ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
+}
+
+static BOOL CALLBACK top_window_cb(HWND hwnd, LPARAM ctx)
+{
+ DWORD pid;
+ GetWindowThreadProcessId(hwnd, &pid);
+ if (pid == GetCurrentProcessId() && (GetWindowLongW(hwnd, GWL_STYLE) & WS_VISIBLE))
+ {
+ *(HWND *)ctx = hwnd;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static HWND get_top_window(void)
+{
+ HWND hwnd;
+ EnumWindows(top_window_cb, (LPARAM)&hwnd);
+ return hwnd;
+}
+
+static void test_video_window_state(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HRESULT hr;
+ LONG state;
+ HWND top;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+
+ hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ hr = IVideoWindow_put_WindowState(window, SW_MINIMIZE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_MINIMIZE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(IsIconic(hwnd), "Window should be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_MAXIMIZE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_MAXIMIZE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should be minimized.\n");
+ ok(IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_WindowState(window, SW_HIDE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_Visible(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_SetWindowForeground(window, TRUE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hr = IVideoWindow_SetWindowForeground(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == our_hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == our_hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+}
+
+static void test_video_window_position(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ LONG left, width, top, height, expect_width, expect_height;
+ RECT rect = {0, 0, 600, 400};
+ HWND top_hwnd;
+ HRESULT hr;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ AdjustWindowRect(&rect, GetWindowLongA(hwnd, GWL_STYLE), FALSE);
+ expect_width = rect.right - rect.left;
+ expect_height = rect.bottom - rect.top;
+
+ hr = IVideoWindow_put_Left(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_Top(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 0, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 0, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 0, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == expect_width, "Got window right %d.\n", rect.right);
+ todo_wine ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_put_Left(window, 10);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 10, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
+ todo_wine ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_put_Height(window, 200);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(height == 200, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ ok(height == 200, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 10, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
+ ok(rect.bottom == 200, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_SetWindowPosition(window, 100, 200, 300, 400);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 100, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 200, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(width == 300, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(height == 400, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 100, "Got left %d.\n", left);
+ ok(top == 200, "Got top %d.\n", top);
+ ok(width == 300, "Got width %d.\n", width);
+ ok(height == 400, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 100, "Got window left %d.\n", rect.left);
+ ok(rect.top == 200, "Got window top %d.\n", rect.top);
+ ok(rect.right == 400, "Got window right %d.\n", rect.right);
+ ok(rect.bottom == 600, "Got window bottom %d.\n", rect.bottom);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
+}
+
+static void test_video_window_owner(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HWND parent, top_hwnd;
+ LONG style, state;
+ OAHWND oahwnd;
+ HRESULT hr;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok(!(style & WS_CHILD), "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(oahwnd == (OAHWND)our_hwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == our_hwnd, "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok((style & WS_CHILD), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
+
+ ShowWindow(our_hwnd, SW_HIDE);
+
+ hr = IVideoWindow_put_Visible(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_put_Owner(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok(!(style & WS_CHILD), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == hwnd, "Got top window %p.\n", top_hwnd);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == OATRUE, "Got state %d.\n", state);
+}
+
+struct notify_message_params
+{
+ IVideoWindow *window;
+ HWND hwnd;
+ UINT message;
+};
+
+static DWORD CALLBACK notify_message_proc(void *arg)
+{
+ const struct notify_message_params *params = arg;
+ HRESULT hr = IVideoWindow_NotifyOwnerMessage(params->window, (OAHWND)params->hwnd, params->message, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ return 0;
+}
+
+static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ struct notify_message_params params;
+ unsigned int i;
+ OAHWND oahwnd;
+ HANDLE thread;
+ HRESULT hr;
+ BOOL ret;
+ MSG msg;
+
+ static UINT drain_tests[] =
+ {
+ WM_MOUSEACTIVATE,
+ WM_NCLBUTTONDOWN,
+ WM_NCLBUTTONUP,
+ WM_NCLBUTTONDBLCLK,
+ WM_NCRBUTTONDOWN,
+ WM_NCRBUTTONUP,
+ WM_NCRBUTTONDBLCLK,
+ WM_NCMBUTTONDOWN,
+ WM_NCMBUTTONUP,
+ WM_NCMBUTTONDBLCLK,
+ WM_KEYDOWN,
+ WM_KEYUP,
+ WM_MOUSEMOVE,
+ WM_LBUTTONDOWN,
+ WM_LBUTTONUP,
+ WM_LBUTTONDBLCLK,
+ WM_RBUTTONDOWN,
+ WM_RBUTTONUP,
+ WM_RBUTTONDBLCLK,
+ WM_MBUTTONDOWN,
+ WM_MBUTTONUP,
+ WM_MBUTTONDBLCLK,
+ };
+
+ flush_events();
+
+ hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got window %#lx.\n", oahwnd);
+
+ hr = IVideoWindow_put_MessageDrain(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(oahwnd == (OAHWND)our_hwnd, "Got window %#lx.\n", oahwnd);
+
+ for (i = 0; i < ARRAY_SIZE(drain_tests); ++i)
+ {
+ SendMessageA(hwnd, drain_tests[i], 0xdeadbeef, 0);
+ ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
+ ok(ret, "Expected a message.\n");
+ ok(msg.hwnd == our_hwnd, "Got hwnd %p.\n", msg.hwnd);
+ ok(msg.message == drain_tests[i], "Got message %#x.\n", msg.message);
+ ok(msg.wParam == 0xdeadbeef, "Got wparam %#lx.\n", msg.wParam);
+ ok(!msg.lParam, "Got lparam %#lx.\n", msg.lParam);
+ DispatchMessageA(&msg);
+
+ ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
+ ok(!ret, "Got unexpected message %#x.\n", msg.message);
+ }
+
+ hr = IVideoWindow_put_MessageDrain(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ flush_events();
+
+ hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SYSCOLORCHANGE, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SETCURSOR,
+ (WPARAM)hwnd, MAKELONG(HTCLIENT, WM_MOUSEMOVE));
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ params.window = window;
+ params.hwnd = our_hwnd;
+ params.message = WM_SYSCOLORCHANGE;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block.\n");
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(ret == ((QS_SENDMESSAGE << 16) | QS_SENDMESSAGE), "Got unexpected status %#x.\n", ret);
+
+ PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
+ ok(!WaitForSingleObject(thread, 100), "Wait timed out.\n");
+ CloseHandle(thread);
+
+ params.message = WM_SETCURSOR;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(!WaitForSingleObject(thread, 100), "Thread should not block.\n");
+ CloseHandle(thread);
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ hr = IVideoWindow_put_Owner(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+}
+
+static void test_video_window_autoshow(IVideoWindow *window, IFilterGraph2 *graph, HWND hwnd)
+{
+ IMediaControl *control;
+ HRESULT hr;
+ LONG l;
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ hr = IVideoWindow_get_AutoShow(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IVideoWindow_put_AutoShow(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(l == OAFALSE, "Got %d.\n", l);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+}
+
+static void test_video_window(void)
+{
+ ALLOCATOR_PROPERTIES req_props = {1, 600 * 400 * 4, 1, 0}, ret_props;
+ VIDEOINFOHEADER vih =
+ {
+ .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
+ .bmiHeader.biBitCount = 32,
+ .bmiHeader.biWidth = 600,
+ .bmiHeader.biHeight = 400,
+ .bmiHeader.biPlanes = 1,
+ .bmiHeader.biCompression = BI_RGB,
+ };
+ AM_MEDIA_TYPE req_mt =
+ {
+ .majortype = MEDIATYPE_Video,
+ .subtype = MEDIASUBTYPE_RGB32,
+ .formattype = FORMAT_VideoInfo,
+ .cbFormat = sizeof(vih),
+ .pbFormat = (BYTE *)&vih,
+ };
+ IFilterGraph2 *graph = create_graph();
+ WNDCLASSA window_class = {0};
+ struct testfilter source;
+ IMemAllocator *allocator;
+ IMediaControl *control;
+ LONG width, height, l;
+ IVideoWindow *window;
+ IMemInputPin *input;
+ IBaseFilter *filter;
+ HWND hwnd, our_hwnd;
+ IOverlay *overlay;
+ BSTR caption;
+ HRESULT hr;
+ DWORD tid;
+ ULONG ref;
+ IPin *pin;
+ RECT rect;
+
+ window_class.lpszClassName = "wine_test_class";
+ window_class.lpfnWndProc = window_proc;
+ RegisterClassA(&window_class);
+ our_hwnd = CreateWindowA("wine_test_class", "test window", WS_VISIBLE | WS_OVERLAPPEDWINDOW,
+ 100, 200, 300, 400, NULL, NULL, NULL, NULL);
+ flush_events();
+
+ filter = create_vmr7(0);
+ flush_events();
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
+ IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input);
+
+ hr = IPin_QueryInterface(pin, &IID_IOverlay, (void **)&overlay);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IOverlay_GetWindowHandle(overlay, &hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (winetest_debug > 1) trace("ours %p, theirs %p\n", our_hwnd, hwnd);
+ GetWindowRect(hwnd, &rect);
+
+ tid = GetWindowThreadProcessId(hwnd, NULL);
+ ok(tid == GetCurrentThreadId(), "Expected tid %#x, got %#x.\n", GetCurrentThreadId(), tid);
+
+ hr = IBaseFilter_QueryInterface(filter, &IID_IVideoWindow, (void **)&window);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyle(window, &l);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_AutoShow(window, &l);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ testfilter_init(&source);
+ IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, filter, NULL);
+ hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
+ if (hr == VFW_E_TYPE_NOT_ACCEPTED) /* w7u */
+ {
+ req_mt.subtype = MEDIASUBTYPE_RGB24;
+ vih.bmiHeader.biBitCount = 24;
+ req_props.cbBuffer = 32 * 16 * 3;
+ hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
+ }
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMemInputPin_GetAllocator(input, &allocator);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ {
+ hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n");
+ hr = IMemAllocator_Commit(allocator);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ IMemAllocator_Release(allocator);
+ }
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ test_video_window_caption(window, hwnd);
+ test_video_window_style(window, hwnd, our_hwnd);
+ test_video_window_state(window, hwnd, our_hwnd);
+ test_video_window_position(window, hwnd, our_hwnd);
+ test_video_window_autoshow(window, graph, hwnd);
+ test_video_window_owner(window, hwnd, our_hwnd);
+ test_video_window_messages(window, hwnd, our_hwnd);
+
+ hr = IVideoWindow_put_FullScreenMode(window, OATRUE);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_get_FullScreenMode(window, &l);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_GetMinIdealImageSize(window, &width, &height);
+ todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_GetMaxIdealImageSize(window, &width, &height);
+ todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_GetMinIdealImageSize(window, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(width == 600, "Got width %d.\n", width);
+ ok(height == 400, "Got height %d.\n", height);
+ hr = IVideoWindow_GetMaxIdealImageSize(window, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(width == 600, "Got width %d.\n", width);
+ ok(height == 400, "Got height %d.\n", height);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+ IFilterGraph2_Release(graph);
+ IVideoWindow_Release(window);
+ IOverlay_Release(overlay);
+ IMemInputPin_Release(input);
+ IPin_Release(pin);
+ ref = IBaseFilter_Release(filter);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ DestroyWindow(our_hwnd);
+}
+
START_TEST(vmr7)
{
CoInitialize(NULL);
@@ -1580,6 +2387,7 @@ START_TEST(vmr7)
test_unconnected_filter_state();
test_connect_pin();
test_overlay();
+ test_video_window();
CoUninitialize();
}
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index 128d4abbc6..3c5986e1f5 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -1562,6 +1562,812 @@ static void test_overlay(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+/* try to make sure pending X events have been processed before continuing */
+static void flush_events(void)
+{
+ int diff = 200;
+ DWORD time;
+ MSG msg;
+
+ time = GetTickCount() + diff;
+ while (diff > 0)
+ {
+ if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
+ break;
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ DispatchMessageA(&msg);
+ diff = time - GetTickCount();
+ }
+}
+
+static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (winetest_debug > 1)
+ trace("hwnd %p, msg %#x, wparam %#lx, lparam %#lx.\n", hwnd, msg, wparam, lparam);
+
+ if (wparam == 0xdeadbeef)
+ return 0;
+
+ return DefWindowProcA(hwnd, msg, wparam, lparam);
+}
+
+static void test_video_window_caption(IVideoWindow *window, HWND hwnd)
+{
+ WCHAR text[50];
+ BSTR caption;
+ HRESULT hr;
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!wcscmp(caption, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(caption));
+ SysFreeString(caption);
+
+ GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ ok(!wcscmp(text, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(text));
+
+ caption = SysAllocString(L"foo");
+ hr = IVideoWindow_put_Caption(window, caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ SysFreeString(caption);
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!wcscmp(caption, L"foo"), "Got caption %s.\n", wine_dbgstr_w(caption));
+ SysFreeString(caption);
+
+ GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ ok(!wcscmp(text, L"foo"), "Got caption %s.\n", wine_dbgstr_w(text));
+}
+
+static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HRESULT hr;
+ LONG style;
+
+ hr = IVideoWindow_get_WindowStyle(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_HSCROLL);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_VSCROLL);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_MAXIMIZE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_MINIMIZE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_WindowStyle(window, style & ~WS_CLIPCHILDREN);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyle(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_get_WindowStyleEx(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_EXSTYLE);
+ ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_WindowStyleEx(window, style | WS_EX_TRANSPARENT);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyleEx(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_EXSTYLE);
+ ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
+}
+
+static BOOL CALLBACK top_window_cb(HWND hwnd, LPARAM ctx)
+{
+ DWORD pid;
+ GetWindowThreadProcessId(hwnd, &pid);
+ if (pid == GetCurrentProcessId() && (GetWindowLongW(hwnd, GWL_STYLE) & WS_VISIBLE))
+ {
+ *(HWND *)ctx = hwnd;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static HWND get_top_window(void)
+{
+ HWND hwnd;
+ EnumWindows(top_window_cb, (LPARAM)&hwnd);
+ return hwnd;
+}
+
+static void test_video_window_state(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HRESULT hr;
+ LONG state;
+ HWND top;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+
+ hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ hr = IVideoWindow_put_WindowState(window, SW_MINIMIZE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_MINIMIZE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(IsIconic(hwnd), "Window should be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_MAXIMIZE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_MAXIMIZE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should be minimized.\n");
+ ok(IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_WindowState(window, SW_HIDE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_Visible(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_SetWindowForeground(window, TRUE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hr = IVideoWindow_SetWindowForeground(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == our_hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == our_hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+}
+
+static void test_video_window_position(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ LONG left, width, top, height, expect_width, expect_height;
+ RECT rect = {0, 0, 600, 400};
+ HWND top_hwnd;
+ HRESULT hr;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ AdjustWindowRect(&rect, GetWindowLongA(hwnd, GWL_STYLE), FALSE);
+ expect_width = rect.right - rect.left;
+ expect_height = rect.bottom - rect.top;
+
+ hr = IVideoWindow_put_Left(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_Top(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 0, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 0, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 0, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == expect_width, "Got window right %d.\n", rect.right);
+ todo_wine ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_put_Left(window, 10);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 10, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
+ todo_wine ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_put_Height(window, 200);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(height == 200, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ ok(height == 200, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 10, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
+ ok(rect.bottom == 200, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_SetWindowPosition(window, 100, 200, 300, 400);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 100, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 200, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(width == 300, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(height == 400, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 100, "Got left %d.\n", left);
+ ok(top == 200, "Got top %d.\n", top);
+ ok(width == 300, "Got width %d.\n", width);
+ ok(height == 400, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 100, "Got window left %d.\n", rect.left);
+ ok(rect.top == 200, "Got window top %d.\n", rect.top);
+ ok(rect.right == 400, "Got window right %d.\n", rect.right);
+ ok(rect.bottom == 600, "Got window bottom %d.\n", rect.bottom);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
+}
+
+static void test_video_window_owner(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HWND parent, top_hwnd;
+ LONG style, state;
+ OAHWND oahwnd;
+ HRESULT hr;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok(!(style & WS_CHILD), "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(oahwnd == (OAHWND)our_hwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == our_hwnd, "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok((style & WS_CHILD), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
+
+ ShowWindow(our_hwnd, SW_HIDE);
+
+ hr = IVideoWindow_put_Visible(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_put_Owner(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok(!(style & WS_CHILD), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == hwnd, "Got top window %p.\n", top_hwnd);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == OATRUE, "Got state %d.\n", state);
+}
+
+struct notify_message_params
+{
+ IVideoWindow *window;
+ HWND hwnd;
+ UINT message;
+};
+
+static DWORD CALLBACK notify_message_proc(void *arg)
+{
+ const struct notify_message_params *params = arg;
+ HRESULT hr = IVideoWindow_NotifyOwnerMessage(params->window, (OAHWND)params->hwnd, params->message, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ return 0;
+}
+
+static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ struct notify_message_params params;
+ unsigned int i;
+ OAHWND oahwnd;
+ HANDLE thread;
+ HRESULT hr;
+ BOOL ret;
+ MSG msg;
+
+ static UINT drain_tests[] =
+ {
+ WM_MOUSEACTIVATE,
+ WM_NCLBUTTONDOWN,
+ WM_NCLBUTTONUP,
+ WM_NCLBUTTONDBLCLK,
+ WM_NCRBUTTONDOWN,
+ WM_NCRBUTTONUP,
+ WM_NCRBUTTONDBLCLK,
+ WM_NCMBUTTONDOWN,
+ WM_NCMBUTTONUP,
+ WM_NCMBUTTONDBLCLK,
+ WM_KEYDOWN,
+ WM_KEYUP,
+ WM_MOUSEMOVE,
+ WM_LBUTTONDOWN,
+ WM_LBUTTONUP,
+ WM_LBUTTONDBLCLK,
+ WM_RBUTTONDOWN,
+ WM_RBUTTONUP,
+ WM_RBUTTONDBLCLK,
+ WM_MBUTTONDOWN,
+ WM_MBUTTONUP,
+ WM_MBUTTONDBLCLK,
+ };
+
+ flush_events();
+
+ hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got window %#lx.\n", oahwnd);
+
+ hr = IVideoWindow_put_MessageDrain(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(oahwnd == (OAHWND)our_hwnd, "Got window %#lx.\n", oahwnd);
+
+ for (i = 0; i < ARRAY_SIZE(drain_tests); ++i)
+ {
+ SendMessageA(hwnd, drain_tests[i], 0xdeadbeef, 0);
+ ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
+ ok(ret, "Expected a message.\n");
+ ok(msg.hwnd == our_hwnd, "Got hwnd %p.\n", msg.hwnd);
+ ok(msg.message == drain_tests[i], "Got message %#x.\n", msg.message);
+ ok(msg.wParam == 0xdeadbeef, "Got wparam %#lx.\n", msg.wParam);
+ ok(!msg.lParam, "Got lparam %#lx.\n", msg.lParam);
+ DispatchMessageA(&msg);
+
+ ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
+ ok(!ret, "Got unexpected message %#x.\n", msg.message);
+ }
+
+ hr = IVideoWindow_put_MessageDrain(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ flush_events();
+
+ hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SYSCOLORCHANGE, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SETCURSOR,
+ (WPARAM)hwnd, MAKELONG(HTCLIENT, WM_MOUSEMOVE));
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ params.window = window;
+ params.hwnd = our_hwnd;
+ params.message = WM_SYSCOLORCHANGE;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block.\n");
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(ret == ((QS_SENDMESSAGE << 16) | QS_SENDMESSAGE), "Got unexpected status %#x.\n", ret);
+
+ PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
+ ok(!WaitForSingleObject(thread, 100), "Wait timed out.\n");
+ CloseHandle(thread);
+
+ params.message = WM_SETCURSOR;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(!WaitForSingleObject(thread, 100), "Thread should not block.\n");
+ CloseHandle(thread);
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ hr = IVideoWindow_put_Owner(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+}
+
+static void test_video_window_autoshow(IVideoWindow *window, IFilterGraph2 *graph, HWND hwnd)
+{
+ IMediaControl *control;
+ HRESULT hr;
+ LONG l;
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ hr = IVideoWindow_get_AutoShow(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IVideoWindow_put_AutoShow(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(l == OAFALSE, "Got %d.\n", l);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+}
+
+static void test_video_window(void)
+{
+ ALLOCATOR_PROPERTIES req_props = {1, 600 * 400 * 4, 1, 0}, ret_props;
+ VIDEOINFOHEADER vih =
+ {
+ .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
+ .bmiHeader.biBitCount = 32,
+ .bmiHeader.biWidth = 600,
+ .bmiHeader.biHeight = 400,
+ .bmiHeader.biPlanes = 1,
+ .bmiHeader.biCompression = BI_RGB,
+ };
+ AM_MEDIA_TYPE req_mt =
+ {
+ .majortype = MEDIATYPE_Video,
+ .subtype = MEDIASUBTYPE_RGB32,
+ .formattype = FORMAT_VideoInfo,
+ .cbFormat = sizeof(vih),
+ .pbFormat = (BYTE *)&vih,
+ };
+ IFilterGraph2 *graph = create_graph();
+ WNDCLASSA window_class = {0};
+ struct testfilter source;
+ IMemAllocator *allocator;
+ MONITORINFO monitorinfo;
+ IMediaControl *control;
+ LONG width, height, l;
+ IVideoWindow *window;
+ IMemInputPin *input;
+ IBaseFilter *filter;
+ HWND hwnd, our_hwnd;
+ IOverlay *overlay;
+ BSTR caption;
+ HRESULT hr;
+ DWORD tid;
+ ULONG ref;
+ IPin *pin;
+ RECT rect;
+
+ window_class.lpszClassName = "wine_test_class";
+ window_class.lpfnWndProc = window_proc;
+ RegisterClassA(&window_class);
+ our_hwnd = CreateWindowA("wine_test_class", "test window", WS_VISIBLE | WS_OVERLAPPEDWINDOW,
+ 100, 200, 300, 400, NULL, NULL, NULL, NULL);
+ flush_events();
+
+ filter = create_vmr9(VMR9Mode_Windowed);
+ flush_events();
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
+ IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input);
+
+ hr = IPin_QueryInterface(pin, &IID_IOverlay, (void **)&overlay);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IOverlay_GetWindowHandle(overlay, &hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (winetest_debug > 1) trace("ours %p, theirs %p\n", our_hwnd, hwnd);
+ GetWindowRect(hwnd, &rect);
+
+ tid = GetWindowThreadProcessId(hwnd, NULL);
+ ok(tid == GetCurrentThreadId(), "Expected tid %#x, got %#x.\n", GetCurrentThreadId(), tid);
+
+ hr = IBaseFilter_QueryInterface(filter, &IID_IVideoWindow, (void **)&window);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyle(window, &l);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_AutoShow(window, &l);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ testfilter_init(&source);
+ IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, filter, NULL);
+ hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMemInputPin_GetAllocator(input, &allocator);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ {
+ hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n");
+ hr = IMemAllocator_Commit(allocator);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ IMemAllocator_Release(allocator);
+ }
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ test_video_window_caption(window, hwnd);
+ test_video_window_style(window, hwnd, our_hwnd);
+ test_video_window_state(window, hwnd, our_hwnd);
+ test_video_window_position(window, hwnd, our_hwnd);
+ test_video_window_autoshow(window, graph, hwnd);
+ test_video_window_owner(window, hwnd, our_hwnd);
+ test_video_window_messages(window, hwnd, our_hwnd);
+
+ hr = IVideoWindow_put_FullScreenMode(window, OATRUE);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_get_FullScreenMode(window, &l);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_GetMinIdealImageSize(window, &width, &height);
+ todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_GetMaxIdealImageSize(window, &width, &height);
+ todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ monitorinfo.cbSize = sizeof(monitorinfo);
+ GetMonitorInfoW(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY), &monitorinfo);
+
+ hr = IVideoWindow_GetMinIdealImageSize(window, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == 1, "Got width %d.\n", width);
+ todo_wine ok(height == 1, "Got height %d.\n", height);
+ hr = IVideoWindow_GetMaxIdealImageSize(window, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == monitorinfo.rcMonitor.right + 1, "Expected width %d, got %d.\n",
+ monitorinfo.rcMonitor.right + 1, width);
+ todo_wine ok(height == monitorinfo.rcMonitor.bottom + 1, "Expected height %d, got %d.\n",
+ monitorinfo.rcMonitor.bottom + 1, height);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+ IFilterGraph2_Release(graph);
+ IVideoWindow_Release(window);
+ IOverlay_Release(overlay);
+ IMemInputPin_Release(input);
+ IPin_Release(pin);
+ ref = IBaseFilter_Release(filter);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ DestroyWindow(our_hwnd);
+}
+
START_TEST(vmr9)
{
IBaseFilter *filter;
@@ -1588,6 +2394,7 @@ START_TEST(vmr9)
test_unconnected_filter_state();
test_connect_pin();
test_overlay();
+ test_video_window();
CoUninitialize();
}
--
2.24.0
Dec. 6, 2019
[PATCH 2/4] quartz/vmr9: Create the rendering window when the filter is created.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/vmr7.c | 2 +-
dlls/quartz/tests/vmr9.c | 2 +-
dlls/quartz/vmr9.c | 50 +++++++++++++---------------------------
3 files changed, 18 insertions(+), 36 deletions(-)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c
index d8c22bede5..93c16caede 100644
--- a/dlls/quartz/tests/vmr7.c
+++ b/dlls/quartz/tests/vmr7.c
@@ -1557,7 +1557,7 @@ static void test_overlay(void)
hwnd = (HWND)0xdeadbeef;
hr = IOverlay_GetWindowHandle(overlay, &hwnd);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
+ ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
IOverlay_Release(overlay);
IPin_Release(pin);
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index 4acf7cb1d8..128d4abbc6 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -1554,7 +1554,7 @@ static void test_overlay(void)
hwnd = (HWND)0xdeadbeef;
hr = IOverlay_GetWindowHandle(overlay, &hwnd);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
+ ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
IOverlay_Release(overlay);
IPin_Release(pin);
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c
index adf7d6e11a..98e1822593 100644
--- a/dlls/quartz/vmr9.c
+++ b/dlls/quartz/vmr9.c
@@ -294,7 +294,7 @@ static HRESULT WINAPI VMR9_DoRenderSample(struct strmbase_renderer *iface, IMedi
info.dwFlags |= VMR9Sample_SyncPoint;
/* If we render ourselves, and this is a preroll sample, discard it */
- if (This->baseControlWindow.baseWindow.hWnd && (info.dwFlags & VMR9Sample_Preroll))
+ if (info.dwFlags & VMR9Sample_Preroll)
{
return S_OK;
}
@@ -374,7 +374,7 @@ static HRESULT VMR9_maybe_init(struct quartz_vmr *This, BOOL force)
HRESULT hr;
TRACE("my mode: %u, my window: %p, my last window: %p\n", This->mode, This->baseControlWindow.baseWindow.hWnd, This->hWndClippingWindow);
- if (This->baseControlWindow.baseWindow.hWnd || !This->renderer.sink.pin.peer)
+ if (This->num_surfaces || !This->renderer.sink.pin.peer)
return S_OK;
if (This->mode == VMR9Mode_Windowless && !This->hWndClippingWindow)
@@ -516,6 +516,7 @@ static void vmr_destroy(struct strmbase_renderer *iface)
CloseHandle(filter->run_event);
FreeLibrary(filter->hD3d9);
+ BaseControlWindow_Destroy(&filter->baseControlWindow);
strmbase_renderer_cleanup(&filter->renderer);
CoTaskMemFree(filter);
}
@@ -1506,13 +1507,10 @@ static HRESULT WINAPI VMR7WindowlessControl_SetVideoPosition(IVMRWindowlessContr
if (dest)
{
This->target_rect = *dest;
- if (This->baseControlWindow.baseWindow.hWnd)
- {
- FIXME("Output rectangle: %s\n", wine_dbgstr_rect(dest));
- SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
- dest->left, dest->top, dest->right - dest->left, dest->bottom-dest->top,
- SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
- }
+ FIXME("Output rectangle: %s.\n", wine_dbgstr_rect(dest));
+ SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
+ dest->left, dest->top, dest->right - dest->left, dest->bottom-dest->top,
+ SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREDRAW);
}
LeaveCriticalSection(&This->renderer.filter.csFilter);
@@ -1710,12 +1708,10 @@ static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessContr
if (dest)
{
This->target_rect = *dest;
- if (This->baseControlWindow.baseWindow.hWnd)
- {
- FIXME("Output rectangle: %s\n", wine_dbgstr_rect(dest));
- SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, dest->left, dest->top, dest->right - dest->left,
- dest->bottom-dest->top, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
- }
+ FIXME("Output rectangle: %s.\n", wine_dbgstr_rect(dest));
+ SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
+ dest->left, dest->top, dest->right - dest->left, dest->bottom - dest->top,
+ SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREDRAW);
}
LeaveCriticalSection(&This->renderer.filter.csFilter);
@@ -2247,6 +2243,9 @@ static HRESULT vmr_create(IUnknown *outer, void **out, const CLSID *clsid)
if (FAILED(hr))
goto fail;
+ if (FAILED(hr = BaseWindowImpl_PrepareWindow(&pVMR->baseControlWindow.baseWindow)))
+ goto fail;
+
hr = strmbase_video_init(&pVMR->baseControlVideo, &pVMR->renderer.filter,
&pVMR->renderer.sink.pin, &renderer_BaseControlVideoFuncTable);
if (FAILED(hr))
@@ -2261,6 +2260,7 @@ static HRESULT vmr_create(IUnknown *outer, void **out, const CLSID *clsid)
return hr;
fail:
+ BaseWindowImpl_DoneWithWindow(&pVMR->baseControlWindow.baseWindow);
strmbase_renderer_cleanup(&pVMR->renderer);
FreeLibrary(pVMR->hD3d9);
CoTaskMemFree(pVMR);
@@ -2590,9 +2590,6 @@ static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9A
TRACE("(%p)->()\n", This);
- if (FAILED(BaseWindowImpl_PrepareWindow(&This->pVMR9->baseControlWindow.baseWindow)))
- return FALSE;
-
/* Obtain a monitor and d3d9 device */
d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon);
@@ -2608,7 +2605,6 @@ static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9A
if (FAILED(hr))
{
ERR("Could not create device: %08x\n", hr);
- BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
return FALSE;
}
IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
@@ -2630,7 +2626,6 @@ static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9A
if (FAILED(hr))
{
IVMRSurfaceAllocatorEx9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie);
- BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
return FALSE;
}
@@ -2662,14 +2657,7 @@ static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocato
static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id)
{
- VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
-
- if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
- {
- return S_OK;
- }
-
- BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
+ TRACE("iface %p, id %#lx.\n", iface, id);
return S_OK;
}
@@ -2684,12 +2672,6 @@ static HRESULT VMR9_SurfaceAllocator_UpdateDeviceReset(VMR9DefaultAllocatorPrese
D3DPRESENT_PARAMETERS d3dpp;
HRESULT hr;
- if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
- {
- ERR("No window\n");
- return E_FAIL;
- }
-
if (!This->d3d9_surfaces || !This->reset)
return S_OK;
--
2.24.0
Dec. 6, 2019
[PATCH 1/4] strmbase: Correctly implement IVideoWindow::NotifyOwnerMessage().
by Zebediah Figura
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43367
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43765
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/videorenderer.c | 40 +++++++++++++++++++++++++++++--
dlls/strmbase/window.c | 24 +++++++++++++++----
2 files changed, 57 insertions(+), 7 deletions(-)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c
index a9f938074b..320d8920d1 100644
--- a/dlls/quartz/tests/videorenderer.c
+++ b/dlls/quartz/tests/videorenderer.c
@@ -1888,10 +1888,27 @@ static void test_video_window_owner(IVideoWindow *window, HWND hwnd, HWND our_hw
ok(state == OATRUE, "Got state %d.\n", state);
}
+struct notify_message_params
+{
+ IVideoWindow *window;
+ HWND hwnd;
+ UINT message;
+};
+
+static DWORD CALLBACK notify_message_proc(void *arg)
+{
+ const struct notify_message_params *params = arg;
+ HRESULT hr = IVideoWindow_NotifyOwnerMessage(params->window, (OAHWND)params->hwnd, params->message, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ return 0;
+}
+
static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
{
+ struct notify_message_params params;
unsigned int i;
OAHWND oahwnd;
+ HANDLE thread;
HRESULT hr;
BOOL ret;
MSG msg;
@@ -1962,14 +1979,33 @@ static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
- todo_wine ok(!ret, "Got unexpected status %#x.\n", ret);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SETCURSOR,
(WPARAM)hwnd, MAKELONG(HTCLIENT, WM_MOUSEMOVE));
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
- todo_wine ok(!ret, "Got unexpected status %#x.\n", ret);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ params.window = window;
+ params.hwnd = our_hwnd;
+ params.message = WM_SYSCOLORCHANGE;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block.\n");
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(ret == ((QS_SENDMESSAGE << 16) | QS_SENDMESSAGE), "Got unexpected status %#x.\n", ret);
+
+ PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
+ ok(!WaitForSingleObject(thread, 100), "Wait timed out.\n");
+ CloseHandle(thread);
+
+ params.message = WM_SETCURSOR;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(!WaitForSingleObject(thread, 100), "Thread should not block.\n");
+ CloseHandle(thread);
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
hr = IVideoWindow_put_Owner(window, 0);
ok(hr == S_OK, "Got hr %#x.\n", hr);
diff --git a/dlls/strmbase/window.c b/dlls/strmbase/window.c
index be6646c27a..04132aaab1 100644
--- a/dlls/strmbase/window.c
+++ b/dlls/strmbase/window.c
@@ -654,14 +654,28 @@ HRESULT WINAPI BaseControlWindowImpl_GetWindowPosition(IVideoWindow *iface, LONG
return S_OK;
}
-HRESULT WINAPI BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg, LONG_PTR wParam, LONG_PTR lParam)
+HRESULT WINAPI BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow *iface,
+ OAHWND hwnd, LONG message, LONG_PTR wparam, LONG_PTR lparam)
{
- BaseControlWindow* This = impl_from_IVideoWindow(iface);
+ BaseControlWindow *window = impl_from_IVideoWindow(iface);
- TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam);
+ TRACE("window %p, hwnd %#lx, message %#x, wparam %#lx, lparam %#lx.\n",
+ window, hwnd, message, wparam, lparam);
- if (!PostMessageW(This->baseWindow.hWnd, uMsg, wParam, lParam))
- return E_FAIL;
+ /* That these messages are forwarded, and no others, is stated by the
+ * DirectX documentation, and supported by manual testing. */
+ switch (message)
+ {
+ case WM_ACTIVATEAPP:
+ case WM_DEVMODECHANGE:
+ case WM_DISPLAYCHANGE:
+ case WM_PALETTECHANGED:
+ case WM_PALETTEISCHANGING:
+ case WM_QUERYNEWPALETTE:
+ case WM_SYSCOLORCHANGE:
+ SendMessageW(window->baseWindow.hWnd, message, wparam, lparam);
+ break;
+ }
return S_OK;
}
--
2.24.0
Dec. 6, 2019
[PATCH v4] odbccp32: Implement SQLConfigDataSource/W
by Alistair Leslie-Hughes
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/odbccp32/odbccp32.c | 121 +++++++++++++++++++++++++++++--------
dlls/odbccp32/tests/misc.c | 8 +--
2 files changed, 101 insertions(+), 28 deletions(-)
diff --git a/dlls/odbccp32/odbccp32.c b/dlls/odbccp32/odbccp32.c
index a09d6571f3..c842872fa6 100644
--- a/dlls/odbccp32/odbccp32.c
+++ b/dlls/odbccp32/odbccp32.c
@@ -68,6 +68,9 @@ static const WCHAR odbc_error_load_lib_failed[] = {'L','o','a','d',' ','L','i','
static const WCHAR odbc_error_request_failed[] = {'R','e','q','u','e','s','t',' ','F','a','i','l','e','d',0};
static const WCHAR odbc_error_invalid_keyword[] = {'I','n','v','a','l','i','d',' ','k','e','y','w','o','r','d',' ','v','a','l','u','e',0};
+static BOOL (WINAPI *pConfigDSN)(HWND hwnd, WORD request, const char *driver, const char *attr);
+static BOOL (WINAPI *pConfigDSNW)(HWND hwnd, WORD request, const WCHAR *driver, const WCHAR *attr);
+
/* Push an error onto the error stack, taking care of ranges etc. */
static void push_error(int code, LPCWSTR msg)
{
@@ -219,30 +222,6 @@ static BOOL SQLInstall_narrow(int mode, LPSTR buffer, LPCWSTR str, WORD str_leng
return success;
}
-BOOL WINAPI SQLConfigDataSourceW(HWND hwndParent, WORD fRequest,
- LPCWSTR lpszDriver, LPCWSTR lpszAttributes)
-{
- LPCWSTR p;
-
- clear_errors();
- FIXME("%p %d %s %s\n", hwndParent, fRequest, debugstr_w(lpszDriver),
- debugstr_w(lpszAttributes));
-
- for (p = lpszAttributes; *p; p += lstrlenW(p) + 1)
- FIXME("%s\n", debugstr_w(p));
-
- return TRUE;
-}
-
-BOOL WINAPI SQLConfigDataSource(HWND hwndParent, WORD fRequest,
- LPCSTR lpszDriver, LPCSTR lpszAttributes)
-{
- FIXME("%p %d %s %s\n", hwndParent, fRequest, debugstr_a(lpszDriver),
- debugstr_a(lpszAttributes));
- clear_errors();
- return TRUE;
-}
-
static HMODULE load_config_driver(const WCHAR *driver)
{
static WCHAR reg_driver[] = {'d','r','i','v','e','r',0};
@@ -359,6 +338,100 @@ fail:
return FALSE;
}
+BOOL WINAPI SQLConfigDataSourceW(HWND hwnd, WORD request, LPCWSTR driver, LPCWSTR attributes)
+{
+ HMODULE mod;
+ BOOL ret = FALSE;
+
+ TRACE("%p, %d, %s, %s\n", hwnd, request, debugstr_w(driver), debugstr_w(attributes));
+ if (TRACE_ON(odbc))
+ {
+ const WCHAR *p;
+ for (p = attributes; *p; p += lstrlenW(p) + 1)
+ TRACE("%s\n", debugstr_w(p));
+ }
+
+ clear_errors();
+
+ mod = load_config_driver(driver);
+ if (!mod)
+ return FALSE;
+
+ pConfigDSNW = (void*)GetProcAddress(mod, "ConfigDSNW");
+ if(pConfigDSNW)
+ ret = pConfigDSNW(hwnd, request, driver, attributes);
+ else
+ ERR("Failed to find ConfigDSNW\n");
+
+ if (!ret)
+ push_error(ODBC_ERROR_REQUEST_FAILED, odbc_error_request_failed);
+
+ FreeLibrary(mod);
+
+ return ret;
+}
+
+BOOL WINAPI SQLConfigDataSource(HWND hwnd, WORD request, LPCSTR driver, LPCSTR attributes)
+{
+ HMODULE mod;
+ BOOL ret = FALSE;
+ WCHAR *driverW;
+
+ TRACE("%p, %d, %s, %s\n", hwnd, request, debugstr_a(driver), debugstr_a(attributes));
+
+ if (TRACE_ON(odbc))
+ {
+ const char *p;
+ for (p = attributes; *p; p += lstrlenA(p) + 1)
+ TRACE("%s\n", debugstr_a(p));
+ }
+
+ clear_errors();
+
+ driverW = heap_strdupAtoW(driver);
+ if (!driverW)
+ {
+ push_error(ODBC_ERROR_OUT_OF_MEM, odbc_error_out_of_mem);
+ return FALSE;
+ }
+
+ mod = load_config_driver(driverW);
+ if (!mod)
+ {
+ heap_free(driverW);
+ return FALSE;
+ }
+
+ pConfigDSN = (void*)GetProcAddress(mod, "ConfigDSN");
+ if (pConfigDSN)
+ {
+ TRACE("Calling ConfigDSN\n");
+ ret = pConfigDSN(hwnd, request, driver, attributes);
+ }
+ else
+ {
+ pConfigDSNW = (void*)GetProcAddress(mod, "ConfigDSNW");
+ if (pConfigDSNW)
+ {
+ WCHAR *attr = NULL;
+ TRACE("Calling ConfigDSNW\n");
+
+ attr = SQLInstall_strdup_multi(attributes);
+ if(attr)
+ ret = pConfigDSNW(hwnd, request, driverW, attr);
+ heap_free(attr);
+ }
+ }
+
+ if (!ret)
+ push_error(ODBC_ERROR_REQUEST_FAILED, odbc_error_request_failed);
+
+ heap_free(driverW);
+ FreeLibrary(mod);
+
+ return ret;
+}
+
BOOL WINAPI SQLConfigDriverW(HWND hwnd, WORD request, LPCWSTR driver,
LPCWSTR args, LPWSTR msg, WORD msgmax, WORD *msgout)
{
diff --git a/dlls/odbccp32/tests/misc.c b/dlls/odbccp32/tests/misc.c
index e2f48ee732..0120504227 100644
--- a/dlls/odbccp32/tests/misc.c
+++ b/dlls/odbccp32/tests/misc.c
@@ -751,10 +751,10 @@ static void test_SQLConfigDataSource(void)
BOOL ret;
ret = SQLConfigDataSource(0, ODBC_ADD_DSN, "SQL Server", "DSN=WINEMQIS\0Database=MQIS\0\0");
- ok(ret, "got %d\n", ret);
+ todo_wine ok(ret, "got %d\n", ret);
ret = SQLConfigDataSource(0, ODBC_REMOVE_DSN, "SQL Server", "DSN=WINEMQIS\0\0");
- ok(ret, "got %d\n", ret);
+ todo_wine ok(ret, "got %d\n", ret);
ret = SQLConfigDataSource(0, ODBC_REMOVE_DSN, "SQL Server", "DSN=WINEMQIS\0\0");
if(!ret)
@@ -767,8 +767,8 @@ static void test_SQLConfigDataSource(void)
}
ret = SQLConfigDataSource(0, ODBC_ADD_DSN, "ODBC driver", "DSN=ODBC data source\0\0");
- todo_wine ok(!ret, "got %d\n", ret);
- todo_wine check_error(ODBC_ERROR_COMPONENT_NOT_FOUND);
+ ok(!ret, "got %d\n", ret);
+ check_error(ODBC_ERROR_COMPONENT_NOT_FOUND);
}
START_TEST(misc)
--
2.17.1
Dec. 5, 2019
[PATCH v3 3/3] xmllite: Expand test for any unparsed data at end of XML.
by Jeff Smith
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/reader.c | 3 ++-
dlls/xmllite/tests/reader.c | 2 --
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index 79e5c2253a..c4b0fe521d 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -2562,6 +2562,7 @@ static HRESULT reader_parse_content(xmlreader *reader)
static HRESULT reader_parse_nextnode(xmlreader *reader)
{
+ const encoded_buffer *buffer = &reader->input->buffer->utf16;
XmlNodeType nodetype = reader_get_nodetype(reader);
HRESULT hr;
@@ -2662,7 +2663,7 @@ static HRESULT reader_parse_nextnode(xmlreader *reader)
hr = reader_parse_misc(reader);
if (hr != S_FALSE) return hr;
- if (*reader_get_ptr(reader))
+ if (buffer->cur*sizeof(WCHAR) < buffer->written)
{
WARN("found garbage in the end of XML\n");
return WC_E_SYNTAX;
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index b02301907d..7ad548d081 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -1051,7 +1051,6 @@ static void test_read_nul(void)
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
@@ -1077,7 +1076,6 @@ todo_wine
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
--
2.23.0
Dec. 5, 2019
[PATCH v3 2/3] xmllite: Whitespace node not returned when followed by invalid character.
by Jeff Smith
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/reader.c | 12 ++++++++++--
dlls/xmllite/tests/reader.c | 2 --
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index eddc4d8eec..79e5c2253a 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -1113,8 +1113,8 @@ static inline UINT reader_get_cur(xmlreader *reader)
static inline WCHAR *reader_get_ptr(xmlreader *reader)
{
encoded_buffer *buffer = &reader->input->buffer->utf16;
- WCHAR *ptr = (WCHAR*)buffer->data + buffer->cur;
- if (!*ptr) reader_more(reader);
+ if (buffer->cur*sizeof(WCHAR) >= buffer->written)
+ reader_more(reader);
return (WCHAR*)buffer->data + buffer->cur;
}
@@ -1714,8 +1714,16 @@ static HRESULT reader_parse_whitespace(xmlreader *reader)
{
strval value;
UINT start;
+ const encoded_buffer *buffer = &reader->input->buffer->utf16;
reader_skipspaces(reader);
+
+ /* Do NOT return Whitespace node if followed by a character other than '<'.
+ * The reader_skipspaces call should have already read in the character. */
+ if (buffer->cur*sizeof(WCHAR) < buffer->written &&
+ *reader_get_ptr2(reader, buffer->cur) != '<')
+ return WC_E_SYNTAX;
+
if (is_reader_pending(reader)) return S_OK;
start = reader->resume[XmlReadResume_Body];
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 88b9103e1e..b02301907d 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -1064,10 +1064,8 @@ todo_wine
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine {
ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
-}
stream = create_stream_on_data(xml_comment, sizeof(xml_comment));
hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
--
2.23.0
Dec. 5, 2019
[PATCH v3 1/3] xmllite/tests: Extract nul-character test from XML declaration test.
by Jeff Smith
The comments in the XML declaration test suggest that it is supposed to
be to checking for failure when no element follows the XML declaration.
However, the error being tested for is due to a nul character in the
input stream.
Create a separate test for nul-character errors, and fix the XML
declaration test accordingly.
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/tests/reader.c | 83 +++++++++++++++++++++++++++++--------
1 file changed, 66 insertions(+), 17 deletions(-)
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 41adad1598..88b9103e1e 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -863,7 +863,6 @@ static void test_read_xmldeclaration(void)
{ {'s','t','a','n','d','a','l','o','n','e',0}, {'y','e','s',0} }
};
IXmlReader *reader;
- IStream *stream;
HRESULT hr;
XmlNodeType type;
UINT count = 0, len, i;
@@ -873,10 +872,7 @@ static void test_read_xmldeclaration(void)
hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
- stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full));
-
- hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
- ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+ set_input_string(reader, xmldecl_full);
hr = IXmlReader_GetAttributeCount(reader, &count);
ok(hr == S_OK, "got %08x\n", hr);
@@ -968,19 +964,19 @@ static void test_read_xmldeclaration(void)
type = XmlNodeType_XmlDeclaration;
hr = IXmlReader_Read(reader, &type);
- /* newer versions return syntax error here cause document is incomplete,
- it makes more sense than invalid char error */
+ ok(hr == S_OK, "got %08x\n", hr);
+ ok(type == XmlNodeType_Whitespace, "expected XmlNodeType_Whitespace, got %s\n", type_to_str(type));
+
+ type = XmlNodeType_Whitespace;
+ hr = IXmlReader_Read(reader, &type);
todo_wine {
- ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "got 0x%08x\n", hr);
+ ok(hr == WC_E_ROOTELEMENT, "got %08x\n", hr);
ok(type == XmlNodeType_None, "got %d\n", type);
+ TEST_READER_STATE(reader, XmlReadState_Error);
}
- IStream_Release(stream);
/* test short variant */
- stream = create_stream_on_data(xmldecl_short, sizeof(xmldecl_short));
-
- hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
- ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
+ set_input_string(reader, xmldecl_short);
read_node(reader, XmlNodeType_XmlDeclaration);
TEST_READER_POSITION2(reader, 1, 3, ~0u, 21);
@@ -1027,14 +1023,66 @@ todo_wine {
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
- ok(hr == WC_E_SYNTAX || hr == WC_E_XMLCHARACTER /* XP */, "expected WC_E_SYNTAX, got %08x\n", hr);
+ ok(hr == S_FALSE, "expected S_FALSE, got %08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
- TEST_READER_POSITION(reader, 1, 41);
+
+ IXmlReader_Release(reader);
+}
+
+static void test_read_nul(void)
+{
+ static const char xml_empty[] = "<a/>";
+ static const char xml_ws[] = "<a/> ";
+ static const char xml_comment[] = "<a/><!-- comment -->";
+ IXmlReader *reader;
+ XmlNodeType type;
+ IStream *stream;
+ HRESULT hr;
+
+ hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
+ ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+
+ stream = create_stream_on_data(xml_empty, sizeof(xml_empty));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
+ IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
todo_wine
- TEST_READER_STATE(reader, XmlReadState_Error);
+ ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+ stream = create_stream_on_data(xml_ws, sizeof(xml_ws));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
+todo_wine {
+ ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+}
+
+ stream = create_stream_on_data(xml_comment, sizeof(xml_comment));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
+ IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+ read_node(reader, XmlNodeType_Comment);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
+todo_wine
+ ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+
IXmlReader_Release(reader);
}
@@ -2672,6 +2720,7 @@ START_TEST(reader)
test_read_pending();
test_readvaluechunk();
test_read_xmldeclaration();
+ test_read_nul();
test_reader_properties();
test_prefix();
test_namespaceuri();
--
2.23.0
Dec. 5, 2019
[PATCH v2 3/3] xmllite: Expand test for any unparsed data at end of XML.
by Jeff Smith
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/reader.c | 3 ++-
dlls/xmllite/tests/reader.c | 2 --
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index 79e5c2253a..c4b0fe521d 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -2562,6 +2562,7 @@ static HRESULT reader_parse_content(xmlreader *reader)
static HRESULT reader_parse_nextnode(xmlreader *reader)
{
+ const encoded_buffer *buffer = &reader->input->buffer->utf16;
XmlNodeType nodetype = reader_get_nodetype(reader);
HRESULT hr;
@@ -2662,7 +2663,7 @@ static HRESULT reader_parse_nextnode(xmlreader *reader)
hr = reader_parse_misc(reader);
if (hr != S_FALSE) return hr;
- if (*reader_get_ptr(reader))
+ if (buffer->cur*sizeof(WCHAR) < buffer->written)
{
WARN("found garbage in the end of XML\n");
return WC_E_SYNTAX;
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 72f9ca902d..878c14f7ef 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -1051,7 +1051,6 @@ static void test_read_nul(void)
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
ok(hr == WC_E_SYNTAX, "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
@@ -1077,7 +1076,6 @@ todo_wine
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
ok(hr == WC_E_SYNTAX, "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
--
2.23.0
Dec. 5, 2019
[PATCH v2 2/3] xmllite: Whitespace node not returned when followed by invalid character.
by Jeff Smith
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/reader.c | 12 ++++++++++--
dlls/xmllite/tests/reader.c | 2 --
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index eddc4d8eec..79e5c2253a 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -1113,8 +1113,8 @@ static inline UINT reader_get_cur(xmlreader *reader)
static inline WCHAR *reader_get_ptr(xmlreader *reader)
{
encoded_buffer *buffer = &reader->input->buffer->utf16;
- WCHAR *ptr = (WCHAR*)buffer->data + buffer->cur;
- if (!*ptr) reader_more(reader);
+ if (buffer->cur*sizeof(WCHAR) >= buffer->written)
+ reader_more(reader);
return (WCHAR*)buffer->data + buffer->cur;
}
@@ -1714,8 +1714,16 @@ static HRESULT reader_parse_whitespace(xmlreader *reader)
{
strval value;
UINT start;
+ const encoded_buffer *buffer = &reader->input->buffer->utf16;
reader_skipspaces(reader);
+
+ /* Do NOT return Whitespace node if followed by a character other than '<'.
+ * The reader_skipspaces call should have already read in the character. */
+ if (buffer->cur*sizeof(WCHAR) < buffer->written &&
+ *reader_get_ptr2(reader, buffer->cur) != '<')
+ return WC_E_SYNTAX;
+
if (is_reader_pending(reader)) return S_OK;
start = reader->resume[XmlReadResume_Body];
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 40d39c22f5..72f9ca902d 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -1064,10 +1064,8 @@ todo_wine
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine {
ok(hr == WC_E_SYNTAX, "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
-}
stream = create_stream_on_data(xml_comment, sizeof(xml_comment));
hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
--
2.23.0
Dec. 5, 2019
[PATCH v2 1/3] xmllite/tests: Extract nul-character test from XML declaration test.
by Jeff Smith
The comments in the XML declaration test suggest that it is supposed to
be to checking for failure when no element follows the XML declaration.
However, the error being tested for is due to a nul character in the
input stream.
Create a separate test for nul-character errors, and fix the XML
declaration test accordingly.
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/tests/reader.c | 83 +++++++++++++++++++++++++++++--------
1 file changed, 66 insertions(+), 17 deletions(-)
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 41adad1598..40d39c22f5 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -863,7 +863,6 @@ static void test_read_xmldeclaration(void)
{ {'s','t','a','n','d','a','l','o','n','e',0}, {'y','e','s',0} }
};
IXmlReader *reader;
- IStream *stream;
HRESULT hr;
XmlNodeType type;
UINT count = 0, len, i;
@@ -873,10 +872,7 @@ static void test_read_xmldeclaration(void)
hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
- stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full));
-
- hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
- ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+ set_input_string(reader, xmldecl_full);
hr = IXmlReader_GetAttributeCount(reader, &count);
ok(hr == S_OK, "got %08x\n", hr);
@@ -968,19 +964,19 @@ static void test_read_xmldeclaration(void)
type = XmlNodeType_XmlDeclaration;
hr = IXmlReader_Read(reader, &type);
- /* newer versions return syntax error here cause document is incomplete,
- it makes more sense than invalid char error */
+ ok(hr == S_OK, "got %08x\n", hr);
+ ok(type == XmlNodeType_Whitespace, "expected XmlNodeType_Whitespace, got %s\n", type_to_str(type));
+
+ type = XmlNodeType_Whitespace;
+ hr = IXmlReader_Read(reader, &type);
todo_wine {
- ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "got 0x%08x\n", hr);
+ ok(hr == WC_E_ROOTELEMENT, "got %08x\n", hr);
ok(type == XmlNodeType_None, "got %d\n", type);
+ TEST_READER_STATE(reader, XmlReadState_Error);
}
- IStream_Release(stream);
/* test short variant */
- stream = create_stream_on_data(xmldecl_short, sizeof(xmldecl_short));
-
- hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
- ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
+ set_input_string(reader, xmldecl_short);
read_node(reader, XmlNodeType_XmlDeclaration);
TEST_READER_POSITION2(reader, 1, 3, ~0u, 21);
@@ -1027,14 +1023,66 @@ todo_wine {
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
- ok(hr == WC_E_SYNTAX || hr == WC_E_XMLCHARACTER /* XP */, "expected WC_E_SYNTAX, got %08x\n", hr);
+ ok(hr == S_FALSE, "expected S_FALSE, got %08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
- TEST_READER_POSITION(reader, 1, 41);
+
+ IXmlReader_Release(reader);
+}
+
+static void test_read_nul(void)
+{
+ static const char xml_empty[] = "<a/>";
+ static const char xml_ws[] = "<a/> ";
+ static const char xml_comment[] = "<a/><!-- comment -->";
+ IXmlReader *reader;
+ XmlNodeType type;
+ IStream *stream;
+ HRESULT hr;
+
+ hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
+ ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+
+ stream = create_stream_on_data(xml_empty, sizeof(xml_empty));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
+ IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
todo_wine
- TEST_READER_STATE(reader, XmlReadState_Error);
+ ok(hr == WC_E_SYNTAX, "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+ stream = create_stream_on_data(xml_ws, sizeof(xml_ws));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
+todo_wine {
+ ok(hr == WC_E_SYNTAX, "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+}
+
+ stream = create_stream_on_data(xml_comment, sizeof(xml_comment));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
+ IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+ read_node(reader, XmlNodeType_Comment);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
+todo_wine
+ ok(hr == WC_E_SYNTAX, "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+
IXmlReader_Release(reader);
}
@@ -2672,6 +2720,7 @@ START_TEST(reader)
test_read_pending();
test_readvaluechunk();
test_read_xmldeclaration();
+ test_read_nul();
test_reader_properties();
test_prefix();
test_namespaceuri();
--
2.23.0
Dec. 5, 2019
[PATCH] kernel32: Set all %eax bits on Wow64EnableWow64FsRedirection return.
by Piotr Caban
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47565
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
---
The Wow64EnableWow64FsRedirection function, when compiled with gcc
9.2.0, uses setz %al to set return value. Microsoft C++ Redistributable
installers are depending on all %eax bits being set.
dlls/kernel32/kernel32.spec | 2 +-
dlls/kernel32/path.c | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
Dec. 5, 2019
[PATCH v2] msxml3: all string passed to IXMLDOMDocument_load() need to be URL-unescaped
by Damjan Jovanovic
msxml3 allows URL escape sequences even for C:\ style paths.
eg. C:\Program%20Files\...
Try 2 determines URL length dynamically, suppresses some compiler
const warnings, and cleans up tests.
Signed-off-by: Damjan Jovanovic <damjan.jov(a)gmail.com>
---
dlls/msxml3/bsc.c | 33 ++++++++++++++++++++++++++++-----
dlls/msxml3/tests/domdoc.c | 17 +++++++++++++++++
2 files changed, 45 insertions(+), 5 deletions(-)
Dec. 5, 2019
[PATCH v3 1/3] bcrypt: Add support for signing hashes with ECDSA keys.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
v3: Fix accidental return of 0 (STATUS_SUCCESS) when gnutls_decode_rs_value fails.
---
dlls/bcrypt/gnutls.c | 147 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 130 insertions(+), 17 deletions(-)
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index a6a07fff19..6e0bfef97b 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -92,6 +92,7 @@ MAKE_FUNCPTR(gnutls_cipher_decrypt2);
MAKE_FUNCPTR(gnutls_cipher_deinit);
MAKE_FUNCPTR(gnutls_cipher_encrypt2);
MAKE_FUNCPTR(gnutls_cipher_init);
+MAKE_FUNCPTR(gnutls_decode_rs_value);
MAKE_FUNCPTR(gnutls_global_deinit);
MAKE_FUNCPTR(gnutls_global_init);
MAKE_FUNCPTR(gnutls_global_set_log_function);
@@ -189,6 +190,7 @@ BOOL gnutls_initialize(void)
LOAD_FUNCPTR(gnutls_cipher_deinit)
LOAD_FUNCPTR(gnutls_cipher_encrypt2)
LOAD_FUNCPTR(gnutls_cipher_init)
+ LOAD_FUNCPTR(gnutls_decode_rs_value)
LOAD_FUNCPTR(gnutls_global_deinit)
LOAD_FUNCPTR(gnutls_global_init)
LOAD_FUNCPTR(gnutls_global_set_log_function)
@@ -711,6 +713,7 @@ NTSTATUS key_asymmetric_generate( struct key *key )
break;
case ALG_ID_ECDH_P256:
+ case ALG_ID_ECDSA_P256:
pk_alg = GNUTLS_PK_ECC; /* compatible with ECDSA and ECDH */
bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP256R1 );
break;
@@ -1029,6 +1032,17 @@ static NTSTATUS prepare_gnutls_signature( struct key *key, UCHAR *signature, ULO
}
}
+static gnutls_digest_algorithm_t get_digest_from_id( const WCHAR *alg_id )
+{
+ if (!strcmpW( alg_id, BCRYPT_SHA1_ALGORITHM )) return GNUTLS_DIG_SHA1;
+ if (!strcmpW( alg_id, BCRYPT_SHA256_ALGORITHM )) return GNUTLS_DIG_SHA256;
+ if (!strcmpW( alg_id, BCRYPT_SHA384_ALGORITHM )) return GNUTLS_DIG_SHA384;
+ if (!strcmpW( alg_id, BCRYPT_SHA512_ALGORITHM )) return GNUTLS_DIG_SHA512;
+ if (!strcmpW( alg_id, BCRYPT_MD2_ALGORITHM )) return GNUTLS_DIG_MD2;
+ if (!strcmpW( alg_id, BCRYPT_MD5_ALGORITHM )) return GNUTLS_DIG_MD5;
+ return -1;
+}
+
NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULONG hash_len, UCHAR *signature,
ULONG signature_len, DWORD flags )
{
@@ -1068,11 +1082,7 @@ NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULO
if (!(flags & BCRYPT_PAD_PKCS1) || !info) return STATUS_INVALID_PARAMETER;
if (!info->pszAlgId) return STATUS_INVALID_SIGNATURE;
- if (!strcmpW( info->pszAlgId, BCRYPT_SHA1_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA1;
- else if (!strcmpW( info->pszAlgId, BCRYPT_SHA256_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA256;
- else if (!strcmpW( info->pszAlgId, BCRYPT_SHA384_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA384;
- else if (!strcmpW( info->pszAlgId, BCRYPT_SHA512_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA512;
- else
+ if ((hash_alg = get_digest_from_id(info->pszAlgId)) == -1)
{
FIXME( "hash algorithm %s not supported\n", debugstr_w(info->pszAlgId) );
return STATUS_NOT_SUPPORTED;
@@ -1107,26 +1117,130 @@ NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULO
return (ret < 0) ? STATUS_INVALID_SIGNATURE : STATUS_SUCCESS;
}
+static unsigned int get_signature_length( enum alg_id id )
+{
+ switch (id)
+ {
+ case ALG_ID_ECDSA_P256: return 64;
+ case ALG_ID_ECDSA_P384: return 96;
+ default:
+ FIXME( "unhandled algorithm %u\n", id );
+ return 0;
+ }
+}
+
+NTSTATUS format_gnutls_signature( enum alg_id type, gnutls_datum_t signature, UCHAR *output,
+ ULONG output_len, ULONG *ret_len )
+{
+ switch (type)
+ {
+ case ALG_ID_RSA:
+ case ALG_ID_RSA_SIGN:
+ {
+ if (output_len < signature.size) return STATUS_BUFFER_TOO_SMALL;
+ memcpy( output, signature.data, signature.size );
+ *ret_len = signature.size;
+ return STATUS_SUCCESS;
+ }
+ case ALG_ID_ECDSA_P256:
+ case ALG_ID_ECDSA_P384:
+ {
+ int err;
+ unsigned int pad_size, sig_len = get_signature_length( type );
+ gnutls_datum_t r, s; /* format as r||s */
+
+ if ((err = pgnutls_decode_rs_value( &signature, &r, &s )))
+ {
+ ERR( "failed to get R/S values from signature %u\n", err );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ if (output_len < sig_len) return STATUS_BUFFER_TOO_SMALL;
+
+ /* remove prepended zero byte */
+ if (r.size % 2)
+ {
+ r.size--;
+ r.data += 1;
+ }
+ if (s.size % 2)
+ {
+ s.size--;
+ s.data += 1;
+ }
+
+ if (r.size != s.size || r.size + s.size > sig_len)
+ {
+ ERR( "we didn't get a correct signature\n" );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ pad_size = (sig_len / 2) - s.size;
+ memset( output, 0, sig_len );
+
+ memcpy( output + pad_size, r.data, r.size );
+ memcpy( output + (sig_len / 2) + pad_size, s.data, s.size );
+
+ *ret_len = sig_len;
+ return STATUS_SUCCESS;
+ }
+ default:
+ return STATUS_INTERNAL_ERROR;
+ }
+}
+
NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULONG input_len, UCHAR *output,
ULONG output_len, ULONG *ret_len, ULONG flags )
{
BCRYPT_PKCS1_PADDING_INFO *pad = padding;
gnutls_datum_t hash, signature;
+ gnutls_digest_algorithm_t hash_alg;
+ NTSTATUS status;
int ret;
- if (key->alg_id != ALG_ID_RSA && key->alg_id != ALG_ID_RSA_SIGN)
+ if (key->alg_id == ALG_ID_ECDSA_P256 || key->alg_id == ALG_ID_ECDSA_P384)
{
- FIXME( "algorithm %u not supported\n", key->alg_id );
- return STATUS_NOT_IMPLEMENTED;
+ /* With ECDSA, we find the digest algorithm from the hash length, and verify it */
+ switch (input_len)
+ {
+ case 20: hash_alg = GNUTLS_DIG_SHA1; break;
+ case 32: hash_alg = GNUTLS_DIG_SHA256; break;
+ case 48: hash_alg = GNUTLS_DIG_SHA384; break;
+ case 64: hash_alg = GNUTLS_DIG_SHA512; break;
+
+ default:
+ FIXME( "hash size %u not yet supported\n", input_len );
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (flags == BCRYPT_PAD_PKCS1 && pad && pad->pszAlgId && get_digest_from_id( pad->pszAlgId ) != hash_alg)
+ {
+ WARN( "incorrect hashing algorithm %s, expected %u\n", debugstr_w(pad->pszAlgId), hash_alg );
+ return STATUS_INVALID_PARAMETER;
+ }
}
- if (flags != BCRYPT_PAD_PKCS1)
+ else if (flags == BCRYPT_PAD_PKCS1)
{
- FIXME( "flags %08x not implemented\n", flags );
- return STATUS_NOT_IMPLEMENTED;
+ if (!pad || !pad->pszAlgId)
+ {
+ WARN( "padding info not found\n" );
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if ((hash_alg = get_digest_from_id( pad->pszAlgId )) == -1)
+ {
+ FIXME( "hash algorithm %s not recognized\n", debugstr_w(pad->pszAlgId) );
+ return STATUS_NOT_SUPPORTED;
+ }
+ }
+ else if (!flags)
+ {
+ WARN( "invalid flags %08x\n", flags );
+ return STATUS_INVALID_PARAMETER;
}
- if (!pad || !pad->pszAlgId || lstrcmpiW(pad->pszAlgId, BCRYPT_SHA1_ALGORITHM))
+ else
{
- FIXME( "%s padding not implemented\n", debugstr_w(pad ? pad->pszAlgId : NULL) );
+ FIXME( "flags %08x not implemented\n", flags );
return STATUS_NOT_IMPLEMENTED;
}
@@ -1143,17 +1257,16 @@ NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULON
signature.data = NULL;
signature.size = 0;
- if ((ret = pgnutls_privkey_sign_hash( key->u.a.handle, GNUTLS_DIG_SHA1, 0, &hash, &signature )))
+ if ((ret = pgnutls_privkey_sign_hash( key->u.a.handle, hash_alg, 0, &hash, &signature )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
- if (output_len >= signature.size) memcpy( output, signature.data, signature.size );
- *ret_len = signature.size;
+ status = format_gnutls_signature( key->alg_id, signature, output, output_len, ret_len );
free( signature.data );
- return STATUS_SUCCESS;
+ return status;
}
NTSTATUS key_destroy( struct key *key )
--
2.24.0
Dec. 5, 2019
Re: [PATCH 1/3] bcrypt: Add support for signing hashes with ECDSA keys.
by Derek Lesho
On 12/5/19 4:55 AM, Hans Leidekker wrote:
> + if ((err = pgnutls_decode_rs_value( &signature, &r, &s )))
> + {
> + ERR( "failed to get R/S values from signature %u\n", err );
> + return 0;
> + }
As I was looking at this patch again making a version that will work in
Proton, I noticed this mistake I made. I'll send a correction soon.
Dec. 5, 2019
Re: [PATCH] msxml3: all string passed to IXMLDOMDocument_load() need to be URL-unescaped
by Damjan Jovanovic
On Thu, Dec 5, 2019 at 1:45 PM Nikolay Sivov <nsivov(a)codeweavers.com> wrote:
> Do we need to unescape if it's not a file:// url? I was hoping we could
> find some IUri/path API flags to do what we need for us.
>
>
The CreateUri() function called at the end of create_uri() does its own
unescaping, which is why I didn't pass it the unescaped URL, but left it
with the original URL. My unescaping is done for the benefit of the earlier
function, PathIsURLW(), which doesn't unescape internally, and for
PathSearchAndQualifyW() and UrlCreateFromPathW(), which require paths not
URLs, and paths are always unescaped.
> Another concern is path/url max lengths are used seemingly randomly, and
> it's not a problem with your change, but with existing code. I think
> asking for required length and allocating it is better.
>
>
Sure.
> + /* Regular local path with some URL encoded characters. */
> + strcpy(path2, path);
> + n = strlen(path2);
> + path2[n-1] = '%';
> + path2[n] = '6';
> + path2[n+1] = 'C';
> + path2[n+2] = '\0'; /* C:\path\to\winetest.xm%6C */
> + test_doc_load_from_path(doc, path2);
>
> Could you make this more readable? Maybe strcat-ing escaped file name as
> string literal instead.
>
Will do.
>
> + /* Regular local path with all URL encoded characters. */
> + percent_path = HeapAlloc(GetProcessHeap(), 0, 3*n + 1);
> + for (i = 0; i < n; i++)
> + {
> + static char hex_tab[] = "0123456789ABCDEF";
> + percent_path[3*i] = '%';
> + percent_path[3*i + 1] = hex_tab[path[i] >> 4];
> + percent_path[3*i + 2] = hex_tab[path[i] & 0xF];
> + }
> + percent_path[3*n] = '\0';
> + test_doc_load_from_path(doc, percent_path);
> + HeapFree(GetProcessHeap(), 0, percent_path);
>
> Couple of cases would be enough, like you did earlier for "l" -> %6c, and
> another one for " " -> %20. Space is actually not tested by this patch, and
> that's what application is using. If you still want to encode it entirely,
> please add a helper function.
>
Agreed. It would actually be good to test with both a space and %20.
Dec. 5, 2019
[PATCH] mscoree: Ignore empty privatePath.
by Vincent Povirk
Signed-off-by: Vincent Povirk <vincent(a)codeweavers.com>
---
Spotted by Rafał Mużyło.
dlls/mscoree/corruntimehost.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c
index e932a7f58be..a900ed6a3e2 100644
--- a/dlls/mscoree/corruntimehost.c
+++ b/dlls/mscoree/corruntimehost.c
@@ -1478,7 +1478,7 @@ __int32 WINAPI _CorExeMain(void)
wcscat(config_file, dotconfig);
hr = parse_config_file(config_file, &parsed_config);
- if (SUCCEEDED(hr) && parsed_config.private_path)
+ if (SUCCEEDED(hr) && parsed_config.private_path && parsed_config.private_path[0])
{
for(i = 0; parsed_config.private_path[i] != 0; i++)
if (parsed_config.private_path[i] == ';') number_of_private_paths++;
--
2.17.1
Dec. 5, 2019
Re: mscoree: fix an error in string access
by Vincent Povirk (they/them)
Thanks. Unfortunately, this doesn't seem to have been picked up by the
patch tracker.
I think we should treat an empty string the same as a NULL string and
not try to parse it at all.
Dec. 5, 2019
Re: [wine-devel] Wine staging 4.21 release
by Zebediah Figura
On 12/5/19 9:57 AM, Zebediah Figura wrote:
> On 12/4/19 4:56 PM, Alan W. Irwin wrote:
>> On 2019-11-30 04:56-0000 Alistair Leslie-Hughes wrote:
>>
>>> Binary packages for various distributions will be available from:
>>> https://www.winehq.org/download
>>>
>>> Summary since last release
>>> * Rebased to current wine 4.21 (833 patches are applied to wine vanilla)
>>>
>>> Upstreamed (Either directly from staging or fixed with a similar patch).
>>> * none
>>>
>>> Added:
>>> * [47668] kernelbase: Improve stub for ReOpenFile and add small test
>>> * [48138] League of Legends 9.23: Crash after champ select
>>> * [47970] Legends of Runeterra crashes at launch
>>> * [40334] AION - Wine /Unhandled exception: page fault on read access to
>>> 0x00000000 in 64-bit code (0x0000000000000000).
>>> * [48175] AION (64 bit) - crashes in crysystem.dll.CryFree() due to high
>>> memory pointers allocated
>>> * [46568] 64-bit msxml6.dll from Microsoft Core XML Services 6.0 redist
>>> package fails to load (Wine doesn't respect 44-bit user-mode VA
>>> limitation from Windows < 8.1)
>>>
>>> Updated:
>>> * d3d9-Direct3DShaderValidatorCreate9
>>> * winecfg-Staging
>>
>> [...]
>>
>> Hi Alistair:
>>
>> Could you explain how these patch numbers in your report are related with each other?
>> For example, my initial assumption was the rebased patch number should
>> be equal to the corresponding number in the last report plus the added
>> patches in this report less the upstreamed patches in this report, i.e.,
>>
>> r = r_old + a - u
>>
>> where r and r_old are the current and last reported rebased patch numbers and a and u
>> are the current added and upstreamed patch numbers.
>>
>> But looking at the last several reports that formula predicts
>> incorrect results with the rebased patch number changing in what looks
>> like a completely arbitrary way from report to report compared to the
>> prediction. So it appears the above formula is incorrect and/or
>> incomplete.
>>
>> Could you let me know what the correct formula is for predicting the
>> rebased patch number from report to report (which helps to evaluate
>> the reliability of the staging patch number statistics that you
>> present), and if that formula depends on information (my guess is it
>> is the number of patches in staging that have just been deleted by the
>> staging maintainers because they judge those patches to not be
>> worthwhile) that you currently do not include in your reports, could
>> you include that important information in your following reports?
>
> In this case, I guess the confusion is caused by the fact that bugs
> 48175 and 46568 are addressed by the same patch set (viz.
> ntdll-ForceBottomUpAlloc). I suspect it may be better (or at least more
> consistent) to list the patch name first, followed by the bug(s) it
> addresses. We could also list the relevant bugs under the "updated" and
> "removed" sections.
The other cause for confusion, it occurs, is that 833 is the number of
individual patches, but these are organized into series, and the latter
are what are given symbolic names.
>
>>
>> TIA.
>>
>> Alan
>> __________________________
>> Alan W. Irwin
>>
>> Programming affiliations with the FreeEOS equation-of-state
>> implementation for stellar interiors (freeeos.sf.net) the Time
>> Ephemerides project (timeephem.sf.net) PLplot scientific plotting
>> software package (plplot.org) the libLASi project
>> (unifont.org/lasi) the Loads of Linux Links project (loll.sf.net)
>> and the Linux Brochure Project (lbproject.sf.net)
>> __________________________
>>
>> Linux-powered Science
>> __________________________
>>
>
Dec. 5, 2019
Re: [wine-devel] Wine staging 4.21 release
by Zebediah Figura
On 12/4/19 4:56 PM, Alan W. Irwin wrote:
> On 2019-11-30 04:56-0000 Alistair Leslie-Hughes wrote:
>
>> Binary packages for various distributions will be available from:
>> https://www.winehq.org/download
>>
>> Summary since last release
>> * Rebased to current wine 4.21 (833 patches are applied to wine vanilla)
>>
>> Upstreamed (Either directly from staging or fixed with a similar patch).
>> * none
>>
>> Added:
>> * [47668] kernelbase: Improve stub for ReOpenFile and add small test
>> * [48138] League of Legends 9.23: Crash after champ select
>> * [47970] Legends of Runeterra crashes at launch
>> * [40334] AION - Wine /Unhandled exception: page fault on read access to
>> 0x00000000 in 64-bit code (0x0000000000000000).
>> * [48175] AION (64 bit) - crashes in crysystem.dll.CryFree() due to high
>> memory pointers allocated
>> * [46568] 64-bit msxml6.dll from Microsoft Core XML Services 6.0 redist
>> package fails to load (Wine doesn't respect 44-bit user-mode VA
>> limitation from Windows < 8.1)
>>
>> Updated:
>> * d3d9-Direct3DShaderValidatorCreate9
>> * winecfg-Staging
>
> [...]
>
> Hi Alistair:
>
> Could you explain how these patch numbers in your report are related with each other?
> For example, my initial assumption was the rebased patch number should
> be equal to the corresponding number in the last report plus the added
> patches in this report less the upstreamed patches in this report, i.e.,
>
> r = r_old + a - u
>
> where r and r_old are the current and last reported rebased patch numbers and a and u
> are the current added and upstreamed patch numbers.
>
> But looking at the last several reports that formula predicts
> incorrect results with the rebased patch number changing in what looks
> like a completely arbitrary way from report to report compared to the
> prediction. So it appears the above formula is incorrect and/or
> incomplete.
>
> Could you let me know what the correct formula is for predicting the
> rebased patch number from report to report (which helps to evaluate
> the reliability of the staging patch number statistics that you
> present), and if that formula depends on information (my guess is it
> is the number of patches in staging that have just been deleted by the
> staging maintainers because they judge those patches to not be
> worthwhile) that you currently do not include in your reports, could
> you include that important information in your following reports?
In this case, I guess the confusion is caused by the fact that bugs
48175 and 46568 are addressed by the same patch set (viz.
ntdll-ForceBottomUpAlloc). I suspect it may be better (or at least more
consistent) to list the patch name first, followed by the bug(s) it
addresses. We could also list the relevant bugs under the "updated" and
"removed" sections.
>
> TIA.
>
> Alan
> __________________________
> Alan W. Irwin
>
> Programming affiliations with the FreeEOS equation-of-state
> implementation for stellar interiors (freeeos.sf.net) the Time
> Ephemerides project (timeephem.sf.net) PLplot scientific plotting
> software package (plplot.org) the libLASi project
> (unifont.org/lasi) the Loads of Linux Links project (loll.sf.net)
> and the Linux Brochure Project (lbproject.sf.net)
> __________________________
>
> Linux-powered Science
> __________________________
>
Dec. 5, 2019
[PATCH] jscript: Import to_int32 implementation from WebKit.
by Jacek Caban
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/jscript/jsutils.c | 63 +++++++++++++++++++++++++++++++++---------
1 file changed, 50 insertions(+), 13 deletions(-)
Dec. 5, 2019
[PATCH vkd3d v3 5/5] vkd3d: Implement support for D3D12_FEATURE_COMMAND_QUEUE_PRIORITY.
by Conor McCarthy
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
include/vkd3d_d3d12.idl | 7 +++++++
libs/vkd3d/device.c | 26 ++++++++++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl
index 60f36b4..6e674a0 100644
--- a/include/vkd3d_d3d12.idl
+++ b/include/vkd3d_d3d12.idl
@@ -1654,6 +1654,13 @@ typedef struct D3D12_FEATURE_DATA_SHADER_CACHE
D3D12_SHADER_CACHE_SUPPORT_FLAGS SupportFlags;
} D3D12_FEATURE_DATA_SHADER_CACHE;
+typedef struct D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY
+{
+ D3D12_COMMAND_LIST_TYPE CommandListType;
+ UINT Priority;
+ BOOL PriorityForTypeIsSupported;
+} D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY;
+
typedef enum D3D12_FEATURE
{
D3D12_FEATURE_D3D12_OPTIONS = 0,
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 694c322..8bae29d 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -2785,6 +2785,32 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device *
return S_OK;
}
+ case D3D12_FEATURE_COMMAND_QUEUE_PRIORITY:
+ {
+ D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ switch (data->CommandListType)
+ {
+ case D3D12_COMMAND_LIST_TYPE_DIRECT:
+ case D3D12_COMMAND_LIST_TYPE_COMPUTE:
+ case D3D12_COMMAND_LIST_TYPE_COPY:
+ data->PriorityForTypeIsSupported = FALSE;
+ TRACE("Command list type %#x, priority %u, supported %#x.\n",
+ data->CommandListType, data->Priority, data->PriorityForTypeIsSupported);
+ return S_OK;
+
+ default:
+ FIXME("Unhandled command list type %#x.\n", data->CommandListType);
+ return E_INVALIDARG;
+ }
+ }
+
default:
FIXME("Unhandled feature %#x.\n", feature);
return E_NOTIMPL;
--
2.24.0
Dec. 5, 2019
[PATCH vkd3d v3 4/5] vkd3d: Implement support for D3D12_FEATURE_SHADER_CACHE.
by Conor McCarthy
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
include/vkd3d_d3d12.idl | 14 ++++++++++++++
libs/vkd3d/device.c | 19 +++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl
index 4c69454..60f36b4 100644
--- a/include/vkd3d_d3d12.idl
+++ b/include/vkd3d_d3d12.idl
@@ -184,6 +184,15 @@ typedef enum D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER
D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_2 = 0x2,
} D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER;
+typedef enum D3D12_SHADER_CACHE_SUPPORT_FLAGS
+{
+ D3D12_SHADER_CACHE_SUPPORT_NONE = 0x0,
+ D3D12_SHADER_CACHE_SUPPORT_SINGLE_PSO = 0x1,
+ D3D12_SHADER_CACHE_SUPPORT_LIBRARY = 0x2,
+ D3D12_SHADER_CACHE_SUPPORT_AUTOMATIC_INPROC_CACHE = 0x4,
+ D3D12_SHADER_CACHE_SUPPORT_AUTOMATIC_DISK_CACHE = 0x8,
+} D3D12_SHADER_CACHE_SUPPORT_FLAGS;
+
interface ID3D12Fence;
interface ID3D12RootSignature;
interface ID3D12Heap;
@@ -1640,6 +1649,11 @@ typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS2
D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER ProgrammableSamplePositionsTier;
} D3D12_FEATURE_DATA_D3D12_OPTIONS2;
+typedef struct D3D12_FEATURE_DATA_SHADER_CACHE
+{
+ D3D12_SHADER_CACHE_SUPPORT_FLAGS SupportFlags;
+} D3D12_FEATURE_DATA_SHADER_CACHE;
+
typedef enum D3D12_FEATURE
{
D3D12_FEATURE_D3D12_OPTIONS = 0,
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 1063680..694c322 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -2766,6 +2766,25 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device *
return S_OK;
}
+ case D3D12_FEATURE_SHADER_CACHE:
+ {
+ D3D12_FEATURE_DATA_SHADER_CACHE *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ /* FIXME: The D3D12 documentation states that D3D12_SHADER_CACHE_SUPPORT_SINGLE_PSO is
+ * always supported, but the CachedPSO field of D3D12_GRAPHICS_PIPELINE_STATE_DESC is
+ * ignored and GetCachedBlob() is a stub. */
+ data->SupportFlags = D3D12_SHADER_CACHE_SUPPORT_NONE;
+
+ TRACE("Shader cache support %#x.\n", data->SupportFlags);
+ return S_OK;
+ }
+
default:
FIXME("Unhandled feature %#x.\n", feature);
return E_NOTIMPL;
--
2.24.0
Dec. 5, 2019