From fc9560f4b97a91d5a096cbbc5822d2f4a90aa3eb Mon Sep 17 00:00:00 2001 From: William Horvath Date: Mon, 1 Jul 2024 20:09:18 -0700 Subject: [PATCH] 9.12-2 patchset regular update and rebase --- ...ault-implementation-for-wglChoosePix.patch | 119 +++- ...river-wglChoosePixelFormatARB-implem.patch | 2 +- ...wayland-Support-WGL_ARB_pixel_format.patch | 2 +- ...d-Support-WGL_ARB_pixel_format_float.patch | 2 +- ...-ntdll-Optimize-NtQueryVirtualMemory.patch | 614 ------------------ ...le-desktop-window-message-queue-hang.patch | 60 ++ ...server-ntdll-Implement-message-waits.patch | 19 + ...ow-disabling-child-window-rendering.patch} | 0 ...1-HACK-Disable-more-window-clipping.patch} | 0 ...-HACK-Avoid-onscreen-stencil-buffer.patch} | 0 staging-commit | 2 +- wine-commit | 2 +- 12 files changed, 167 insertions(+), 655 deletions(-) delete mode 100644 0003-pending-mrs-and-backports/9999-misc-loose/0008-ps5907-ntdll-Optimize-NtQueryVirtualMemory.patch create mode 100644 0003-pending-mrs-and-backports/9999-misc-loose/0010-ps5890-winex11-Fix-a-possible-desktop-window-message-queue-hang.patch create mode 100644 0007-proton-fsync/1000-fixup-server-ntdll-Implement-message-waits.patch rename 0010-renderer/{0001-winex11-Allow-disabling-child-window-rendering.patch => 0001-winex11-HACK-Allow-disabling-child-window-rendering.patch} (100%) rename 0010-renderer/{0002-winex11-Remove-more-clipping-if-envvar-set.patch => 0002-winex11-HACK-Disable-more-window-clipping.patch} (100%) rename 0010-renderer/{0003-winex11-Avoid-onscreen-stencil-buffer-if-envvar-set.patch => 0003-winex11-HACK-Avoid-onscreen-stencil-buffer.patch} (100%) diff --git a/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0001-opengl32-Add-default-implementation-for-wglChoosePix.patch b/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0001-opengl32-Add-default-implementation-for-wglChoosePix.patch index db1d9be..ede74f1 100644 --- a/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0001-opengl32-Add-default-implementation-for-wglChoosePix.patch +++ b/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0001-opengl32-Add-default-implementation-for-wglChoosePix.patch @@ -1,4 +1,4 @@ -From 2a4775fb1dfc95103d33a17755da74d6e08d07cb Mon Sep 17 00:00:00 2001 +From f6504047c53e28783f1f5515d69cae5cc41314cf Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Tue, 25 Jun 2024 13:45:02 +0300 Subject: [PATCH 1/4] opengl32: Add default implementation for @@ -9,8 +9,8 @@ populates the wgl_pixel_format ARB fields. --- dlls/opengl32/make_opengl | 1 + dlls/opengl32/thunks.c | 10 +- - dlls/opengl32/wgl.c | 243 ++++++++++++++++++++++++++++++++++++++ - 3 files changed, 245 insertions(+), 9 deletions(-) + dlls/opengl32/wgl.c | 283 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 285 insertions(+), 9 deletions(-) diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 771793b9049..54873150da3 100755 @@ -53,15 +53,24 @@ index 3ee1776daef..ccabbbc7519 100644 extern const char * WINAPI wglGetExtensionsStringARB( HDC hdc ); extern const char * WINAPI wglGetExtensionsStringEXT(void); diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c -index 2ae79a56f9e..c4cdf941fc5 100644 +index 2ae79a56f9e..19d989e44fc 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c -@@ -492,6 +492,249 @@ static BOOL wgl_pixel_format_get_attrib( const struct wgl_pixel_format *fmt, int +@@ -18,6 +18,7 @@ + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + ++#include + #include + #include + #include +@@ -492,6 +493,288 @@ static BOOL wgl_pixel_format_get_attrib( const struct wgl_pixel_format *fmt, int return valid; } +enum attrib_match +{ ++ ATTRIB_MATCH_INVALID = -1, + ATTRIB_MATCH_IGNORE, + ATTRIB_MATCH_EXACT, + ATTRIB_MATCH_MINIMUM, @@ -111,8 +120,20 @@ index 2ae79a56f9e..c4cdf941fc5 100644 + case WGL_SAMPLE_BUFFERS_ARB: + case WGL_SAMPLES_ARB: + return ATTRIB_MATCH_MINIMUM; -+ default: ++ case WGL_NUMBER_PIXEL_FORMATS_ARB: ++ case WGL_RED_SHIFT_ARB: ++ case WGL_GREEN_SHIFT_ARB: ++ case WGL_BLUE_SHIFT_ARB: ++ case WGL_ALPHA_SHIFT_ARB: ++ case WGL_TRANSPARENT_ARB: ++ case WGL_TRANSPARENT_RED_VALUE_ARB: ++ case WGL_TRANSPARENT_GREEN_VALUE_ARB: ++ case WGL_TRANSPARENT_BLUE_VALUE_ARB: ++ case WGL_TRANSPARENT_ALPHA_VALUE_ARB: ++ case WGL_TRANSPARENT_INDEX_VALUE_ARB: + return ATTRIB_MATCH_IGNORE; ++ default: ++ return ATTRIB_MATCH_INVALID; + } +} + @@ -123,6 +144,8 @@ index 2ae79a56f9e..c4cdf941fc5 100644 + int fmt_value; + UINT i; + ++ assert(match != ATTRIB_MATCH_INVALID); ++ + if (match == ATTRIB_MATCH_IGNORE) return; + + for (i = 0; i < num_formats; ++i) @@ -145,12 +168,12 @@ index 2ae79a56f9e..c4cdf941fc5 100644 + case WGL_DRAW_TO_BITMAP_ARB: return 2; + case WGL_ACCELERATION_ARB: return 3; + case WGL_COLOR_BITS_ARB: return 4; -+ case WGL_PIXEL_TYPE_ARB: return 5; -+ case WGL_ALPHA_BITS_ARB: return 6; -+ case WGL_AUX_BUFFERS_ARB: return 7; -+ case WGL_DEPTH_BITS_ARB: return 8; -+ case WGL_STENCIL_BITS_ARB: return 9; -+ case WGL_ACCUM_BITS_ARB: return 10; ++ case WGL_ACCUM_BITS_ARB: return 5; ++ case WGL_PIXEL_TYPE_ARB: return 6; ++ case WGL_ALPHA_BITS_ARB: return 7; ++ case WGL_AUX_BUFFERS_ARB: return 8; ++ case WGL_DEPTH_BITS_ARB: return 9; ++ case WGL_STENCIL_BITS_ARB: return 10; + case WGL_DOUBLE_BUFFER_ARB: return 11; + case WGL_SWAP_METHOD_ARB: return 12; + default: return 100; @@ -159,12 +182,7 @@ index 2ae79a56f9e..c4cdf941fc5 100644 + +static int compare_attribs( const void *a, const void *b ) +{ -+ int prio_a = wgl_attrib_sort_priority( *(int *)a ); -+ int prio_b = wgl_attrib_sort_priority( *(int *)b ); -+ -+ if (prio_a == prio_b) return 0; -+ else if (prio_a < prio_b) return -1; -+ else return 1; ++ return wgl_attrib_sort_priority( *(int *)a ) - wgl_attrib_sort_priority( *(int *)b ); +} + +static int wgl_attrib_value_priority( int value ) @@ -190,7 +208,7 @@ index 2ae79a56f9e..c4cdf941fc5 100644 + +struct compare_formats_ctx +{ -+ int attribs[128]; ++ int attribs[256]; + UINT num_attribs; +}; + @@ -198,7 +216,7 @@ index 2ae79a56f9e..c4cdf941fc5 100644 +{ + const struct wgl_pixel_format *fmt_a = *(void **)a, *fmt_b = *(void **)b; + struct compare_formats_ctx *ctx = arg; -+ int val_a, val_b; ++ int attrib, val_a, val_b; + UINT i; + + if (!fmt_a) return 1; @@ -206,17 +224,22 @@ index 2ae79a56f9e..c4cdf941fc5 100644 + + for (i = 0; i < ctx->num_attribs; ++i) + { -+ if (wgl_pixel_format_get_attrib( fmt_a, ctx->attribs[i], &val_a ) && -+ wgl_pixel_format_get_attrib( fmt_b, ctx->attribs[i], &val_b ) && ++ attrib = ctx->attribs[2 * i]; ++ if (wgl_pixel_format_get_attrib( fmt_a, attrib, &val_a ) && ++ wgl_pixel_format_get_attrib( fmt_b, attrib, &val_b ) && + val_a != val_b) + { -+ switch (ctx->attribs[i]) ++ switch (attrib) + { + case WGL_ACCELERATION_ARB: + case WGL_SWAP_METHOD_ARB: + case WGL_PIXEL_TYPE_ARB: + return wgl_attrib_value_priority( val_a ) - + wgl_attrib_value_priority( val_b ); ++ case WGL_COLOR_BITS_ARB: ++ /* Prefer 32bpp over other values */ ++ if (val_a >= 32 && val_b >= 32) return val_a - val_b; ++ else return val_b - val_a; + default: + /* Smaller values first */ + return val_a - val_b; @@ -228,6 +251,22 @@ index 2ae79a56f9e..c4cdf941fc5 100644 + return fmt_a - fmt_b; +} + ++static void compare_formats_ctx_set_attrib( struct compare_formats_ctx *ctx, ++ int attrib, int value ) ++{ ++ UINT i; ++ ++ /* Overwrite attribute if it exists already */ ++ for (i = 0; i < ctx->num_attribs; ++i) ++ if (ctx->attribs[2 * i] == attrib) break; ++ ++ assert(i < ARRAY_SIZE(ctx->attribs) / 2); ++ ++ ctx->attribs[2 * i] = attrib; ++ ctx->attribs[2 * i + 1] = value; ++ if (i == ctx->num_attribs) ++ctx->num_attribs; ++} ++ +/*********************************************************************** + * wglChoosePixelFormatARB (OPENGL32.@) + */ @@ -266,27 +305,35 @@ index 2ae79a56f9e..c4cdf941fc5 100644 + return args.ret; + } + -+ /* Initialize the format_array with (pointers to) all wgl formats */ -+ format_array = malloc( num_wgl_formats * sizeof(*format_array) ); -+ if (!format_array) return FALSE; -+ for (i = 0; i < num_wgl_formats; ++i) format_array[i] = &wgl_formats[i]; -+ -+ /* Remove formats that are not acceptable */ ++ /* Gather, validate and deduplicate all attributes */ + for (i = 0; attribs_int && attribs_int[i]; i += 2) + { -+ if (ctx.num_attribs == ARRAY_SIZE(ctx.attribs)) { free( format_array ); return FALSE; } -+ else ctx.attribs[ctx.num_attribs++] = attribs_int[i]; -+ filter_format_array( format_array, num_wgl_formats, attribs_int[i], attribs_int[i + 1] ); ++ if (wgl_attrib_match_criteria( attribs_int[i] ) == ATTRIB_MATCH_INVALID) return FALSE; ++ compare_formats_ctx_set_attrib( &ctx, attribs_int[i], attribs_int[i + 1] ); + } + for (i = 0; attribs_float && attribs_float[i]; i += 2) + { -+ if (ctx.num_attribs == ARRAY_SIZE(ctx.attribs)) { free( format_array ); return FALSE; } -+ else ctx.attribs[ctx.num_attribs++] = attribs_float[i]; -+ filter_format_array( format_array, num_wgl_formats, attribs_float[i], attribs_float[i + 1] ); ++ if (wgl_attrib_match_criteria( attribs_float[i] ) == ATTRIB_MATCH_INVALID) return FALSE; ++ compare_formats_ctx_set_attrib( &ctx, attribs_float[i], attribs_float[i + 1] ); + } + ++ /* Initialize the format_array with (pointers to) all wgl formats */ ++ format_array = malloc( num_wgl_formats * sizeof(*format_array) ); ++ if (!format_array) return FALSE; ++ for (i = 0; i < num_wgl_formats; ++i) format_array[i] = &wgl_formats[i]; ++ ++ /* Remove formats that are not acceptable */ ++ for (i = 0; i < ctx.num_attribs; ++i) ++ filter_format_array( format_array, num_wgl_formats, ctx.attribs[2 * i], ++ ctx.attribs[2 * i + 1] ); ++ ++ /* Some attributes we always want to sort by (values don't matter for sorting) */ ++ compare_formats_ctx_set_attrib( &ctx, WGL_ACCELERATION_ARB, 0 ); ++ compare_formats_ctx_set_attrib( &ctx, WGL_COLOR_BITS_ARB, 0 ); ++ compare_formats_ctx_set_attrib( &ctx, WGL_ACCUM_BITS_ARB, 0 ); ++ + /* Arrange attributes in the order which we want to check them */ -+ qsort( ctx.attribs, ctx.num_attribs, sizeof(*ctx.attribs), compare_attribs ); ++ qsort( ctx.attribs, ctx.num_attribs, 2 * sizeof(*ctx.attribs), compare_attribs ); + + /* Sort pixel formats based on the specified attributes */ + qsort_s( format_array, num_wgl_formats, sizeof(*format_array), compare_formats, &ctx ); diff --git a/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0002-winex11-Remove-driver-wglChoosePixelFormatARB-implem.patch b/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0002-winex11-Remove-driver-wglChoosePixelFormatARB-implem.patch index 446051c..177077c 100644 --- a/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0002-winex11-Remove-driver-wglChoosePixelFormatARB-implem.patch +++ b/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0002-winex11-Remove-driver-wglChoosePixelFormatARB-implem.patch @@ -1,4 +1,4 @@ -From b71d250f5142f645b4da4f32be5f24fc7e0004fa Mon Sep 17 00:00:00 2001 +From 8cd89f75fd2c02f734c9dde99d2f77d243065f27 Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Tue, 25 Jun 2024 13:59:38 +0300 Subject: [PATCH 2/4] winex11: Remove driver wglChoosePixelFormatARB diff --git a/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0003-winewayland-Support-WGL_ARB_pixel_format.patch b/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0003-winewayland-Support-WGL_ARB_pixel_format.patch index 58cb0c2..76ecbf3 100644 --- a/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0003-winewayland-Support-WGL_ARB_pixel_format.patch +++ b/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0003-winewayland-Support-WGL_ARB_pixel_format.patch @@ -1,4 +1,4 @@ -From 3913807d8cb143481bd7d5f809cf6da741762225 Mon Sep 17 00:00:00 2001 +From a05b4b0186f51d9151c0fa578495e01835f1d787 Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Wed, 26 Jun 2024 10:49:58 +0300 Subject: [PATCH 3/4] winewayland: Support WGL_ARB_pixel_format. diff --git a/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0004-winewayland-Support-WGL_ARB_pixel_format_float.patch b/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0004-winewayland-Support-WGL_ARB_pixel_format_float.patch index 274a469..e1a0321 100644 --- a/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0004-winewayland-Support-WGL_ARB_pixel_format_float.patch +++ b/0003-pending-mrs-and-backports/5933-opengl32-wglChoosePixelFormatARB/0004-winewayland-Support-WGL_ARB_pixel_format_float.patch @@ -1,4 +1,4 @@ -From 53e08c7938cec9e6899c8b820e3dbda8a274dea8 Mon Sep 17 00:00:00 2001 +From 1915484054e818e43c72dcf3bab67794ab4370f1 Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Wed, 26 Jun 2024 10:55:16 +0300 Subject: [PATCH 4/4] winewayland: Support WGL_ARB_pixel_format_float. diff --git a/0003-pending-mrs-and-backports/9999-misc-loose/0008-ps5907-ntdll-Optimize-NtQueryVirtualMemory.patch b/0003-pending-mrs-and-backports/9999-misc-loose/0008-ps5907-ntdll-Optimize-NtQueryVirtualMemory.patch deleted file mode 100644 index e6eb85e..0000000 --- a/0003-pending-mrs-and-backports/9999-misc-loose/0008-ps5907-ntdll-Optimize-NtQueryVirtualMemory.patch +++ /dev/null @@ -1,614 +0,0 @@ -From 6bc79d11fb5da5da434139cff6e152ae05313fc2 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Fri, 21 Jun 2024 17:14:21 -0600 -Subject: [PATCH 1/7] psapi/tests: Add tests for QueryWorkingSetEx() with - multiple addresses. - ---- - dlls/psapi/tests/psapi_main.c | 85 +++++++++++++++++++++++++---------- - 1 file changed, 61 insertions(+), 24 deletions(-) - -diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c -index e7e5e5f04e6..515364f156d 100644 ---- a/dlls/psapi/tests/psapi_main.c -+++ b/dlls/psapi/tests/psapi_main.c -@@ -1150,6 +1150,32 @@ free_page: - VirtualFree(addr, 0, MEM_RELEASE); - } - -+static void check_working_set_info(PSAPI_WORKING_SET_EX_INFORMATION *info, const char *desc, DWORD expected_valid, -+ DWORD expected_protection, DWORD expected_shared, BOOL todo) -+{ -+ todo_wine_if(todo) -+ ok(info->VirtualAttributes.Valid == expected_valid, "%s expected Valid=%lu but got %u\n", -+ desc, expected_valid, info->VirtualAttributes.Valid); -+ -+ todo_wine_if(todo) -+ ok(info->VirtualAttributes.Win32Protection == expected_protection, "%s expected Win32Protection=%lu but got %u\n", -+ desc, expected_protection, info->VirtualAttributes.Win32Protection); -+ -+ ok(info->VirtualAttributes.Node == 0, "%s expected Node=0 but got %u\n", -+ desc, info->VirtualAttributes.Node); -+ ok(info->VirtualAttributes.LargePage == 0, "%s expected LargePage=0 but got %u\n", -+ desc, info->VirtualAttributes.LargePage); -+ -+ ok(info->VirtualAttributes.Shared == expected_shared || broken(!info->VirtualAttributes.Valid) /* w2003 */, -+ "%s expected Shared=%lu but got %u\n", desc, expected_shared, info->VirtualAttributes.Shared); -+ if (info->VirtualAttributes.Valid && info->VirtualAttributes.Shared) -+ ok(info->VirtualAttributes.ShareCount > 0, "%s expected ShareCount > 0 but got %u\n", -+ desc, info->VirtualAttributes.ShareCount); -+ else -+ ok(info->VirtualAttributes.ShareCount == 0, "%s expected ShareCount == 0 but got %u\n", -+ desc, info->VirtualAttributes.ShareCount); -+} -+ - static void check_QueryWorkingSetEx(PVOID addr, const char *desc, DWORD expected_valid, - DWORD expected_protection, DWORD expected_shared, BOOL todo) - { -@@ -1161,32 +1187,13 @@ static void check_QueryWorkingSetEx(PVOID addr, const char *desc, DWORD expected - ret = pQueryWorkingSetEx(GetCurrentProcess(), &info, sizeof(info)); - ok(ret, "QueryWorkingSetEx failed with %ld\n", GetLastError()); - -- todo_wine_if(todo) -- ok(info.VirtualAttributes.Valid == expected_valid, "%s expected Valid=%lu but got %u\n", -- desc, expected_valid, info.VirtualAttributes.Valid); -- -- todo_wine_if(todo) -- ok(info.VirtualAttributes.Win32Protection == expected_protection, "%s expected Win32Protection=%lu but got %u\n", -- desc, expected_protection, info.VirtualAttributes.Win32Protection); -- -- ok(info.VirtualAttributes.Node == 0, "%s expected Node=0 but got %u\n", -- desc, info.VirtualAttributes.Node); -- ok(info.VirtualAttributes.LargePage == 0, "%s expected LargePage=0 but got %u\n", -- desc, info.VirtualAttributes.LargePage); -- -- ok(info.VirtualAttributes.Shared == expected_shared || broken(!info.VirtualAttributes.Valid) /* w2003 */, -- "%s expected Shared=%lu but got %u\n", desc, expected_shared, info.VirtualAttributes.Shared); -- if (info.VirtualAttributes.Valid && info.VirtualAttributes.Shared) -- ok(info.VirtualAttributes.ShareCount > 0, "%s expected ShareCount > 0 but got %u\n", -- desc, info.VirtualAttributes.ShareCount); -- else -- ok(info.VirtualAttributes.ShareCount == 0, "%s expected ShareCount == 0 but got %u\n", -- desc, info.VirtualAttributes.ShareCount); -+ check_working_set_info(&info, desc, expected_valid, expected_protection, expected_shared, todo); - } - - static void test_QueryWorkingSetEx(void) - { -- PVOID addr; -+ PSAPI_WORKING_SET_EX_INFORMATION info[4]; -+ char *addr, *addr2; - DWORD prot; - BOOL ret; - -@@ -1196,7 +1203,7 @@ static void test_QueryWorkingSetEx(void) - return; - } - -- addr = GetModuleHandleA(NULL); -+ addr = (void *)GetModuleHandleA(NULL); - check_QueryWorkingSetEx(addr, "exe", 1, PAGE_READONLY, 1, FALSE); - - ret = VirtualProtect(addr, 0x1000, PAGE_NOACCESS, &prot); -@@ -1211,7 +1218,7 @@ static void test_QueryWorkingSetEx(void) - ok(ret, "VirtualProtect failed with %ld\n", GetLastError()); - check_QueryWorkingSetEx(addr, "exe,readonly2", 1, PAGE_READONLY, 1, FALSE); - -- addr = VirtualAlloc(NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); -+ addr = VirtualAlloc(NULL, 0x2000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - ok(addr != NULL, "VirtualAlloc failed with %ld\n", GetLastError()); - check_QueryWorkingSetEx(addr, "valloc", 0, 0, 0, FALSE); - -@@ -1232,9 +1239,39 @@ static void test_QueryWorkingSetEx(void) - *(volatile char *)addr; - check_QueryWorkingSetEx(addr, "valloc,readwrite2", 1, PAGE_READWRITE, 0, FALSE); - -+ addr2 = VirtualAlloc(NULL, 0x2000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); -+ ok(!!addr2, "VirtualAlloc failed with %ld\n", GetLastError()); -+ *(addr2 + 0x1000) = 1; -+ -+ info[1].VirtualAddress = addr; -+ info[0].VirtualAddress = addr + 0x1000; -+ info[3].VirtualAddress = addr2; -+ info[2].VirtualAddress = addr2 + 0x1000; -+ ret = pQueryWorkingSetEx(GetCurrentProcess(), info, sizeof(info)); -+ ok(ret, "got error %lu\n", GetLastError()); -+ check_working_set_info(&info[1], "[1] range[1] valid", 1, PAGE_READWRITE, 0, FALSE); -+ check_working_set_info(&info[0], "[1] range[0] invalid", 0, 0, 0, FALSE); -+ check_working_set_info(&info[3], "[1] range[3] invalid", 0, 0, 0, FALSE); -+ check_working_set_info(&info[2], "[1] range[2] valid", 1, PAGE_READWRITE, 0, FALSE); -+ - ret = VirtualFree(addr, 0, MEM_RELEASE); - ok(ret, "VirtualFree failed with %ld\n", GetLastError()); - check_QueryWorkingSetEx(addr, "valloc,free", FALSE, 0, 0, FALSE); -+ -+ ret = pQueryWorkingSetEx(GetCurrentProcess(), info, sizeof(info)); -+ ok(ret, "got error %lu\n", GetLastError()); -+ check_working_set_info(&info[1], "[2] range[1] invalid", 0, 0, 0, FALSE); -+ check_working_set_info(&info[0], "[2] range[0] invalid", 0, 0, 0, FALSE); -+ check_working_set_info(&info[3], "[2] range[3] invalid", 0, 0, 0, FALSE); -+ check_working_set_info(&info[2], "[2] range[2] valid", 1, PAGE_READWRITE, 0, FALSE); -+ -+ VirtualFree(addr2, 0, MEM_RELEASE); -+ ret = pQueryWorkingSetEx(GetCurrentProcess(), info, sizeof(info)); -+ ok(ret, "got error %lu\n", GetLastError()); -+ check_working_set_info(&info[1], "[3] range[1] invalid", 0, 0, 0, FALSE); -+ check_working_set_info(&info[0], "[3] range[0] invalid", 0, 0, 0, FALSE); -+ check_working_set_info(&info[3], "[3] range[3] invalid", 0, 0, 0, FALSE); -+ check_working_set_info(&info[2], "[3] range[2] invalid", 0, 0, 0, FALSE); - } - - START_TEST(psapi_main) --- -GitLab - - -From 8c848e5627b6fd14a218cfccd5d1e3466e24fbf7 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Fri, 21 Jun 2024 16:42:44 -0600 -Subject: [PATCH 2/7] ntdll: Validate length in get_working_set_ex(). - ---- - dlls/ntdll/unix/virtual.c | 4 +++- - dlls/psapi/tests/psapi_main.c | 21 +++++++++++++++++++++ - 2 files changed, 24 insertions(+), 1 deletion(-) - -## -diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c -index 515364f156d..92529447afa 100644 ---- a/dlls/psapi/tests/psapi_main.c -+++ b/dlls/psapi/tests/psapi_main.c -@@ -1194,6 +1194,8 @@ static void test_QueryWorkingSetEx(void) - { - PSAPI_WORKING_SET_EX_INFORMATION info[4]; - char *addr, *addr2; -+ NTSTATUS status; -+ SIZE_T size; - DWORD prot; - BOOL ret; - -@@ -1203,6 +1205,25 @@ static void test_QueryWorkingSetEx(void) - return; - } - -+ size = 0xdeadbeef; -+ memset(info, 0, sizeof(info)); -+ status = pNtQueryVirtualMemory(GetCurrentProcess(), NULL, MemoryWorkingSetExInformation, info, 0, &size); -+ ok(status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx.\n", status); -+ ok(size == 0xdeadbeef, "got %Iu.\n", size); -+ -+ memset(&info, 0, sizeof(info)); -+ ret = pQueryWorkingSetEx(GetCurrentProcess(), info, 0); -+ ok(!ret && GetLastError() == ERROR_BAD_LENGTH, "got ret %d, err %lu.\n", ret, GetLastError()); -+ -+ size = 0xdeadbeef; -+ memset(info, 0, sizeof(info)); -+ status = pNtQueryVirtualMemory(GetCurrentProcess(), NULL, MemoryWorkingSetExInformation, info, -+ sizeof(*info) + sizeof(*info) / 2, &size); -+ ok(!status, "got %#lx.\n", status); -+ ok(!info->VirtualAttributes.Valid, "got %d.\n", info->VirtualAttributes.Valid); -+ ok(size == sizeof(*info) /* wow64 */ || size == sizeof(*info) + sizeof(*info) / 2 /* win64 */, -+ "got %Iu, sizeof(info) %Iu.\n", size, sizeof(info)); -+ - addr = (void *)GetModuleHandleA(NULL); - check_QueryWorkingSetEx(addr, "exe", 1, PAGE_READONLY, 1, FALSE); - --- -GitLab - - -From 40b2532bf617bb5f4b21b4530882110c297a5080 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Wed, 19 Jun 2024 18:49:12 -0600 -Subject: [PATCH 3/7] ntdll: Factor OS-specific parts out of - get_working_set_ex(). - ---- - dlls/ntdll/unix/virtual.c | 202 +++++++++++++++++++++----------------- - 1 file changed, 111 insertions(+), 91 deletions(-) -## -From c40633a1d95d7d452826585e66a7cd6aac11979a Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Wed, 19 Jun 2024 20:38:40 -0600 -Subject: [PATCH 4/7] ntdll: Iterate views instead of requested addresses in - get_working_set_ex(). - ---- - dlls/ntdll/unix/virtual.c | 71 ++++++++++++++++++++++++++++++++++----- - 1 file changed, 63 insertions(+), 8 deletions(-) -## -From 3d062b74ac2426b1701000a4761288402c8ee3d7 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 20 Jun 2024 14:31:07 -0600 -Subject: [PATCH 5/7] ntdll: Limit vprot scan range to the needed interval in - get_working_set_ex(). - ---- - dlls/ntdll/unix/virtual.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) -## -From 8fe090debe7638b70054d26d9ecee161af8caee0 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 20 Jun 2024 14:47:53 -0600 -Subject: [PATCH 6/7] ntdll: Fill range of output in fill_working_set_info(). - ---- - dlls/ntdll/unix/virtual.c | 78 +++++++++++++++++++++++---------------- - 1 file changed, 46 insertions(+), 32 deletions(-) -## -From 02680a1f263c054e4fb51f21d963e96d1233d891 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 20 Jun 2024 15:43:15 -0600 -Subject: [PATCH 7/7] ntdll: Buffer pagemap reads in fill_working_set_info(). - ---- - dlls/ntdll/unix/virtual.c | 38 ++++++++++++++++++++++++++++++-------- - 1 file changed, 30 insertions(+), 8 deletions(-) -## - -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index bfb9270dae2..fff39bf3f00 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -2202,7 +2202,7 @@ done: - * Get the size of the committed range with equal masked vprot bytes starting at base. - * Also return the protections for the first page. - */ --static SIZE_T get_committed_size( struct file_view *view, void *base, BYTE *vprot, BYTE vprot_mask ) -+static SIZE_T get_committed_size( struct file_view *view, void *base, size_t max_size, BYTE *vprot, BYTE vprot_mask ) - { - SIZE_T offset, size; - -@@ -2221,7 +2221,7 @@ static SIZE_T get_committed_size( struct file_view *view, void *base, BYTE *vpro - req->offset = offset; - if (!wine_server_call( req )) - { -- size = reply->size; -+ size = min( reply->size, max_size ); - if (reply->committed) - { - *vprot |= VPROT_COMMITTED; -@@ -2233,7 +2233,7 @@ static SIZE_T get_committed_size( struct file_view *view, void *base, BYTE *vpro - - if (!size || !(vprot_mask & ~VPROT_COMMITTED)) return size; - } -- else size = view->size - offset; -+ else size = min( view->size - offset, max_size ); - - return get_vprot_range_size( base, size, vprot_mask, vprot ); - } -@@ -5014,7 +5014,7 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T - if ((view = find_view( base, size ))) - { - /* Make sure all the pages are committed */ -- if (get_committed_size( view, base, &vprot, VPROT_COMMITTED ) >= size && (vprot & VPROT_COMMITTED)) -+ if (get_committed_size( view, base, ~(size_t)0, &vprot, VPROT_COMMITTED ) >= size && (vprot & VPROT_COMMITTED)) - { - old = get_win32_prot( vprot, view->protect ); - status = set_protection( view, base, size, new_prot ); -@@ -5136,7 +5136,7 @@ static unsigned int fill_basic_memory_info( const void *addr, MEMORY_BASIC_INFOR - BYTE vprot; - - info->AllocationBase = alloc_base; -- info->RegionSize = get_committed_size( view, base, &vprot, ~VPROT_WRITEWATCH ); -+ info->RegionSize = get_committed_size( view, base, ~(size_t)0, &vprot, ~VPROT_WRITEWATCH ); - info->State = (vprot & VPROT_COMMITTED) ? MEM_COMMIT : MEM_RESERVE; - info->Protect = (vprot & VPROT_COMMITTED) ? get_win32_prot( vprot, view->protect ) : 0; - info->AllocationProtect = get_win32_prot( view->protect, view->protect ); -@@ -5222,15 +5222,171 @@ static unsigned int get_memory_region_info( HANDLE process, LPCVOID addr, MEMORY - return STATUS_SUCCESS; - } - -+struct working_set_info_ref -+{ -+ char *addr; -+ SIZE_T orig_index; -+}; -+ -+#if defined(HAVE_LIBPROCSTAT) -+struct fill_working_set_info_data -+{ -+ struct procstat *pstat; -+ struct kinfo_proc *kip; -+ unsigned int vmentry_count; -+ struct kinfo_vmentry *vmentries; -+}; -+ -+static void init_fill_working_set_info_data( struct fill_working_set_info_data *d, char *end ) -+{ -+ unsigned int proc_count; -+ -+ d->kip = NULL; -+ d->vmentry_count = 0; -+ d->vmentries = NULL; -+ -+ if ((d->pstat = procstat_open_sysctl())) -+ d->kip = procstat_getprocs( d->pstat, KERN_PROC_PID, getpid(), &proc_count ); -+ if (d->kip) -+ d->vmentries = procstat_getvmmap( d->pstat, d->kip, &d->vmentry_count ); -+ if (!d->vmentries) -+ WARN( "couldn't get process vmmap, errno %d\n", errno ); -+} -+ -+static void free_fill_working_set_info_data( struct fill_working_set_info_data *d ) -+{ -+ if (d->vmentries) -+ procstat_freevmmap( d->pstat, d->vmentries ); -+ if (d->kip) -+ procstat_freeprocs( d->pstat, d->kip ); -+ if (d->pstat) -+ procstat_close( d->pstat ); -+} -+ -+static void fill_working_set_info( struct fill_working_set_info_data *d, struct file_view *view, BYTE vprot, -+ struct working_set_info_ref *ref, SIZE_T count, -+ MEMORY_WORKING_SET_EX_INFORMATION *info ) -+{ -+ SIZE_T i; -+ int j; -+ -+ for (i = 0; i < count; ++i) -+ { -+ MEMORY_WORKING_SET_EX_INFORMATION *p = &info[ref[i].orig_index]; -+ struct kinfo_vmentry *entry = NULL; -+ -+ for (j = 0; j < d->vmentry_count; j++) -+ { -+ if (d->vmentries[j].kve_start <= (ULONG_PTR)p->VirtualAddress && (ULONG_PTR)p->VirtualAddress <= d->vmentries[j].kve_end) -+ { -+ entry = &d->vmentries[j]; -+ break; -+ } -+ } -+ -+ p->VirtualAttributes.Valid = !(vprot & VPROT_GUARD) && (vprot & 0x0f) && entry && entry->kve_type != KVME_TYPE_SWAP; -+ p->VirtualAttributes.Shared = !is_view_valloc( view ); -+ if (p->VirtualAttributes.Shared && p->VirtualAttributes.Valid) -+ p->VirtualAttributes.ShareCount = 1; /* FIXME */ -+ if (p->VirtualAttributes.Valid) -+ p->VirtualAttributes.Win32Protection = get_win32_prot( vprot, view->protect ); -+ } -+} -+#else -+static int pagemap_fd = -2; -+ -+struct fill_working_set_info_data -+{ -+ UINT64 pm_buffer[256]; -+ SIZE_T buffer_start; -+ ssize_t buffer_len; -+ SIZE_T end_page; -+}; -+ -+static void init_fill_working_set_info_data( struct fill_working_set_info_data *d, char *end ) -+{ -+ d->buffer_start = 0; -+ d->buffer_len = 0; -+ d->end_page = (UINT_PTR)end >> page_shift; -+ memset( d->pm_buffer, 0, sizeof(d->pm_buffer) ); -+ -+ if (pagemap_fd != -2) return; -+ -+#ifdef O_CLOEXEC -+ if ((pagemap_fd = open( "/proc/self/pagemap", O_RDONLY | O_CLOEXEC, 0 )) == -1 && errno == EINVAL) -+#endif -+ pagemap_fd = open( "/proc/self/pagemap", O_RDONLY, 0 ); -+ -+ if (pagemap_fd == -1) WARN( "unable to open /proc/self/pagemap\n" ); -+ else fcntl(pagemap_fd, F_SETFD, FD_CLOEXEC); /* in case O_CLOEXEC isn't supported */ -+} -+ -+static void free_fill_working_set_info_data( struct fill_working_set_info_data *d ) -+{ -+} -+ -+static void fill_working_set_info( struct fill_working_set_info_data *d, struct file_view *view, BYTE vprot, -+ struct working_set_info_ref *ref, SIZE_T count, -+ MEMORY_WORKING_SET_EX_INFORMATION *info ) -+{ -+ MEMORY_WORKING_SET_EX_INFORMATION *p; -+ UINT64 pagemap; -+ SIZE_T i, page; -+ ssize_t len; -+ -+ for (i = 0; i < count; ++i) -+ { -+ page = (UINT_PTR)ref[i].addr >> page_shift; -+ p = &info[ref[i].orig_index]; -+ -+ assert(page >= d->buffer_start); -+ if (page >= d->buffer_start + d->buffer_len) -+ { -+ d->buffer_start = page; -+ len = min( sizeof(d->pm_buffer), (d->end_page - page) * sizeof(pagemap) ); -+ if (pagemap_fd != -1) -+ { -+ d->buffer_len = pread( pagemap_fd, d->pm_buffer, len, page * sizeof(pagemap) ); -+ if (d->buffer_len != len) -+ { -+ d->buffer_len = max( d->buffer_len, 0 ); -+ memset( d->pm_buffer + d->buffer_len / sizeof(pagemap), 0, len - d->buffer_len ); -+ } -+ } -+ d->buffer_len = len / sizeof(pagemap); -+ } -+ pagemap = d->pm_buffer[page - d->buffer_start]; -+ -+ p->VirtualAttributes.Valid = !(vprot & VPROT_GUARD) && (vprot & 0x0f) && (pagemap >> 63); -+ p->VirtualAttributes.Shared = !is_view_valloc( view ) && ((pagemap >> 61) & 1); -+ if (p->VirtualAttributes.Shared && p->VirtualAttributes.Valid) -+ p->VirtualAttributes.ShareCount = 1; /* FIXME */ -+ if (p->VirtualAttributes.Valid) -+ p->VirtualAttributes.Win32Protection = get_win32_prot( vprot, view->protect ); -+ } -+} -+#endif -+ -+static int compare_working_set_info_ref( const void *a, const void *b ) -+{ -+ const struct working_set_info_ref *r1 = a, *r2 = b; -+ -+ if (r1->addr < r2->addr) return -1; -+ return r1->addr > r2->addr; -+} -+ - static NTSTATUS get_working_set_ex( HANDLE process, LPCVOID addr, - MEMORY_WORKING_SET_EX_INFORMATION *info, - SIZE_T len, SIZE_T *res_len ) - { --#if !defined(HAVE_LIBPROCSTAT) -- static int pagemap_fd = -2; --#endif -- MEMORY_WORKING_SET_EX_INFORMATION *p; -+ struct working_set_info_ref ref_buffer[256], *ref = ref_buffer, *r; -+ struct fill_working_set_info_data data; -+ char *start, *end; -+ SIZE_T i, count; -+ size_t size; -+ struct file_view *view, *prev_view; - sigset_t sigset; -+ BYTE vprot; - - if (process != NtCurrentProcess()) - { -@@ -5238,103 +5394,59 @@ static NTSTATUS get_working_set_ex( HANDLE process, LPCVOID addr, - return STATUS_INVALID_INFO_CLASS; - } - --#if defined(HAVE_LIBPROCSTAT) -- { -- struct procstat *pstat; -- unsigned int proc_count; -- struct kinfo_proc *kip = NULL; -- unsigned int vmentry_count = 0; -- struct kinfo_vmentry *vmentries = NULL; -+ if (len < sizeof(*info)) return STATUS_INFO_LENGTH_MISMATCH; - -- pstat = procstat_open_sysctl(); -- if (pstat) -- kip = procstat_getprocs( pstat, KERN_PROC_PID, getpid(), &proc_count ); -- if (kip) -- vmentries = procstat_getvmmap( pstat, kip, &vmentry_count ); -- if (vmentries == NULL) -- WARN( "couldn't get process vmmap, errno %d\n", errno ); -+ count = len / sizeof(*info); - -- server_enter_uninterrupted_section( &virtual_mutex, &sigset ); -- for (p = info; (UINT_PTR)(p + 1) <= (UINT_PTR)info + len; p++) -- { -- int i; -- struct kinfo_vmentry *entry = NULL; -- BYTE vprot; -- struct file_view *view; -- -- memset( &p->VirtualAttributes, 0, sizeof(p->VirtualAttributes) ); -- if ((view = find_view( p->VirtualAddress, 0 )) && -- get_committed_size( view, p->VirtualAddress, &vprot, VPROT_COMMITTED ) && -- (vprot & VPROT_COMMITTED)) -- { -- for (i = 0; i < vmentry_count && entry == NULL; i++) -- { -- if (vmentries[i].kve_start <= (ULONG_PTR)p->VirtualAddress && (ULONG_PTR)p->VirtualAddress <= vmentries[i].kve_end) -- entry = &vmentries[i]; -- } -- -- p->VirtualAttributes.Valid = !(vprot & VPROT_GUARD) && (vprot & 0x0f) && entry && entry->kve_type != KVME_TYPE_SWAP; -- p->VirtualAttributes.Shared = !is_view_valloc( view ); -- if (p->VirtualAttributes.Shared && p->VirtualAttributes.Valid) -- p->VirtualAttributes.ShareCount = 1; /* FIXME */ -- if (p->VirtualAttributes.Valid) -- p->VirtualAttributes.Win32Protection = get_win32_prot( vprot, view->protect ); -- } -- } -- server_leave_uninterrupted_section( &virtual_mutex, &sigset ); -- -- if (vmentries) -- procstat_freevmmap( pstat, vmentries ); -- if (kip) -- procstat_freeprocs( pstat, kip ); -- if (pstat) -- procstat_close( pstat ); -+ if (count > ARRAY_SIZE(ref_buffer)) ref = malloc( count * sizeof(*ref) ); -+ for (i = 0; i < count; ++i) -+ { -+ ref[i].orig_index = i; -+ ref[i].addr = ROUND_ADDR( info[i].VirtualAddress, page_mask ); -+ info[i].VirtualAttributes.Flags = 0; - } --#else -+ qsort( ref, count, sizeof(*ref), compare_working_set_info_ref ); -+ start = ref[0].addr; -+ end = ref[count - 1].addr + page_size; -+ - server_enter_uninterrupted_section( &virtual_mutex, &sigset ); -- if (pagemap_fd == -2) -- { --#ifdef O_CLOEXEC -- if ((pagemap_fd = open( "/proc/self/pagemap", O_RDONLY | O_CLOEXEC, 0 )) == -1 && errno == EINVAL) --#endif -- pagemap_fd = open( "/proc/self/pagemap", O_RDONLY, 0 ); -+ init_fill_working_set_info_data( &data, end ); - -- if (pagemap_fd == -1) WARN( "unable to open /proc/self/pagemap\n" ); -- else fcntl(pagemap_fd, F_SETFD, FD_CLOEXEC); /* in case O_CLOEXEC isn't supported */ -+ view = find_view_range( start, end - start ); -+ while (view && (char *)view->base > start) -+ { -+ prev_view = RB_ENTRY_VALUE( rb_prev( &view->entry ), struct file_view, entry ); -+ if (!prev_view || (char *)prev_view->base + prev_view->size <= start) break; -+ view = prev_view; - } - -- for (p = info; (UINT_PTR)(p + 1) <= (UINT_PTR)info + len; p++) -+ r = ref; -+ while (view && (char *)view->base < end) - { -- BYTE vprot; -- UINT64 pagemap; -- struct file_view *view; -- -- memset( &p->VirtualAttributes, 0, sizeof(p->VirtualAttributes) ); -- -- if ((view = find_view( p->VirtualAddress, 0 )) && -- get_committed_size( view, p->VirtualAddress, &vprot, VPROT_COMMITTED ) && -- (vprot & VPROT_COMMITTED)) -+ if (start < (char *)view->base) start = view->base; -+ while (r != ref + count && r->addr < start) ++r; -+ while (start != (char *)view->base + view->size && r != ref + count -+ && r->addr < (char *)view->base + view->size) - { -- if (pagemap_fd == -1 || -- pread( pagemap_fd, &pagemap, sizeof(pagemap), ((UINT_PTR)p->VirtualAddress >> page_shift) * sizeof(pagemap) ) != sizeof(pagemap)) -+ size = get_committed_size( view, start, end - start, &vprot, ~VPROT_WRITEWATCH ); -+ start += size; -+ if (vprot & VPROT_COMMITTED) - { -- /* If we don't have pagemap information, default to invalid. */ -- pagemap = 0; -+ i = 0; -+ while (r + i != ref + count && r[i].addr < start) ++i; -+ fill_working_set_info( &data, view, vprot, r, i, info ); -+ r += i; - } -- -- p->VirtualAttributes.Valid = !(vprot & VPROT_GUARD) && (vprot & 0x0f) && (pagemap >> 63); -- p->VirtualAttributes.Shared = (!is_view_valloc( view ) && ((pagemap >> 61) & 1)) || ((view->protect & VPROT_WRITECOPY) && !(vprot & VPROT_WRITTEN)); -- if (p->VirtualAttributes.Shared && p->VirtualAttributes.Valid) -- p->VirtualAttributes.ShareCount = 1; /* FIXME */ -- if (p->VirtualAttributes.Valid) -- p->VirtualAttributes.Win32Protection = get_win32_prot( vprot, view->protect ); - } -+ if (r == ref + count) break; -+ view = RB_ENTRY_VALUE( rb_next( &view->entry ), struct file_view, entry ); - } -+ free_fill_working_set_info_data( &data ); -+ if (ref != ref_buffer) free( ref ); - server_leave_uninterrupted_section( &virtual_mutex, &sigset ); --#endif - - if (res_len) -- *res_len = (UINT_PTR)p - (UINT_PTR)info; -+ *res_len = len; - return STATUS_SUCCESS; - } - diff --git a/0003-pending-mrs-and-backports/9999-misc-loose/0010-ps5890-winex11-Fix-a-possible-desktop-window-message-queue-hang.patch b/0003-pending-mrs-and-backports/9999-misc-loose/0010-ps5890-winex11-Fix-a-possible-desktop-window-message-queue-hang.patch new file mode 100644 index 0000000..3248d9b --- /dev/null +++ b/0003-pending-mrs-and-backports/9999-misc-loose/0010-ps5890-winex11-Fix-a-possible-desktop-window-message-queue-hang.patch @@ -0,0 +1,60 @@ +From 3526c2fbd88f93a42c50adc8fb4328e62e0b7d72 Mon Sep 17 00:00:00 2001 +From: Zhiyi Zhang +Date: Thu, 20 Jun 2024 16:02:05 +0800 +Subject: [PATCH] winex11.drv: Fix a possible desktop window message queue + hang. + +After an X11 event handler queues messages to another thread, TRUE should be returned and eventually +propagated to X11DRV_ProcessEvents(). + +When FALSE is always returned in xrandr14_device_change_handler(), a possible hang can happen for +the desktop message queue as follows: + +1. The explorer.exe calls GetMessageW() -> NtUserGetMessage() -> wait_objects() -> wait_message(). +2. In wait_message(), user_driver->pProcessEvents() gets called in the desktop window thread to +handle RRNotify events and calls xrandr14_device_change_handler() -> display_mode_changed(FALSE) +-> send_message(get_desktop_window(), WM_DISPLAYCHANGE, ...) -> desktop_window_proc() -> +send_message_timeout() -> send_client_message() -> process_message() -> broadcast_message() -> +send_message_timeout() -> send_client_message() -> process_message() -> send_inter_thread_message() +-> wait_message_reply() -> a server set_queue_mask() with skip_wait being 1 -> wake_mask and +changed_mask are set to 0. +3. In wait_message(), user_driver->pProcessEvents() returns FALSE from xrandr14_device_change_handler(). +So wait_message() continues to call NtWaitForMultipleObjects(). +4. Now NtWaitForMultipleObjects() hangs for INFINITE timeout because wake_mask and changed_mask +for the message queue are set to 0 so the thread is not woke up. + +The hang is sensitive to message ordering and only happens in this specific case so it's hard to +reproduce with tests. I believe some of the past test timeouts on TestBots can be attributed to this +bug. +--- + dlls/winex11.drv/xrandr.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c +index edad0712927..1cf8c7c5070 100644 +--- a/dlls/winex11.drv/xrandr.c ++++ b/dlls/winex11.drv/xrandr.c +@@ -1212,15 +1212,19 @@ static void xrandr14_free_monitors( struct gdi_monitor *monitors, int count ) + + static BOOL xrandr14_device_change_handler( HWND hwnd, XEvent *event ) + { ++ BOOL ret = FALSE; + RECT rect; + + xrandr14_invalidate_current_mode_cache(); + if (hwnd == NtUserGetDesktopWindow() && NtUserGetWindowThread( hwnd, NULL ) == GetCurrentThreadId()) ++ { + NtUserCallNoParam( NtUserCallNoParam_DisplayModeChanged ); ++ ret = TRUE; ++ } + /* Update xinerama monitors for xinerama_get_fullscreen_monitors() */ + rect = get_host_primary_monitor_rect(); + xinerama_init( rect.right - rect.left, rect.bottom - rect.top ); +- return FALSE; ++ return ret; + } + + static void xrandr14_register_event_handlers(void) +-- +GitLab + diff --git a/0007-proton-fsync/1000-fixup-server-ntdll-Implement-message-waits.patch b/0007-proton-fsync/1000-fixup-server-ntdll-Implement-message-waits.patch new file mode 100644 index 0000000..64044af --- /dev/null +++ b/0007-proton-fsync/1000-fixup-server-ntdll-Implement-message-waits.patch @@ -0,0 +1,19 @@ +diff --git a/server/queue.c b/server/queue.c +index c8f32554f0c..821b772c5c0 100644 +--- a/server/queue.c ++++ b/server/queue.c +@@ -4165,11 +4165,13 @@ DECL_HANDLER(set_keyboard_repeat) + DECL_HANDLER(fsync_msgwait) + { + struct msg_queue *queue = get_current_queue(); ++ const queue_shm_t *queue_shm; + + if (!queue) return; ++ queue_shm = queue->shared; + queue->fsync_in_msgwait = req->in_msgwait; + +- if (current->process->idle_event && !(queue->wake_mask & QS_SMRESULT)) ++ if (current->process->idle_event && !(queue_shm->wake_mask & QS_SMRESULT)) + set_event( current->process->idle_event ); + + /* and start/stop waiting on the driver */ diff --git a/0010-renderer/0001-winex11-Allow-disabling-child-window-rendering.patch b/0010-renderer/0001-winex11-HACK-Allow-disabling-child-window-rendering.patch similarity index 100% rename from 0010-renderer/0001-winex11-Allow-disabling-child-window-rendering.patch rename to 0010-renderer/0001-winex11-HACK-Allow-disabling-child-window-rendering.patch diff --git a/0010-renderer/0002-winex11-Remove-more-clipping-if-envvar-set.patch b/0010-renderer/0002-winex11-HACK-Disable-more-window-clipping.patch similarity index 100% rename from 0010-renderer/0002-winex11-Remove-more-clipping-if-envvar-set.patch rename to 0010-renderer/0002-winex11-HACK-Disable-more-window-clipping.patch diff --git a/0010-renderer/0003-winex11-Avoid-onscreen-stencil-buffer-if-envvar-set.patch b/0010-renderer/0003-winex11-HACK-Avoid-onscreen-stencil-buffer.patch similarity index 100% rename from 0010-renderer/0003-winex11-Avoid-onscreen-stencil-buffer-if-envvar-set.patch rename to 0010-renderer/0003-winex11-HACK-Avoid-onscreen-stencil-buffer.patch diff --git a/staging-commit b/staging-commit index aa1c0a6..9cf7bbb 100644 --- a/staging-commit +++ b/staging-commit @@ -1 +1 @@ -9ba0efb9da67ecd0aaa7e60fed5d27fbd8566951 \ No newline at end of file +0d4b9f2f626073c8c9de44795e541b9518dc5a7b \ No newline at end of file diff --git a/wine-commit b/wine-commit index d955d8a..6bdab70 100644 --- a/wine-commit +++ b/wine-commit @@ -1 +1 @@ -b87f35898d22b90e36970e0b1fce1172ba64eb15 \ No newline at end of file +17f052c36a414a05fcb6a6e67bd3aac824fbed3e \ No newline at end of file