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
March 2020
- 72 participants
- 2643 messages
[PATCH v2 3/6] d3d8/tests: Add cursor size tests.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/d3d8/tests/device.c | 97 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 96 insertions(+), 1 deletion(-)
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index b7aa02adabb..c96adfc7481 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -931,16 +931,30 @@ cleanup:
static void test_cursor(void)
{
+ unsigned int adapter_idx, adapter_count, test_idx;
IDirect3DSurface8 *cursor = NULL;
+ struct device_desc device_desc;
+ unsigned int width, height;
IDirect3DDevice8 *device;
+ HRESULT expected_hr, hr;
+ D3DDISPLAYMODE mode;
CURSORINFO info;
IDirect3D8 *d3d;
ULONG refcount;
HCURSOR cur;
HWND window;
- HRESULT hr;
BOOL ret;
+ static const DWORD device_flags[] = {0, CREATE_DEVICE_FULLSCREEN};
+ static const SIZE cursor_sizes[] =
+ {
+ {1, 1},
+ {2, 4},
+ {3, 2},
+ {2, 3},
+ {6, 6},
+ };
+
window = create_window();
ok(!!window, "Failed to create a window.\n");
@@ -1001,8 +1015,89 @@ static void test_cursor(void)
ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
ok(info.hCursor != cur, "The cursor handle is %p\n", info.hCursor);
+ /* Cursor dimensions must all be powers of two */
+ for (test_idx = 0; test_idx < ARRAY_SIZE(cursor_sizes); ++test_idx)
+ {
+ width = cursor_sizes[test_idx].cx;
+ height = cursor_sizes[test_idx].cy;
+ hr = IDirect3DDevice8_CreateImageSurface(device, width, height, D3DFMT_A8R8G8B8, &cursor);
+ ok(hr == D3D_OK, "Test %u: CreateImageSurface failed, hr %#x.\n", test_idx, hr);
+ hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
+ if (width && !(width & (width - 1)) && height && !(height & (height - 1)))
+ expected_hr = D3D_OK;
+ else
+ expected_hr = D3DERR_INVALIDCALL;
+ todo_wine_if(expected_hr == D3DERR_INVALIDCALL)
+ ok(hr == expected_hr, "Test %u: Expect SetCursorProperties return %#x, got %#x.\n",
+ test_idx, expected_hr, hr);
+ IDirect3DSurface8_Release(cursor);
+ }
+
refcount = IDirect3DDevice8_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
+
+ /* Cursor dimensions must not exceed adapter display mode */
+ device_desc.device_window = window;
+ device_desc.width = 640;
+ device_desc.height = 480;
+
+ adapter_count = IDirect3D8_GetAdapterCount(d3d);
+ for (adapter_idx = 0; adapter_idx < adapter_count; ++adapter_idx)
+ {
+ for (test_idx = 0; test_idx < ARRAY_SIZE(device_flags); ++test_idx)
+ {
+ device_desc.adapter_ordinal = adapter_idx;
+ device_desc.flags = device_flags[test_idx];
+ if (!(device = create_device(d3d, window, &device_desc)))
+ {
+ skip("Adapter %u test %u: Failed to create a D3D device.\n", adapter_idx, test_idx);
+ break;
+ }
+
+ hr = IDirect3D8_GetAdapterDisplayMode(d3d, adapter_idx, &mode);
+ ok(hr == D3D_OK, "Adapter %u test %u: GetAdapterDisplayMode failed, hr %#x.\n",
+ adapter_idx, test_idx, hr);
+
+ /* Find the largest width and height that are powers of two and less than the display mode */
+ width = 1;
+ height = 1;
+ while (width * 2 <= mode.Width)
+ width *= 2;
+ while (height * 2 <= mode.Height)
+ height *= 2;
+
+ hr = IDirect3DDevice8_CreateImageSurface(device, width, height, D3DFMT_A8R8G8B8, &cursor);
+ ok(hr == D3D_OK, "Adapter %u test %u: CreateImageSurface failed, hr %#x.\n",
+ adapter_idx, test_idx, hr);
+ hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
+ ok(hr == D3D_OK, "Adapter %u test %u: SetCursorProperties failed, hr %#x.\n",
+ adapter_idx, test_idx, hr);
+ IDirect3DSurface8_Release(cursor);
+
+ hr = IDirect3DDevice8_CreateImageSurface(device, width * 2, height, D3DFMT_A8R8G8B8,
+ &cursor);
+ ok(hr == D3D_OK, "Adapter %u test %u: CreateImageSurface failed, hr %#x.\n",
+ adapter_idx, test_idx, hr);
+ hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
+ ok(hr == D3DERR_INVALIDCALL,
+ "Adapter %u test %u: Expect SetCursorProperties return %#x, got %#x.\n",
+ adapter_idx, test_idx, D3DERR_INVALIDCALL, hr);
+ IDirect3DSurface8_Release(cursor);
+
+ hr = IDirect3DDevice8_CreateImageSurface(device, width, height * 2, D3DFMT_A8R8G8B8,
+ &cursor);
+ ok(hr == D3D_OK, "Adapter %u test %u: CreateImageSurface failed, hr %#x.\n",
+ adapter_idx, test_idx, hr);
+ hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
+ ok(hr == D3DERR_INVALIDCALL,
+ "Adapter %u test %u: Expect SetCursorProperties return %#x, got %#x.\n",
+ adapter_idx, test_idx, D3DERR_INVALIDCALL, hr);
+ IDirect3DSurface8_Release(cursor);
+
+ refcount = IDirect3DDevice8_Release(device);
+ ok(!refcount, "Adapter %u: Device has %u references left.\n", adapter_idx, refcount);
+ }
+ }
cleanup:
IDirect3D8_Release(d3d);
DestroyWindow(window);
--
2.20.1
March 31, 2020
[PATCH v2 2/6] d3d9/tests: Fix possible test failures.
by Zhiyi Zhang
expect_messages points to a local variable. When it goes out of scope, it
reads into random memory, causing failures.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/d3d9/tests/d3d9ex.c | 17 +++++++++++++----
dlls/d3d9/tests/device.c | 21 +++++++++++++++++----
2 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/dlls/d3d9/tests/d3d9ex.c b/dlls/d3d9/tests/d3d9ex.c
index 5b24f6b05eb..dab5cf6d8df 100644
--- a/dlls/d3d9/tests/d3d9ex.c
+++ b/dlls/d3d9/tests/d3d9ex.c
@@ -2631,6 +2631,7 @@ static void test_wndproc(void)
{
struct wndproc_thread_param thread_params;
struct device_desc device_desc;
+ static WINDOWPOS windowpos;
IDirect3DDevice9Ex *device;
WNDCLASSA wc = {0};
HANDLE thread;
@@ -2646,7 +2647,6 @@ static void test_wndproc(void)
LONG change_ret, device_style;
BOOL ret;
IDirect3D9Ex *d3d9ex;
- WINDOWPOS windowpos;
static const struct message create_messages[] =
{
@@ -2747,7 +2747,7 @@ static void test_wndproc(void)
/* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
{0, 0, FALSE, 0},
};
- struct message mode_change_messages[] =
+ static const struct message mode_change_messages[] =
{
{WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
{WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
@@ -2760,7 +2760,7 @@ static void test_wndproc(void)
* ShowWindow does not send such a message because the window is already visible. */
{0, 0, FALSE, 0},
};
- struct message mode_change_messages_hidden[] =
+ static const struct message mode_change_messages_hidden[] =
{
{WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
{WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
@@ -2777,7 +2777,7 @@ static void test_wndproc(void)
{WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
{0, 0, FALSE, 0},
};
- struct
+ static const struct
{
DWORD create_flags;
const struct message *focus_loss_messages;
@@ -2859,6 +2859,9 @@ static void test_wndproc(void)
return;
}
+ filter_messages = NULL;
+ expect_messages = NULL;
+
wc.lpfnWndProc = test_proc;
wc.lpszClassName = "d3d9_test_wndproc_wc";
ok(RegisterClassA(&wc), "Failed to register window class.\n");
@@ -3189,6 +3192,7 @@ static void test_wndproc(void)
flush_events();
ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
expect_messages->message, expect_messages->window, i);
+ expect_messages = NULL;
/* World of Warplanes hides the window by removing WS_VISIBLE and expects Reset() to show it again. */
device_style = GetWindowLongA(device_window, GWL_STYLE);
@@ -3208,6 +3212,7 @@ static void test_wndproc(void)
flush_events();
ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
expect_messages->message, expect_messages->window, i);
+ expect_messages = NULL;
if (!(tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES))
{
@@ -3244,6 +3249,7 @@ static void test_wndproc(void)
done:
filter_messages = NULL;
+ expect_messages = NULL;
DestroyWindow(device_window);
DestroyWindow(focus_window);
SetEvent(thread_params.test_finished);
@@ -3270,6 +3276,9 @@ static void test_wndproc_windowed(void)
DWORD res, tid;
HWND tmp;
+ filter_messages = NULL;
+ expect_messages = NULL;
+
wc.lpfnWndProc = test_proc;
wc.lpszClassName = "d3d9_test_wndproc_wc";
ok(RegisterClassA(&wc), "Failed to register window class.\n");
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index 839c0301853..74d330c80bc 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -3655,6 +3655,7 @@ static void test_wndproc(void)
{
struct wndproc_thread_param thread_params;
struct device_desc device_desc;
+ static WINDOWPOS windowpos;
IDirect3DDevice9 *device;
WNDCLASSA wc = {0};
IDirect3D9 *d3d9;
@@ -3670,7 +3671,6 @@ static void test_wndproc(void)
DEVMODEW devmode;
LONG change_ret, device_style;
BOOL ret;
- WINDOWPOS windowpos;
static const struct message create_messages[] =
{
@@ -3784,7 +3784,7 @@ static void test_wndproc(void)
/* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
{0, 0, FALSE, 0},
};
- struct message mode_change_messages[] =
+ static const struct message mode_change_messages[] =
{
{WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
{WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
@@ -3797,7 +3797,7 @@ static void test_wndproc(void)
* ShowWindow does not send such a message because the window is already visible. */
{0, 0, FALSE, 0},
};
- struct message mode_change_messages_hidden[] =
+ static const struct message mode_change_messages_hidden[] =
{
{WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
{WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
@@ -3814,7 +3814,7 @@ static void test_wndproc(void)
{WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
{0, 0, FALSE, 0},
};
- struct
+ static const struct
{
DWORD create_flags;
const struct message *focus_loss_messages, *reactivate_messages;
@@ -3893,6 +3893,9 @@ static void test_wndproc(void)
return;
}
+ filter_messages = NULL;
+ expect_messages = NULL;
+
wc.lpfnWndProc = test_proc;
wc.lpszClassName = "d3d9_test_wndproc_wc";
ok(RegisterClassA(&wc), "Failed to register window class.\n");
@@ -4258,6 +4261,7 @@ static void test_wndproc(void)
flush_events();
ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
expect_messages->message, expect_messages->window, i);
+ expect_messages = NULL;
/* World of Warplanes hides the window by removing WS_VISIBLE and expects Reset() to show it again. */
device_style = GetWindowLongA(device_window, GWL_STYLE);
@@ -4277,6 +4281,7 @@ static void test_wndproc(void)
flush_events();
ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
expect_messages->message, expect_messages->window, i);
+ expect_messages = NULL;
if (!(tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES))
{
@@ -4314,6 +4319,7 @@ static void test_wndproc(void)
done:
filter_messages = NULL;
+ expect_messages = NULL;
DestroyWindow(device_window);
DestroyWindow(focus_window);
SetEvent(thread_params.test_finished);
@@ -4344,6 +4350,9 @@ static void test_wndproc_windowed(void)
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
ok(!!d3d9, "Failed to create a D3D object.\n");
+ filter_messages = NULL;
+ expect_messages = NULL;
+
wc.lpfnWndProc = test_proc;
wc.lpszClassName = "d3d9_test_wndproc_wc";
ok(RegisterClassA(&wc), "Failed to register window class.\n");
@@ -4557,6 +4566,7 @@ static void test_reset_fullscreen(void)
d3d = Direct3DCreate9(D3D_SDK_VERSION);
ok(!!d3d, "Failed to create a D3D object.\n");
+ filter_messages = NULL;
expect_messages = messages;
wc.cbSize = sizeof(wc);
@@ -5259,6 +5269,9 @@ static void test_device_window_reset(void)
HRESULT hr;
ULONG ref;
+ filter_messages = NULL;
+ expect_messages = NULL;
+
wc.lpfnWndProc = test_proc;
wc.lpszClassName = "d3d9_test_wndproc_wc";
ok(RegisterClassA(&wc), "Failed to register window class.\n");
--
2.20.1
March 31, 2020
[PATCH v2 1/6] d3d8/tests: Fix possible test failures.
by Zhiyi Zhang
expect_messages points to a local variable. When it goes out of scope, it
reads into random memory, causing failures.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
v2: Supersede 182264~182270
dlls/d3d8/tests/device.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index d87832b716d..b7aa02adabb 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -2662,6 +2662,7 @@ static void test_wndproc(void)
{
struct wndproc_thread_param thread_params;
struct device_desc device_desc;
+ static WINDOWPOS windowpos;
IDirect3DDevice8 *device;
WNDCLASSA wc = {0};
IDirect3D8 *d3d8;
@@ -2677,7 +2678,6 @@ static void test_wndproc(void)
DEVMODEW devmode;
LONG change_ret, device_style;
BOOL ret;
- WINDOWPOS windowpos;
static const struct message create_messages[] =
{
@@ -2777,7 +2777,7 @@ static void test_wndproc(void)
{WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MAXIMIZED},
{0, 0, FALSE, 0},
};
- struct message mode_change_messages[] =
+ static const struct message mode_change_messages[] =
{
{WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
{WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
@@ -2790,7 +2790,7 @@ static void test_wndproc(void)
* ShowWindow does not send such a message because the window is already visible. */
{0, 0, FALSE, 0},
};
- struct message mode_change_messages_hidden[] =
+ static const struct message mode_change_messages_hidden[] =
{
{WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
{WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
@@ -2857,6 +2857,9 @@ static void test_wndproc(void)
return;
}
+ filter_messages = NULL;
+ expect_messages = NULL;
+
wc.lpfnWndProc = test_proc;
wc.lpszClassName = "d3d8_test_wndproc_wc";
ok(RegisterClassA(&wc), "Failed to register window class.\n");
@@ -3200,6 +3203,7 @@ static void test_wndproc(void)
flush_events();
ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
expect_messages->message, expect_messages->window, i);
+ expect_messages = NULL;
/* World of Warplanes hides the window by removing WS_VISIBLE and expects Reset() to show it again. */
device_style = GetWindowLongA(device_window, GWL_STYLE);
@@ -3219,6 +3223,7 @@ static void test_wndproc(void)
flush_events();
ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
expect_messages->message, expect_messages->window);
+ expect_messages = NULL;
ok(windowpos.hwnd == device_window && !windowpos.hwndInsertAfter
&& !windowpos.x && !windowpos.y && !windowpos.cx && !windowpos.cy
@@ -3242,6 +3247,7 @@ static void test_wndproc(void)
done:
filter_messages = NULL;
+ expect_messages = NULL;
IDirect3D8_Release(d3d8);
SetEvent(thread_params.test_finished);
@@ -3272,6 +3278,9 @@ static void test_wndproc_windowed(void)
d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
ok(!!d3d8, "Failed to create a D3D object.\n");
+ filter_messages = NULL;
+ expect_messages = NULL;
+
wc.lpfnWndProc = test_proc;
wc.lpszClassName = "d3d8_test_wndproc_wc";
ok(RegisterClassA(&wc), "Failed to register window class.\n");
@@ -4177,6 +4186,9 @@ static void test_device_window_reset(void)
HRESULT hr;
ULONG ref;
+ filter_messages = NULL;
+ expect_messages = NULL;
+
wc.lpfnWndProc = test_proc;
wc.lpszClassName = "d3d8_test_wndproc_wc";
ok(RegisterClassA(&wc), "Failed to register window class.\n");
--
2.20.1
March 31, 2020
[PATCH vkd3d] include: Use the correct type for the tessellator partitioning compile argument.
by Henri Verbeet
From: Chip Davis <cdavis(a)codeweavers.com>
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
This supersedes patch 182371.
include/vkd3d_shader.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h
index 6b4d3f5..327b788 100644
--- a/include/vkd3d_shader.h
+++ b/include/vkd3d_shader.h
@@ -272,7 +272,7 @@ struct vkd3d_shader_domain_shader_compile_arguments
const void *next;
enum vkd3d_tessellator_output_primitive output_primitive;
- enum vkd3d_tessellator_output_primitive partitioning;
+ enum vkd3d_tessellator_partitioning partitioning;
};
/* root signature 1.0 */
--
2.20.1
March 31, 2020
[PATCH v2 6/6] winedbg: Cleanup return for kill and status packets.
by Rémi Bernon
There's a special packet_last_f flag to indicate we should quit, use
that on kill packet instead of exiting abruptly.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
programs/winedbg/gdbproxy.c | 20 ++++++--------------
1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c
index a9f9210f5291..02522ea31955 100644
--- a/programs/winedbg/gdbproxy.c
+++ b/programs/winedbg/gdbproxy.c
@@ -814,15 +814,12 @@ static inline void packet_reply_register_hex_to(struct gdb_context* gdbctx, unsi
static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
{
- enum packet_return ret = packet_done;
-
- packet_reply_open(gdbctx);
-
if (gdbctx->process != NULL)
{
unsigned char sig;
unsigned i;
+ packet_reply_open(gdbctx);
packet_reply_add(gdbctx, "T");
sig = gdbctx->last_sig;
packet_reply_val(gdbctx, sig, 1);
@@ -840,19 +837,17 @@ static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
packet_reply_register_hex_to(gdbctx, i);
packet_reply_add(gdbctx, ";");
}
+
+ packet_reply_close(gdbctx);
+ return packet_done;
}
else
{
/* Try to put an exit code
* Cannot use GetExitCodeProcess, wouldn't fit in a 8 bit value, so
* just indicate the end of process and exit */
- packet_reply_add(gdbctx, "W00");
- /*if (!gdbctx->extended)*/ ret |= packet_last_f;
+ return packet_reply(gdbctx, "W00") | packet_last_f;
}
-
- packet_reply_close(gdbctx);
-
- return ret;
}
#if 0
@@ -1159,10 +1154,7 @@ static enum packet_return packet_kill(struct gdb_context* gdbctx)
if (!gdbctx->extended)
/* dunno whether GDB cares or not */
#endif
- wait(NULL);
- exit(0);
- /* assume we can't really answer something here */
- /* return packet_done; */
+ return packet_ok | packet_last_f;
}
static enum packet_return packet_thread(struct gdb_context* gdbctx)
--
2.26.0.rc2
March 31, 2020
[PATCH v2 5/6] winedbg: Explicitely handle MustReplyEmpty packet.
by Rémi Bernon
We now always print a warning when packet_error is returned.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
programs/winedbg/gdbproxy.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c
index 5e9e274beb90..a9f9210f5291 100644
--- a/programs/winedbg/gdbproxy.c
+++ b/programs/winedbg/gdbproxy.c
@@ -1070,8 +1070,9 @@ static enum packet_return packet_verbose(struct gdb_context* gdbctx)
return packet_verbose_cont(gdbctx);
}
- WARN("Unhandled verbose packet %s\n",
- debugstr_an(gdbctx->in_packet, gdbctx->in_packet_len));
+ if (gdbctx->in_packet_len == 14 && !memcmp(gdbctx->in_packet, "MustReplyEmpty", 14))
+ return packet_reply(gdbctx, "");
+
return packet_error;
}
--
2.26.0.rc2
March 31, 2020
[PATCH v2 4/6] winedbg: Support QStartNoAckMode to reduce verbosity.
by Rémi Bernon
We don't have to validate and acknowledge the packets as long as this
mode is enabled, this will reduce verbosity especially when tracing.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
programs/winedbg/gdbproxy.c | 32 +++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c
index 211d39edd596..5e9e274beb90 100644
--- a/programs/winedbg/gdbproxy.c
+++ b/programs/winedbg/gdbproxy.c
@@ -94,6 +94,7 @@ struct gdb_context
struct dbg_process* process;
/* Unix environment */
unsigned long wine_segs[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
+ BOOL no_ack_mode;
};
static BOOL tgt_process_gdbproxy_read(HANDLE hProcess, const void* addr,
@@ -1614,15 +1615,11 @@ static enum packet_return packet_query(struct gdb_context* gdbctx)
return packet_ok;
if (strncmp(gdbctx->in_packet, "Supported", 9) == 0)
{
- if (*target_xml)
- return packet_reply(gdbctx, "PacketSize=400;qXfer:features:read+");
- else
- {
- /* no features supported */
- packet_reply_open(gdbctx);
- packet_reply_close(gdbctx);
- return packet_done;
- }
+ packet_reply_open(gdbctx);
+ packet_reply_add(gdbctx, "QStartNoAckMode+;");
+ if (*target_xml) packet_reply_add(gdbctx, "PacketSize=400;qXfer:features:read+");
+ packet_reply_close(gdbctx);
+ return packet_done;
}
break;
case 'T':
@@ -1659,6 +1656,17 @@ static enum packet_return packet_query(struct gdb_context* gdbctx)
return packet_error;
}
+static enum packet_return packet_set(struct gdb_context* gdbctx)
+{
+ if (strncmp(gdbctx->in_packet, "StartNoAckMode", 14) == 0)
+ {
+ gdbctx->no_ack_mode = TRUE;
+ return packet_ok;
+ }
+
+ return packet_error;
+}
+
static enum packet_return packet_step(struct gdb_context* gdbctx)
{
/* FIXME: add support for address in packet */
@@ -1736,7 +1744,7 @@ static struct packet_entry packet_entries[] =
{'p', packet_read_register},
{'P', packet_write_register},
{'q', packet_query},
- /* {'Q', packet_set}, */
+ {'Q', packet_set},
/* {'R', packet,restart}, only in extended mode ! */
{'s', packet_step},
/*{'S', packet_step_signal}, hard(er) to implement */
@@ -1757,7 +1765,8 @@ static BOOL extract_packets(struct gdb_context* gdbctx)
* end points to the end of the received data buffer
*/
- while ((ptr = memchr(sum, '$', end - sum)) &&
+ while (!gdbctx->no_ack_mode &&
+ (ptr = memchr(sum, '$', end - sum)) &&
(sum = memchr(ptr, '#', end - ptr)) &&
(end - sum >= 3) && sscanf(sum, "#%02x", &cksum) == 1)
{
@@ -1998,6 +2007,7 @@ static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags, unsigne
gdbctx->last_sig = 0;
gdbctx->in_trap = FALSE;
gdbctx->process = NULL;
+ gdbctx->no_ack_mode = FALSE;
for (i = 0; i < ARRAY_SIZE(gdbctx->wine_segs); i++)
gdbctx->wine_segs[i] = 0;
--
2.26.0.rc2
March 31, 2020
[PATCH v2 3/6] winedbg: Cleanup extract_packets for faster acking.
by Rémi Bernon
Sometimes multiple packets are received and we were assuming it was
some repeated requests due to slow ack. We can ack packets first.
It was also dropping some perfectly valid packets and we should process
them all. For instance, lldb frontend sometimes send multiple packets
at a the same time and expects them to be handled.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
programs/winedbg/gdbproxy.c | 151 +++++++++++++++++-------------------
1 file changed, 72 insertions(+), 79 deletions(-)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c
index fde6c556c26d..211d39edd596 100644
--- a/programs/winedbg/gdbproxy.c
+++ b/programs/winedbg/gdbproxy.c
@@ -1746,95 +1746,88 @@ static struct packet_entry packet_entries[] =
static BOOL extract_packets(struct gdb_context* gdbctx)
{
- char* end;
- int plen;
- unsigned char in_cksum, loc_cksum;
- char* ptr;
- enum packet_return ret = packet_error;
- int num_packet = 0;
+ char *ptr, *sum = gdbctx->in_buf, *end = gdbctx->in_buf + gdbctx->in_len;
+ enum packet_return ret = packet_error;
+ unsigned int cksum;
+ int i, len;
+
+ /* ptr points to the beginning ('$') of the current packet
+ * sum points to the beginning ('#') of the current packet checksum ("#xx")
+ * len is the length of the current packet data (sum - ptr - 1)
+ * end points to the end of the received data buffer
+ */
- while ((ret & packet_last_f) == 0)
+ while ((ptr = memchr(sum, '$', end - sum)) &&
+ (sum = memchr(ptr, '#', end - ptr)) &&
+ (end - sum >= 3) && sscanf(sum, "#%02x", &cksum) == 1)
{
- TRACE("Packet: %s\n", debugstr_an(gdbctx->in_buf, gdbctx->in_len));
- ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
- if (ptr == NULL) return FALSE;
- if (ptr != gdbctx->in_buf)
+ len = sum - ptr - 1;
+ sum += 3;
+
+ if (cksum == checksum(ptr + 1, len))
{
- int glen = ptr - gdbctx->in_buf; /* garbage len */
- WARN("Removing garbage: %s\n", debugstr_an(gdbctx->in_buf, glen));
- gdbctx->in_len -= glen;
- memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
+ TRACE("Acking: %s\n", debugstr_an(ptr, sum - ptr));
+ write(gdbctx->sock, "+", 1);
}
- end = memchr(gdbctx->in_buf + 1, '#', gdbctx->in_len);
- if (end == NULL) return FALSE;
- /* no checksum yet */
- if (end + 3 > gdbctx->in_buf + gdbctx->in_len) return FALSE;
- plen = end - gdbctx->in_buf - 1;
- hex_from(&in_cksum, end + 1, 1);
- loc_cksum = checksum(gdbctx->in_buf + 1, plen);
- if (loc_cksum == in_cksum)
+ else
{
- if (num_packet == 0) {
- int i;
-
- ret = packet_error;
-
- write(gdbctx->sock, "+", 1);
- assert(plen);
-
- /* FIXME: should use bsearch if packet_entries was sorted */
- for (i = 0; i < ARRAY_SIZE(packet_entries); i++)
- {
- if (packet_entries[i].key == gdbctx->in_buf[1]) break;
- }
- if (i == ARRAY_SIZE(packet_entries))
- WARN("Unhandled packet %s\n", debugstr_an(&gdbctx->in_buf[1], plen));
- else
- {
- gdbctx->in_packet = gdbctx->in_buf + 2;
- gdbctx->in_packet_len = plen - 1;
- gdbctx->in_packet[gdbctx->in_packet_len] = '\0';
- ret = (packet_entries[i].handler)(gdbctx);
- }
- switch (ret & ~packet_last_f)
- {
- case packet_error: packet_reply(gdbctx, ""); break;
- case packet_ok: packet_reply(gdbctx, "OK"); break;
- case packet_done: break;
- }
- TRACE("Reply: %s\n", debugstr_an(gdbctx->out_buf, gdbctx->out_len));
- i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
- assert(i == gdbctx->out_len);
- /* if this fails, we'll have to use POLLOUT...
- */
- gdbctx->out_len = 0;
- num_packet++;
- }
- else
+ ERR("Nacking: %s (checksum: %d != %d)\n", debugstr_an(ptr, sum - ptr),
+ cksum, checksum(ptr + 1, len));
+ write(gdbctx->sock, "-", 1);
+ }
+ }
+
+ while ((ret & packet_last_f) == 0 &&
+ (ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len)) &&
+ (sum = memchr(ptr, '#', end - ptr)) &&
+ (end - sum >= 3) && sscanf(sum, "#%02x", &cksum) == 1)
+ {
+ if (ptr != gdbctx->in_buf)
+ WARN("Ignoring: %s\n", debugstr_an(gdbctx->in_buf, ptr - gdbctx->in_buf));
+
+ len = sum - ptr - 1;
+ sum += 3;
+
+ if (cksum == checksum(ptr + 1, len))
+ {
+ TRACE("Handling: %s\n", debugstr_an(ptr, sum - ptr));
+
+ ret = packet_error;
+ gdbctx->in_packet = ptr + 2;
+ gdbctx->in_packet_len = len - 1;
+ gdbctx->in_packet[gdbctx->in_packet_len] = '\0';
+
+ for (i = 0; i < ARRAY_SIZE(packet_entries); i++)
+ if (packet_entries[i].key == ptr[1])
+ break;
+
+ if (i == ARRAY_SIZE(packet_entries))
+ WARN("Unhandled: %s\n", debugstr_an(ptr + 1, len));
+ else if (((ret = (packet_entries[i].handler)(gdbctx)) & ~packet_last_f) == packet_error)
+ WARN("Failed: %s\n", debugstr_an(ptr + 1, len));
+
+ switch (ret & ~packet_last_f)
{
- /* FIXME: If we have more than one packet in our input buffer,
- * it's very likely that we took too long to answer to a given packet
- * and gdb is sending us the same packet again.
- * So we simply drop the second packet. This will lower the risk of error,
- * but there are still some race conditions here.
- * A better fix (yet not perfect) would be to have two threads:
- * - one managing the packets for gdb
- * - the second one managing the commands...
- * This would allow us to send the reply with the '+' character (Ack of
- * the command) way sooner than we do now.
- */
- ERR("Dropping packet; I was too slow to respond\n");
+ case packet_error: packet_reply(gdbctx, ""); break;
+ case packet_ok: packet_reply(gdbctx, "OK"); break;
+ case packet_done: break;
}
+
+ TRACE("Reply: %s\n", debugstr_an(gdbctx->out_buf, gdbctx->out_len));
+ i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
+ assert(i == gdbctx->out_len);
+ gdbctx->out_len = 0;
}
else
- {
- write(gdbctx->sock, "+", 1);
- ERR("Dropping packet; invalid checksum %d <> %d\n", in_cksum, loc_cksum);
- }
- gdbctx->in_len -= plen + 4;
- memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
+ WARN("Ignoring: %s (checksum: %d != %d)\n", debugstr_an(ptr, sum - ptr),
+ cksum, checksum(ptr + 1, len));
+
+ gdbctx->in_len = end - sum;
+ memmove(gdbctx->in_buf, sum, end - sum);
+ end = gdbctx->in_buf + gdbctx->in_len;
}
- return TRUE;
+
+ return (ret & packet_last_f);
}
static int fetch_data(struct gdb_context* gdbctx)
--
2.26.0.rc2
March 31, 2020
[PATCH v2 2/6] winedbg: Force packet data to be NUL terminated.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
programs/winedbg/gdbproxy.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c
index e2954c08dddf..fde6c556c26d 100644
--- a/programs/winedbg/gdbproxy.c
+++ b/programs/winedbg/gdbproxy.c
@@ -1201,7 +1201,6 @@ static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
SIZE_T r = 0;
assert(gdbctx->in_trap);
- /* FIXME:check in_packet_len for reading %p,%x */
if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
if (len <= 0) return packet_error;
TRACE("Read %u bytes at %p\n", len, addr);
@@ -1794,6 +1793,7 @@ static BOOL extract_packets(struct gdb_context* gdbctx)
{
gdbctx->in_packet = gdbctx->in_buf + 2;
gdbctx->in_packet_len = plen - 1;
+ gdbctx->in_packet[gdbctx->in_packet_len] = '\0';
ret = (packet_entries[i].handler)(gdbctx);
}
switch (ret & ~packet_last_f)
--
2.26.0.rc2
March 31, 2020
[PATCH v2 1/6] winedbg: Force read data to be NUL terminated.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
programs/winedbg/gdbproxy.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c
index 052e73b2ad69..e2954c08dddf 100644
--- a/programs/winedbg/gdbproxy.c
+++ b/programs/winedbg/gdbproxy.c
@@ -1848,12 +1848,14 @@ static int fetch_data(struct gdb_context* gdbctx)
if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
#undef STEP
- len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
+ len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len - 1);
if (len <= 0) break;
gdbctx->in_len += len;
assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
}
+
+ gdbctx->in_buf[gdbctx->in_len] = '\0';
return gdbctx->in_len - in_len;
}
--
2.26.0.rc2
March 31, 2020