diff --git a/0003-pending-mrs-and-backports/4187-mfmediaengine-Be-a-bit-more-conservative-with-locks-in-engine-Shutdown/0001-mfmediaengine-Be-a-bit-more-conservative-with-locks-in-engine-Shutdown.patch b/0003-pending-mrs-and-backports/4187-mfmediaengine-Be-a-bit-more-conservative-with-locks-in-engine-Shutdown/0001-mfmediaengine-Be-a-bit-more-conservative-with-locks-in-engine-Shutdown.patch deleted file mode 100644 index f5cb0ba..0000000 --- a/0003-pending-mrs-and-backports/4187-mfmediaengine-Be-a-bit-more-conservative-with-locks-in-engine-Shutdown/0001-mfmediaengine-Be-a-bit-more-conservative-with-locks-in-engine-Shutdown.patch +++ /dev/null @@ -1,48 +0,0 @@ -From b234f51bf05a7aea0cf2eb596d69a6b1f62a873e Mon Sep 17 00:00:00 2001 -From: Yuxuan Shui -Date: Thu, 26 Oct 2023 15:17:03 +0100 -Subject: [PATCH] mfmediaengine: Be a bit more conservative with locks in - engine Shutdown. - -During engine shutdown we acquire engine lock first, then locks of its constituents (e.g. sample -grabbers); whereas normally the order is the other way around (e.g. timer callback -> acquire sample -grabber lock -> OnProcessSample callback -> engine lock). This is deadlock prone. - -With this commit, engine lock is released before we shutdown the inner media session. ---- - dlls/mfmediaengine/main.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c -index 0d553a40a7e..583437ac952 100644 ---- a/dlls/mfmediaengine/main.c -+++ b/dlls/mfmediaengine/main.c -@@ -2237,6 +2237,7 @@ static HRESULT WINAPI media_engine_Shutdown(IMFMediaEngineEx *iface) - { - struct media_engine *engine = impl_from_IMFMediaEngineEx(iface); - HRESULT hr = S_OK; -+ IMFMediaSession *session = NULL; - - TRACE("%p.\n", iface); - -@@ -2247,10 +2248,16 @@ static HRESULT WINAPI media_engine_Shutdown(IMFMediaEngineEx *iface) - { - media_engine_set_flag(engine, FLAGS_ENGINE_SHUT_DOWN, TRUE); - media_engine_clear_presentation(engine); -- IMFMediaSession_Shutdown(engine->session); -+ session = engine->session; -+ IMFMediaSession_AddRef(session); - } - LeaveCriticalSection(&engine->cs); - -+ if (session) -+ { -+ IMFMediaSession_Shutdown(session); -+ IMFMediaSession_Release(session); -+ } - return hr; - } - --- -GitLab - diff --git a/0003-pending-mrs-and-backports/4328-ntdll-Don-t-allocate-vprot-entries-until-commit/0001-ntdll-Don-t-allocate-vprot-entries-until-commit.patch b/0003-pending-mrs-and-backports/4328-ntdll-Don-t-allocate-vprot-entries-until-commit/0001-ntdll-Don-t-allocate-vprot-entries-until-commit.patch new file mode 100644 index 0000000..b7c0b72 --- /dev/null +++ b/0003-pending-mrs-and-backports/4328-ntdll-Don-t-allocate-vprot-entries-until-commit/0001-ntdll-Don-t-allocate-vprot-entries-until-commit.patch @@ -0,0 +1,203 @@ +From 9b4099ed8b9ac0670396bdc50dbfa6f5bb435784 Mon Sep 17 00:00:00 2001 +From: Evan Tang +Date: Mon, 30 Oct 2023 11:40:41 -0500 +Subject: [PATCH] ntdll: Don't allocate vprot entries until commit. + +Reservations only consume address space, which can be much larger than +the amount of ram in the system, so allocating even one byte per page +can result in huge amounts of ram used. +--- + dlls/ntdll/unix/virtual.c | 87 ++++++++++++++++++++++++++++++++------- + 1 file changed, 73 insertions(+), 14 deletions(-) + +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index b2e1be9f53f..2e2d5ce2345 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -908,8 +908,7 @@ static BYTE get_page_vprot( const void *addr ) + * Return the size of the region with equal masked vprot byte. + * Also return the protections for the first page. + * The function assumes that base and size are page aligned, +- * base + size does not wrap around and the range is within view so +- * vprot bytes are allocated for the range. */ ++ * base + size does not wrap around, and the range is within view. */ + static SIZE_T get_vprot_range_size( char *base, SIZE_T size, BYTE mask, BYTE *vprot ) + { + static const UINT_PTR word_from_byte = (UINT_PTR)0x101010101010101; +@@ -927,11 +926,24 @@ static SIZE_T get_vprot_range_size( char *base, SIZE_T size, BYTE mask, BYTE *vp + if (aligned_start_idx > end_idx) aligned_start_idx = end_idx; + + #ifdef _WIN64 +- vprot_ptr = pages_vprot[curr_idx >> pages_vprot_shift] + (curr_idx & pages_vprot_mask); ++ if (pages_vprot[curr_idx >> pages_vprot_shift]) ++ { ++ vprot_ptr = pages_vprot[curr_idx >> pages_vprot_shift] + (curr_idx & pages_vprot_mask); ++ *vprot = *vprot_ptr; ++ } ++ else ++ { ++ *vprot = 0; ++ curr_idx = (curr_idx + pages_vprot_mask + 1) & ~pages_vprot_mask; ++ if (curr_idx > end_idx) ++ return size; ++ vprot_ptr = pages_vprot[curr_idx >> pages_vprot_shift]; ++ assert(curr_idx >= aligned_start_idx); ++ } + #else + vprot_ptr = pages_vprot + curr_idx; +-#endif + *vprot = *vprot_ptr; ++#endif + + /* Page count page table is at least the multiples of sizeof(UINT_PTR) + * so we don't have to worry about crossing the boundary on unaligned idx values. */ +@@ -944,7 +956,17 @@ static SIZE_T get_vprot_range_size( char *base, SIZE_T size, BYTE mask, BYTE *vp + for (; curr_idx < end_idx; curr_idx += sizeof(UINT_PTR), vprot_ptr += sizeof(UINT_PTR)) + { + #ifdef _WIN64 +- if (!(curr_idx & pages_vprot_mask)) vprot_ptr = pages_vprot[curr_idx >> pages_vprot_shift]; ++ if (!(curr_idx & pages_vprot_mask)) ++ { ++ while (!(vprot_ptr = pages_vprot[curr_idx >> pages_vprot_shift])) ++ { ++ if (!(vprot_word & mask_word)) ++ return (curr_idx - start_idx) << page_shift; ++ curr_idx += pages_vprot_mask + 1; ++ if (curr_idx >= end_idx) ++ return size; ++ } ++ } + #endif + if ((vprot_word ^ *(UINT_PTR *)vprot_ptr) & mask_word) + { +@@ -956,6 +978,21 @@ static SIZE_T get_vprot_range_size( char *base, SIZE_T size, BYTE mask, BYTE *vp + return size; + } + ++#ifdef _WIN64 ++/*********************************************************************** ++ * set_page_vprot_internal ++ * ++ * Helper function for set_page_vprot ++ */ ++static void set_pages_vprot_internal( size_t idx, BYTE vprot, size_t len ) ++{ ++ if (pages_vprot[idx >> pages_vprot_shift]) ++ memset(pages_vprot[idx >> pages_vprot_shift] + (idx & pages_vprot_mask), vprot, len); ++ else if (vprot) ++ ERR("vprot table missing entry at %x!\n", (unsigned int)(idx >> pages_vprot_shift)); ++} ++#endif ++ + /*********************************************************************** + * set_page_vprot + * +@@ -970,10 +1007,10 @@ static void set_page_vprot( const void *addr, size_t size, BYTE vprot ) + while (idx >> pages_vprot_shift != end >> pages_vprot_shift) + { + size_t dir_size = pages_vprot_mask + 1 - (idx & pages_vprot_mask); +- memset( pages_vprot[idx >> pages_vprot_shift] + (idx & pages_vprot_mask), vprot, dir_size ); ++ set_pages_vprot_internal(idx, vprot, dir_size); + idx += dir_size; + } +- memset( pages_vprot[idx >> pages_vprot_shift] + (idx & pages_vprot_mask), vprot, end - idx ); ++ set_pages_vprot_internal(idx, vprot, end - idx); + #else + memset( pages_vprot + idx, vprot, end - idx ); + #endif +@@ -991,10 +1028,22 @@ static void set_page_vprot_bits( const void *addr, size_t size, BYTE set, BYTE c + size_t end = ((size_t)addr + size + page_mask) >> page_shift; + + #ifdef _WIN64 +- for ( ; idx < end; idx++) ++ while (idx < end) + { +- BYTE *ptr = pages_vprot[idx >> pages_vprot_shift] + (idx & pages_vprot_mask); +- *ptr = (*ptr & ~clear) | set; ++ size_t next = (idx + pages_vprot_mask + 1) & ~pages_vprot_mask; ++ BYTE *ptr = pages_vprot[idx >> pages_vprot_shift]; ++ if (ptr) ++ { ++ size_t i = idx & pages_vprot_mask; ++ size_t table_end = min(next, end) - (idx & ~pages_vprot_mask); ++ for (; i < table_end; i++) ++ ptr[i] = (ptr[i] & ~clear) | set; ++ } ++ else if (set) ++ { ++ ERR("vprot table missing entry at %x!\n", (unsigned)(idx >> pages_vprot_shift)); ++ } ++ idx = next; + } + #else + for ( ; idx < end; idx++) pages_vprot[idx] = (pages_vprot[idx] & ~clear) | set; +@@ -1482,6 +1531,10 @@ static void register_view( struct file_view *view ) + static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t size, unsigned int vprot ) + { + struct file_view *view; ++ /* If uncommitted, delay allocation until commit so we don't make vprot tables for reservations, ++ * which can be as large as the address space allows (128TB). ++ * WRITEWATCH doesn't yet support allocating on commit, so make an exception for that. */ ++ BOOL write_vprot = !!(vprot & (VPROT_COMMITTED | VPROT_WRITEWATCH)); + int unix_prot = get_unix_prot( vprot ); + + assert( !((UINT_PTR)base & page_mask) ); +@@ -1499,7 +1552,7 @@ static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t siz + delete_view( view ); + } + +- if (!alloc_pages_vprot( base, size )) return STATUS_NO_MEMORY; ++ if (write_vprot && !alloc_pages_vprot( base, size )) return STATUS_NO_MEMORY; + + /* Create the view structure */ + +@@ -1512,7 +1565,7 @@ static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t siz + view->base = base; + view->size = size; + view->protect = vprot; +- set_page_vprot( base, size, vprot ); ++ set_page_vprot( base, size, write_vprot ? vprot : 0 ); + + register_view( view ); + +@@ -1649,6 +1702,8 @@ static BOOL set_vprot( struct file_view *view, void *base, size_t size, BYTE vpr + } + if (enable_write_exceptions && is_vprot_exec_write( vprot )) vprot |= VPROT_WRITEWATCH; + if (mprotect_exec( base, size, get_unix_prot(vprot) )) return FALSE; ++ /* Reserved pages may not have table entries yet, make those now */ ++ if (vprot && !alloc_pages_vprot( base, size )) return FALSE; + set_page_vprot( base, size, vprot ); + return TRUE; + } +@@ -2176,6 +2231,7 @@ done: + 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; ++ BYTE extra = 0; + + base = ROUND_ADDR( base, page_mask ); + offset = (char *)base - (char *)view->base; +@@ -2196,7 +2252,8 @@ static SIZE_T get_committed_size( struct file_view *view, void *base, size_t max + if (reply->committed) + { + *vprot |= VPROT_COMMITTED; +- set_page_vprot_bits( base, size, VPROT_COMMITTED, 0 ); ++ extra = VPROT_COMMITTED; ++ vprot_mask &= ~VPROT_COMMITTED; + } + } + } +@@ -2206,7 +2263,9 @@ static SIZE_T get_committed_size( struct file_view *view, void *base, size_t max + } + else size = min( view->size - offset, max_size ); + +- return get_vprot_range_size( base, size, vprot_mask, vprot ); ++ size = get_vprot_range_size( base, size, vprot_mask, vprot ); ++ *vprot |= extra; ++ return size; + } + + +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/4328-ntdll-Don-t-allocate-vprot-entries-until-commit/0002-ntdll-tests-Add-test-for-reserving-massive-amounts-of-memory.patch b/0003-pending-mrs-and-backports/4328-ntdll-Don-t-allocate-vprot-entries-until-commit/0002-ntdll-tests-Add-test-for-reserving-massive-amounts-of-memory.patch new file mode 100644 index 0000000..4fa2a9e --- /dev/null +++ b/0003-pending-mrs-and-backports/4328-ntdll-Don-t-allocate-vprot-entries-until-commit/0002-ntdll-tests-Add-test-for-reserving-massive-amounts-of-memory.patch @@ -0,0 +1,55 @@ +From e9d146653d292d5c05675a1c9d7f53473af3a95c Mon Sep 17 00:00:00 2001 +From: Evan Tang +Date: Mon, 30 Oct 2023 14:34:03 -0500 +Subject: [PATCH] ntdll/tests: Add test for reserving massive amounts of + memory. + +--- + dlls/ntdll/tests/virtual.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c +index a9dec1b5a8a..808b67b9b27 100644 +--- a/dlls/ntdll/tests/virtual.c ++++ b/dlls/ntdll/tests/virtual.c +@@ -2676,6 +2676,31 @@ static void test_query_image_information(void) + NtClose( file ); + } + ++static void test_massive_memory_reservation(void) ++{ ++ /* Test to make sure large address space reservations don't use more ram than the system has. ++ * Most failures here will be the test getting killed by the OOM killer. */ ++ int i; ++ for (i = 12; i < sizeof(void*) * 8; i++) ++ { ++ void* ptr; ++ BOOL is_ok; ++ SetLastError(0xdeadbeef); ++ ptr = VirtualAlloc(NULL, 1ull << i, MEM_RESERVE, PAGE_NOACCESS); ++ if (i < 40 && sizeof(void*) == 8) /* These should succeed */ ++ is_ok = GetLastError() == 0xdeadbeef; ++ else if (i < 47) /* These might run out of address space */ ++ is_ok = GetLastError() == 0xdeadbeef || GetLastError() == ERROR_NOT_ENOUGH_MEMORY; ++ else ++ is_ok = GetLastError() == ERROR_INVALID_PARAMETER; ++ ok(is_ok, "Unexpected error allocating 1 << %d: %lx.\n", i, GetLastError()); ++ if (ptr) ++ VirtualFree(ptr, 1ull << i, MEM_RELEASE); ++ ptr = malloc(1ull << i); ++ free(ptr); ++ } ++} ++ + START_TEST(virtual) + { + HMODULE mod; +@@ -2726,4 +2751,5 @@ START_TEST(virtual) + test_query_region_information(); + test_query_image_information(); + test_exec_memory_writes(); ++ test_massive_memory_reservation(); + } +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/4587-kernelbase-Implement-flag-validation-in-LoadLibraryEx-to-work-like-in-Win10/0001-kernelbase-Add-test-case-for-LoadLibraryEx-when-hFile-is-non-NULL.patch b/0003-pending-mrs-and-backports/4587-kernelbase-Implement-flag-validation-in-LoadLibraryEx-to-work-like-in-Win10/0001-kernelbase-Add-test-case-for-LoadLibraryEx-when-hFile-is-non-NULL.patch new file mode 100644 index 0000000..3a787c4 --- /dev/null +++ b/0003-pending-mrs-and-backports/4587-kernelbase-Implement-flag-validation-in-LoadLibraryEx-to-work-like-in-Win10/0001-kernelbase-Add-test-case-for-LoadLibraryEx-when-hFile-is-non-NULL.patch @@ -0,0 +1,49 @@ +From b7333394d1a0dc94a02f7fd722914dce343f10c6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= +Date: Mon, 4 Dec 2023 02:38:19 +0200 +Subject: [PATCH] kernelbase: Add test case for LoadLibraryEx() when hFile is + non-NULL + +When hFile is non-NULL then LoadLibraryEx() should return NULL +with LastError set as ERROR_INVALID_PARAMETER +--- + dlls/kernelbase/tests/file.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/dlls/kernelbase/tests/file.c b/dlls/kernelbase/tests/file.c +index 18dff0a32ab..b19360c8998 100644 +--- a/dlls/kernelbase/tests/file.c ++++ b/dlls/kernelbase/tests/file.c +@@ -46,6 +46,23 @@ static void test_ioring_caps(void) + todo_wine ok(hr == S_OK, "got %#lx.\n", hr); + } + ++static void test_load_library_ex_flags(void) ++{ ++ HMODULE hmod; ++ DWORD last_error; ++ ++ SetLastError(0x33); ++ ++ /* Test if LoadLibraryEx can load a dll */ ++ hmod = LoadLibraryExW(L"kernelbase.dll", NULL /* hFile */, LOAD_LIBRARY_SEARCH_SYSTEM32 /* dwFlags */); ++ ok(hmod != NULL, "LoadLibraryEx returned %p with LastError: %#lx.\n", hmod, GetLastError()); ++ ++ /* When hFile is non-NULL LoadLibraryEx should return NULL and set LastError to ERROR_INVALID_PARAMETER */ ++ hmod = LoadLibraryExW(L"kernelbase.dll", (HANDLE)0x000003A0 /* random hFile */, 0 /* dwFlags */); ++ last_error = GetLastError(); ++ ok(hmod == NULL && last_error == ERROR_INVALID_PARAMETER, "LoadLibraryEx returned %p with LastError: %#lx.\n", hmod, last_error); ++} ++ + START_TEST(file) + { + HMODULE hmod; +@@ -54,4 +71,5 @@ START_TEST(file) + pQueryIoRingCapabilities = (void *)GetProcAddress(hmod, "QueryIoRingCapabilities"); + + test_ioring_caps(); ++ test_load_library_ex_flags(); + } +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/4587-kernelbase-Implement-flag-validation-in-LoadLibraryEx-to-work-like-in-Win10/0002-kernelbase-LoadLibraryEx-enforce-valid-flag-combinations.patch b/0003-pending-mrs-and-backports/4587-kernelbase-Implement-flag-validation-in-LoadLibraryEx-to-work-like-in-Win10/0002-kernelbase-LoadLibraryEx-enforce-valid-flag-combinations.patch new file mode 100644 index 0000000..a6670fb --- /dev/null +++ b/0003-pending-mrs-and-backports/4587-kernelbase-Implement-flag-validation-in-LoadLibraryEx-to-work-like-in-Win10/0002-kernelbase-LoadLibraryEx-enforce-valid-flag-combinations.patch @@ -0,0 +1,37 @@ +From db34272389cc9d7b4ef7bdfc6708bc477ab37ff7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= +Date: Fri, 1 Dec 2023 04:32:32 +0200 +Subject: [PATCH] kernelbase: LoadLibraryEx enforce valid flag combinations + +--- + dlls/kernelbase/loader.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c +index 59b91596f13..8f40286b880 100644 +--- a/dlls/kernelbase/loader.c ++++ b/dlls/kernelbase/loader.c +@@ -530,12 +530,19 @@ HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW( LPCWSTR name, HANDLE file, DWOR + { + UNICODE_STRING str; + HMODULE module; ++ BOOL invalid_parameter; + +- if (!name) ++ invalid_parameter = !name || ++ file || ++ ((flags & LOAD_LIBRARY_AS_DATAFILE) && (flags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)) || ++ ((flags & LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) && (flags & LOAD_WITH_ALTERED_SEARCH_PATH)); ++ ++ if (invalid_parameter) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } ++ + RtlInitUnicodeString( &str, name ); + if (str.Buffer[str.Length/sizeof(WCHAR) - 1] != ' ') return load_library( &str, flags ); + +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/4587-kernelbase-Implement-flag-validation-in-LoadLibraryEx-to-work-like-in-Win10/0003-kernelbase-LoadLibraryEx-support-LOAD-PACKAGED-LIBRARY.patch b/0003-pending-mrs-and-backports/4587-kernelbase-Implement-flag-validation-in-LoadLibraryEx-to-work-like-in-Win10/0003-kernelbase-LoadLibraryEx-support-LOAD-PACKAGED-LIBRARY.patch new file mode 100644 index 0000000..d8504dc --- /dev/null +++ b/0003-pending-mrs-and-backports/4587-kernelbase-Implement-flag-validation-in-LoadLibraryEx-to-work-like-in-Win10/0003-kernelbase-LoadLibraryEx-support-LOAD-PACKAGED-LIBRARY.patch @@ -0,0 +1,43 @@ +From f0006b6133fe7544091c58d989ae967effa065a2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= +Date: Fri, 1 Dec 2023 04:36:25 +0200 +Subject: [PATCH] kernelbase: LoadLibraryEx support LOAD_PACKAGED_LIBRARY + +--- + dlls/kernelbase/loader.c | 7 +++++++ + include/winbase.h | 1 + + 2 files changed, 8 insertions(+) + +diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c +index 8f40286b880..af61428487b 100644 +--- a/dlls/kernelbase/loader.c ++++ b/dlls/kernelbase/loader.c +@@ -543,6 +543,13 @@ HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW( LPCWSTR name, HANDLE file, DWOR + return 0; + } + ++ if (flags & LOAD_PACKAGED_LIBRARY) ++ { ++ /* FIXME: Don't know if it's implemented like this on Windows ++ but this does accomplish same result in error case */ ++ return LoadPackagedLibrary(name, flags); ++ } ++ + RtlInitUnicodeString( &str, name ); + if (str.Buffer[str.Length/sizeof(WCHAR) - 1] != ' ') return load_library( &str, flags ); + +diff --git a/include/winbase.h b/include/winbase.h +index 16e449f7c2d..93b592c3791 100644 +--- a/include/winbase.h ++++ b/include/winbase.h +@@ -995,6 +995,7 @@ DECL_WINELIB_TYPE_AW(ENUMRESLANGPROC) + /* flags that can be passed to LoadLibraryEx */ + #define DONT_RESOLVE_DLL_REFERENCES 0x00000001 + #define LOAD_LIBRARY_AS_DATAFILE 0x00000002 ++#define LOAD_PACKAGED_LIBRARY 0x00000004 /* Undocumented Windows internal */ + #define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008 + #define LOAD_IGNORE_CODE_AUTHZ_LEVEL 0x00000010 + #define LOAD_LIBRARY_AS_IMAGE_RESOURCE 0x00000020 +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/4587-kernelbase-Implement-flag-validation-in-LoadLibraryEx-to-work-like-in-Win10/0004-kernelbase-LoadLibraryEx-validate-flags-like-Win10.patch b/0003-pending-mrs-and-backports/4587-kernelbase-Implement-flag-validation-in-LoadLibraryEx-to-work-like-in-Win10/0004-kernelbase-LoadLibraryEx-validate-flags-like-Win10.patch new file mode 100644 index 0000000..ef50493 --- /dev/null +++ b/0003-pending-mrs-and-backports/4587-kernelbase-Implement-flag-validation-in-LoadLibraryEx-to-work-like-in-Win10/0004-kernelbase-LoadLibraryEx-validate-flags-like-Win10.patch @@ -0,0 +1,51 @@ +From 001137a9c547013303b4feeec73df61f31ce4c4b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= +Date: Fri, 1 Dec 2023 04:44:30 +0200 +Subject: [PATCH] kernelbase: LoadLibraryEx validate flags like Win10 + +--- + dlls/kernelbase/loader.c | 12 ++++++++++++ + include/winbase.h | 4 ++++ + 2 files changed, 16 insertions(+) + +diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c +index af61428487b..316b1d180cb 100644 +--- a/dlls/kernelbase/loader.c ++++ b/dlls/kernelbase/loader.c +@@ -537,6 +537,18 @@ HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW( LPCWSTR name, HANDLE file, DWOR + ((flags & LOAD_LIBRARY_AS_DATAFILE) && (flags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)) || + ((flags & LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) && (flags & LOAD_WITH_ALTERED_SEARCH_PATH)); + ++ /* Windows 10 22H2 have such validation */ ++ invalid_parameter = invalid_parameter || ++ ((flags & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) && ++ (flags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))); ++ ++ if (flags & LOAD_LIBRARY_UNSUPPORTED_MASK) ++ { ++ WARN( "Pretending to be Windows 10 22H2, unsupported flags: 0x%lx\n, returning ERROR_INVALID_PARAMETER", ++ flags & LOAD_LIBRARY_UNSUPPORTED_MASK ); ++ invalid_parameter = TRUE; ++ } ++ + if (invalid_parameter) + { + SetLastError( ERROR_INVALID_PARAMETER ); +diff --git a/include/winbase.h b/include/winbase.h +index 93b592c3791..bcfd0fc8d1f 100644 +--- a/include/winbase.h ++++ b/include/winbase.h +@@ -1006,6 +1006,10 @@ DECL_WINELIB_TYPE_AW(ENUMRESLANGPROC) + #define LOAD_LIBRARY_SEARCH_USER_DIRS 0x00000400 + #define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 + #define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000 ++#define LOAD_LIBRARY_SAFE_CURRENT_DIRS 0x00002000 ++#define LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER 0x00004000 ++#define LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY 0x00008000 ++#define LOAD_LIBRARY_UNSUPPORTED_MASK 0xFFFF0000 /* If you add new flags update this mask */ + + #define GET_MODULE_HANDLE_EX_FLAG_PIN 1 + #define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2 +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/4833-ntdll-Improve-NtQuerySystemInformation-SystemCodeIntegrityInformation-/0001-ntdll-Improve-NtQuerySystemInformation-SystemCodeIntegrityInformation-.patch b/0003-pending-mrs-and-backports/4833-ntdll-Improve-NtQuerySystemInformation-SystemCodeIntegrityInformation-/0001-ntdll-Improve-NtQuerySystemInformation-SystemCodeIntegrityInformation-.patch deleted file mode 100644 index 2b49507..0000000 --- a/0003-pending-mrs-and-backports/4833-ntdll-Improve-NtQuerySystemInformation-SystemCodeIntegrityInformation-/0001-ntdll-Improve-NtQuerySystemInformation-SystemCodeIntegrityInformation-.patch +++ /dev/null @@ -1,44 +0,0 @@ -From efaf2bd6090200d3fa7ea313c70d7d7a4fa584fd Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= -Date: Mon, 11 Dec 2023 04:59:59 +0200 -Subject: [PATCH] ntdll: Improve - NtQuerySystemInformation(SystemCodeIntegrityInformation) - -This makes it match more closely how it works on Windows. ---- - dlls/ntdll/unix/system.c | 18 ++++++++++++++---- - 1 file changed, 14 insertions(+), 4 deletions(-) - -diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c -index 879a5893758..c5b7cf07d95 100644 ---- a/dlls/ntdll/unix/system.c -+++ b/dlls/ntdll/unix/system.c -@@ -3216,11 +3216,21 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class, - FIXME("SystemCodeIntegrityInformation, size %u, info %p, stub!\n", (int)size, info); - - len = sizeof(SYSTEM_CODEINTEGRITY_INFORMATION); -- -- if (size >= len) -- integrity_info->CodeIntegrityOptions = CODEINTEGRITY_OPTION_ENABLED; -- else -+ if (size > 0) -+ { -+ if (!info) ret = STATUS_ACCESS_VIOLATION; -+ else if (size >= len && integrity_info->Length == len) -+ { -+ /* proper implementation is probably reading this from registry, see https://learn.microsoft.com/en-us/windows/security/hardware-security/enable-virtualization-based-protection-of-code-integrity */ -+ integrity_info->CodeIntegrityOptions = CODEINTEGRITY_OPTION_ENABLED | CODEINTEGRITY_OPTION_HVCI_IUM_ENABLED; -+ } else -+ { -+ ret = STATUS_INFO_LENGTH_MISMATCH; -+ } -+ } else -+ { - ret = STATUS_INFO_LENGTH_MISMATCH; -+ } - break; - } - --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0001-ntoskrnl-exe-tests-Open-directory-object-with-nonzero-access-in-test-permanent-.patch b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0001-ntoskrnl-exe-tests-Open-directory-object-with-nonzero-access-in-test-permanent-.patch new file mode 100644 index 0000000..35f0e27 --- /dev/null +++ b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0001-ntoskrnl-exe-tests-Open-directory-object-with-nonzero-access-in-test-permanent-.patch @@ -0,0 +1,35 @@ +From b3f65e3d4e034df551dd2b8f735c296785d871a8 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Wed, 10 Jul 2024 16:41:20 -0600 +Subject: [PATCH] ntoskrnl.exe/tests: Open directory object with nonzero access + in test_permanent(). + +--- + dlls/ntoskrnl.exe/tests/driver.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c +index f82e34fca3b..7194dc403d7 100644 +--- a/dlls/ntoskrnl.exe/tests/driver.c ++++ b/dlls/ntoskrnl.exe/tests/driver.c +@@ -2289,7 +2289,7 @@ static void test_permanence(void) + ok(!status, "got %#lx\n", status); + + attr.Attributes = 0; +- status = ZwOpenDirectoryObject( &handle, 0, &attr ); ++ status = ZwOpenDirectoryObject( &handle, DIRECTORY_ALL_ACCESS, &attr ); + ok(!status, "got %#lx\n", status); + status = ZwMakeTemporaryObject( handle ); + todo_wine +@@ -2307,7 +2307,7 @@ static void test_permanence(void) + todo_wine + ok(!status, "got %#lx\n", status); + attr.Attributes = OBJ_PERMANENT; +- status = ZwOpenDirectoryObject( &handle2, 0, &attr ); ++ status = ZwOpenDirectoryObject( &handle2, DIRECTORY_ALL_ACCESS, &attr ); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + status = ZwClose( handle2 ); + ok(!status, "got %#lx\n", status); +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0002-server-Skip-inaccessible-threads-in-get-next-thread-.patch b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0002-server-Skip-inaccessible-threads-in-get-next-thread-.patch new file mode 100644 index 0000000..16ca6ea --- /dev/null +++ b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0002-server-Skip-inaccessible-threads-in-get-next-thread-.patch @@ -0,0 +1,31 @@ +From b3a647851a473e7408c3afdac7507ceb2998bbc9 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Wed, 10 Jul 2024 16:53:49 -0600 +Subject: [PATCH] server: Skip inaccessible threads in (get_next_thread). + +--- + server/thread.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/server/thread.c b/server/thread.c +index b3ce5d9ac95..b83bd9231f4 100644 +--- a/server/thread.c ++++ b/server/thread.c +@@ -2026,8 +2026,12 @@ DECL_HANDLER(get_next_thread) + if (thread->process == process) + { + reply->handle = alloc_handle( current->process, thread, req->access, req->attributes ); +- release_object( process ); +- return; ++ if (get_error() != STATUS_ACCESS_DENIED) ++ { ++ release_object( process ); ++ return; ++ } ++ clear_error(); + } + ptr = req->flags ? list_prev( &thread_list, &thread->entry ) + : list_next( &thread_list, &thread->entry ); +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0003-httpapi-Don-t-open-files-with-zero-access.patch b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0003-httpapi-Don-t-open-files-with-zero-access.patch new file mode 100644 index 0000000..f0cce31 --- /dev/null +++ b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0003-httpapi-Don-t-open-files-with-zero-access.patch @@ -0,0 +1,34 @@ +From 04fa081590598bc1a1766deee18330c715acf1d2 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Fri, 6 Dec 2024 14:57:21 -0600 +Subject: [PATCH] httpapi: Don't open files with zero access. + +--- + dlls/httpapi/httpapi_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/dlls/httpapi/httpapi_main.c b/dlls/httpapi/httpapi_main.c +index d1c2667be2e..28d67c98333 100644 +--- a/dlls/httpapi/httpapi_main.c ++++ b/dlls/httpapi/httpapi_main.c +@@ -195,7 +195,7 @@ ULONG WINAPI HttpCreateHttpHandle(HANDLE *handle, ULONG reserved) + return ERROR_INVALID_PARAMETER; + + attr.ObjectName = &string; +- return RtlNtStatusToDosError(NtCreateFile(handle, 0, &attr, &iosb, NULL, ++ return RtlNtStatusToDosError(NtCreateFile(handle, SYNCHRONIZE, &attr, &iosb, NULL, + FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0)); + } + +@@ -843,7 +843,7 @@ ULONG WINAPI HttpCreateRequestQueue(HTTPAPI_VERSION version, const WCHAR *name, + if (sa && sa->bInheritHandle) + attr.Attributes |= OBJ_INHERIT; + attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL; +- return RtlNtStatusToDosError(NtCreateFile(handle, 0, &attr, &iosb, NULL, ++ return RtlNtStatusToDosError(NtCreateFile(handle, SYNCHRONIZE, &attr, &iosb, NULL, + FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0)); + } + +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0004-kernel32-Don-t-open-reg-keys-with-zero-access-mask.patch b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0004-kernel32-Don-t-open-reg-keys-with-zero-access-mask.patch new file mode 100644 index 0000000..1c918a1 --- /dev/null +++ b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0004-kernel32-Don-t-open-reg-keys-with-zero-access-mask.patch @@ -0,0 +1,25 @@ +From 4b5f64b6ea2b8d4b0398c03a75882221c9da463d Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Fri, 6 Dec 2024 15:35:37 -0600 +Subject: [PATCH] kernel32: Don't open reg keys with zero access mask. + +--- + dlls/kernel32/profile.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dlls/kernel32/profile.c b/dlls/kernel32/profile.c +index f65790ecc92..032802a42e0 100644 +--- a/dlls/kernel32/profile.c ++++ b/dlls/kernel32/profile.c +@@ -1032,7 +1032,7 @@ static HKEY open_file_mapping_key( const WCHAR *filename ) + + if (!mapping_key && RegOpenKeyExW( HKEY_LOCAL_MACHINE, + L"Software\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping", +- 0, KEY_WOW64_64KEY, &mapping_key )) ++ 0, KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY, &mapping_key )) + mapping_key = NULL; + + LeaveCriticalSection( &PROFILE_CritSect ); +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0005-setupapi-Don-t-open-reg-keys-with-zero-access-mask.patch b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0005-setupapi-Don-t-open-reg-keys-with-zero-access-mask.patch new file mode 100644 index 0000000..6a9124a --- /dev/null +++ b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0005-setupapi-Don-t-open-reg-keys-with-zero-access-mask.patch @@ -0,0 +1,25 @@ +From 29bcc7145aad748c5e34c9e8b56b8bf4391a3777 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Fri, 6 Dec 2024 15:50:46 -0600 +Subject: [PATCH] setupapi: Don't open reg keys with zero access mask. + +--- + dlls/setupapi/devinst.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c +index 4e406fe700e..34e9454c828 100644 +--- a/dlls/setupapi/devinst.c ++++ b/dlls/setupapi/devinst.c +@@ -842,7 +842,7 @@ static void remove_device(struct device *device) + RegDeleteKeyW(device->key, emptyW); + + /* delete all empty parents of the key */ +- if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, 0, &enum_key)) ++ if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, KEY_ENUMERATE_SUB_KEYS, &enum_key)) + { + lstrcpyW(id, device->instanceId); + +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0006-devenum-Don-t-open-reg-keys-with-zero-access-mask.patch b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0006-devenum-Don-t-open-reg-keys-with-zero-access-mask.patch new file mode 100644 index 0000000..d2a1a13 --- /dev/null +++ b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0006-devenum-Don-t-open-reg-keys-with-zero-access-mask.patch @@ -0,0 +1,52 @@ +From 9b04dff46b38c30cc78d8c7b1b443c99a46def28 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Fri, 6 Dec 2024 15:50:57 -0600 +Subject: [PATCH] devenum: Don't open reg keys with zero access mask. + +--- + dlls/devenum/mediacatenum.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/dlls/devenum/mediacatenum.c b/dlls/devenum/mediacatenum.c +index 906d01b2057..7ba370a3a02 100644 +--- a/dlls/devenum/mediacatenum.c ++++ b/dlls/devenum/mediacatenum.c +@@ -205,7 +205,7 @@ static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, + StringFromGUID2(&moniker->class, path + wcslen(path), CHARS_IN_GUID); + wcscat(path, L"\\Instance"); + } +- if ((ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, 0, &parent))) ++ if ((ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, KEY_ENUMERATE_SUB_KEYS, &parent))) + return HRESULT_FROM_WIN32(ret); + break; + +@@ -213,7 +213,7 @@ static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, + wcscpy(path, L"Software\\Microsoft\\ActiveMovie\\devenum\\"); + if (moniker->has_class) + StringFromGUID2(&moniker->class, path + wcslen(path), CHARS_IN_GUID); +- if ((ret = RegOpenKeyExW(HKEY_CURRENT_USER, path, 0, 0, &parent))) ++ if ((ret = RegOpenKeyExW(HKEY_CURRENT_USER, path, 0, KEY_ENUMERATE_SUB_KEYS, &parent))) + return HRESULT_FROM_WIN32(ret); + break; + +@@ -317,7 +317,7 @@ static HRESULT WINAPI property_bag_Write(IPropertyBag *iface, const WCHAR *name, + StringFromGUID2(&moniker->class, path + wcslen(path), CHARS_IN_GUID); + wcscat(path, L"\\Instance"); + } +- if ((ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, path, 0, NULL, 0, 0, NULL, &parent, NULL))) ++ if ((ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, path, 0, NULL, 0, KEY_ENUMERATE_SUB_KEYS, NULL, &parent, NULL))) + return HRESULT_FROM_WIN32(ret); + break; + +@@ -325,7 +325,7 @@ static HRESULT WINAPI property_bag_Write(IPropertyBag *iface, const WCHAR *name, + wcscpy(path, L"Software\\Microsoft\\ActiveMovie\\devenum\\"); + if (moniker->has_class) + StringFromGUID2(&moniker->class, path + wcslen(path), CHARS_IN_GUID); +- if ((ret = RegCreateKeyExW(HKEY_CURRENT_USER, path, 0, NULL, 0, 0, NULL, &parent, NULL))) ++ if ((ret = RegCreateKeyExW(HKEY_CURRENT_USER, path, 0, NULL, 0, KEY_ENUMERATE_SUB_KEYS, NULL, &parent, NULL))) + return HRESULT_FROM_WIN32(ret); + break; + +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0007-quartz-Don-t-open-reg-keys-with-zero-access-mask.patch b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0007-quartz-Don-t-open-reg-keys-with-zero-access-mask.patch new file mode 100644 index 0000000..99b8b5a --- /dev/null +++ b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0007-quartz-Don-t-open-reg-keys-with-zero-access-mask.patch @@ -0,0 +1,52 @@ +From a617c0ece8b3c0ced3ae0c2dcff0bb17819df30d Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Fri, 6 Dec 2024 17:40:05 -0600 +Subject: [PATCH] quartz: Don't open reg keys with zero access mask. + +--- + dlls/quartz/filtermapper.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/dlls/quartz/filtermapper.c b/dlls/quartz/filtermapper.c +index 87d7c4bb5d5..98b83455b5a 100644 +--- a/dlls/quartz/filtermapper.c ++++ b/dlls/quartz/filtermapper.c +@@ -1470,7 +1470,7 @@ static HRESULT WINAPI FilterMapper_RegisterPin(IFilterMapper *iface, CLSID clsid + if ((ret = RegSetValueExW(pin_key, L"IsRendered", 0, REG_DWORD, (const BYTE *)&rendered, sizeof(DWORD)))) + ERR("Failed to set IsRendered value, error %lu.\n", ret); + +- if (!(ret = RegCreateKeyExW(pin_key, L"Types", 0, NULL, 0, 0, NULL, &type_key, NULL))) ++ if (!(ret = RegCreateKeyExW(pin_key, L"Types", 0, NULL, 0, KEY_ENUMERATE_SUB_KEYS, NULL, &type_key, NULL))) + RegCloseKey(type_key); + else + ERR("Failed to create Types subkey, error %lu.\n", ret); +@@ -1512,7 +1512,7 @@ static HRESULT WINAPI FilterMapper_RegisterPinType(IFilterMapper *iface, + StringFromGUID2(&majortype, type_keypath, ARRAY_SIZE(type_keypath)); + wcscat(type_keypath, L"\\"); + StringFromGUID2(&subtype, type_keypath + wcslen(type_keypath), ARRAY_SIZE(type_keypath) - wcslen(type_keypath)); +- if (!(ret = RegCreateKeyExW(key, type_keypath, 0, NULL, 0, 0, NULL, &type_key, NULL))) ++ if (!(ret = RegCreateKeyExW(key, type_keypath, 0, NULL, 0, KEY_ENUMERATE_SUB_KEYS, NULL, &type_key, NULL))) + RegCloseKey(type_key); + else + ERR("Failed to create type key, error %lu.\n", ret); +@@ -1531,7 +1531,7 @@ static HRESULT WINAPI FilterMapper_UnregisterFilter(IFilterMapper *iface, CLSID + + StringFromGUID2(&clsid, guidstr, ARRAY_SIZE(guidstr)); + +- if ((ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Filter", 0, 0, &key))) ++ if ((ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Filter", 0, KEY_ENUMERATE_SUB_KEYS, &key))) + return HRESULT_FROM_WIN32(ret); + if ((ret = RegDeleteKeyW(key, guidstr))) + ERR("Failed to delete filter key, error %lu.\n", ret); +@@ -1576,7 +1576,7 @@ static HRESULT WINAPI FilterMapper_UnregisterPin(IFilterMapper * iface, CLSID cl + wcscpy(keypath, L"CLSID\\"); + StringFromGUID2(&clsid, keypath + wcslen(keypath), ARRAY_SIZE(keypath) - wcslen(keypath)); + wcscat(keypath, L"\\Pins"); +- if ((ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, keypath, 0, 0, &key))) ++ if ((ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, keypath, 0, KEY_ENUMERATE_SUB_KEYS, &key))) + return HRESULT_FROM_WIN32(ret); + + if ((ret = RegDeleteTreeW(key, name))) +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0008-wbemprox-Don-t-open-reg-keys-with-zero-access-mask.patch b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0008-wbemprox-Don-t-open-reg-keys-with-zero-access-mask.patch new file mode 100644 index 0000000..8444a58 --- /dev/null +++ b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0008-wbemprox-Don-t-open-reg-keys-with-zero-access-mask.patch @@ -0,0 +1,25 @@ +From 01935ff588a21b61ab2d76a1dfc641502f599a3e Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Fri, 6 Dec 2024 18:01:37 -0600 +Subject: [PATCH] wbemprox: Don't open reg keys with zero access mask. + +--- + dlls/wbemprox/reg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dlls/wbemprox/reg.c b/dlls/wbemprox/reg.c +index cdfb5d28007..e1a40776c1f 100644 +--- a/dlls/wbemprox/reg.c ++++ b/dlls/wbemprox/reg.c +@@ -106,7 +106,7 @@ static HRESULT create_key( HKEY root, const WCHAR *subkey, IWbemContext *context + + TRACE("%p, %s\n", root, debugstr_w(subkey)); + +- res = RegCreateKeyExW( root, subkey, 0, NULL, 0, get_access_mask( context ), NULL, &hkey, NULL ); ++ res = RegCreateKeyExW( root, subkey, 0, NULL, 0, KEY_ENUMERATE_SUB_KEYS | get_access_mask( context ), NULL, &hkey, NULL ); + set_variant( VT_UI4, res, NULL, retval ); + if (!res) + { +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0009-shell32-Don-t-open-reg-keys-with-zero-access-mask.patch b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0009-shell32-Don-t-open-reg-keys-with-zero-access-mask.patch new file mode 100644 index 0000000..1f19fad --- /dev/null +++ b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0009-shell32-Don-t-open-reg-keys-with-zero-access-mask.patch @@ -0,0 +1,57 @@ +From 7820972c15a4627fe9e1459747efd85d6ee774b4 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Fri, 6 Dec 2024 18:21:19 -0600 +Subject: [PATCH] shell32: Don't open reg keys with zero access mask. + +--- + dlls/shell32/classes.c | 4 ++-- + dlls/shell32/shellpath.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/dlls/shell32/classes.c b/dlls/shell32/classes.c +index a8e70c021c2..399dbf5b4fb 100644 +--- a/dlls/shell32/classes.c ++++ b/dlls/shell32/classes.c +@@ -135,7 +135,7 @@ BOOL HCR_GetDefaultVerbW( HKEY hkeyClass, LPCWSTR szVerb, LPWSTR szDest, DWORD l + lstrcpyW(sTemp, L"shell\\"); + lstrcatW(sTemp, szDest); + lstrcatW(sTemp, L"\\command"); +- if (!RegOpenKeyExW(hkeyClass, sTemp, 0, 0, &hkey)) ++ if (!RegOpenKeyExW(hkeyClass, sTemp, 0, KEY_ENUMERATE_SUB_KEYS, &hkey)) + { + RegCloseKey(hkey); + TRACE("default verb=%s\n", debugstr_w(szDest)); +@@ -145,7 +145,7 @@ BOOL HCR_GetDefaultVerbW( HKEY hkeyClass, LPCWSTR szVerb, LPWSTR szDest, DWORD l + + /* then fallback to 'open' */ + lstrcpyW(sTemp, L"shell\\open\\command"); +- if (!RegOpenKeyExW(hkeyClass, sTemp, 0, 0, &hkey)) ++ if (!RegOpenKeyExW(hkeyClass, sTemp, 0, KEY_ENUMERATE_SUB_KEYS, &hkey)) + { + RegCloseKey(hkey); + lstrcpynW(szDest, L"open", len); +diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c +index 4330ee367b3..95ddf661519 100644 +--- a/dlls/shell32/shellpath.c ++++ b/dlls/shell32/shellpath.c +@@ -3881,7 +3881,7 @@ static HRESULT knownfolder_set_id( + /* check is it registry-registered folder */ + hr = get_known_folder_registry_path(kfid, NULL, &knownfolder->registryPath); + if(SUCCEEDED(hr)) +- hr = HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_LOCAL_MACHINE, knownfolder->registryPath, 0, 0, &hKey)); ++ hr = HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_LOCAL_MACHINE, knownfolder->registryPath, 0, KEY_ENUMERATE_SUB_KEYS, &hKey)); + + if(SUCCEEDED(hr)) + { +@@ -4327,7 +4327,7 @@ static BOOL is_knownfolder( struct foldermanager *fm, const KNOWNFOLDERID *id ) + hr = get_known_folder_registry_path(id, NULL, ®istryPath); + if(SUCCEEDED(hr)) + { +- hr = HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_LOCAL_MACHINE, registryPath, 0, 0, &hKey)); ++ hr = HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_LOCAL_MACHINE, registryPath, 0, KEY_ENUMERATE_SUB_KEYS, &hKey)); + free(registryPath); + } + +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0010-server-Check-for-zero-access-in-alloc-handle-.patch b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0010-server-Check-for-zero-access-in-alloc-handle-.patch new file mode 100644 index 0000000..4d84c95 --- /dev/null +++ b/0003-pending-mrs-and-backports/6047-server-Deny-opening-handles-to-objects-with-zero-access/0010-server-Check-for-zero-access-in-alloc-handle-.patch @@ -0,0 +1,485 @@ +From b0c291a2eff9da6645d2d4adbcce6eb7b8c69abc Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Wed, 10 Jul 2024 16:43:25 -0600 +Subject: [PATCH] server: Check for zero access in alloc_handle(). + +--- + dlls/advapi32/tests/security.c | 4 - + dlls/kernel32/tests/sync.c | 4 +- + dlls/ntdll/tests/om.c | 121 +++++++++++++------------------ + dlls/ntdll/tests/reg.c | 2 - + dlls/ntoskrnl.exe/tests/driver.c | 6 -- + dlls/setupapi/tests/devinst.c | 2 - + server/device.c | 4 +- + server/handle.c | 7 +- + 8 files changed, 59 insertions(+), 91 deletions(-) + +diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c +index e215ab9e5f2..56b10cee97f 100644 +--- a/dlls/advapi32/tests/security.c ++++ b/dlls/advapi32/tests/security.c +@@ -5542,9 +5542,7 @@ static void test_mutex_security(HANDLE token) + + SetLastError(0xdeadbeef); + dup = OpenMutexA(0, FALSE, "WineTestMutex"); +- todo_wine + ok(!dup, "OpenMutex should fail\n"); +- todo_wine + ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu\n", GetLastError()); + } + +@@ -5599,9 +5597,7 @@ static void test_event_security(HANDLE token) + + SetLastError(0xdeadbeef); + dup = OpenEventA(0, FALSE, "WineTestEvent"); +- todo_wine + ok(!dup, "OpenEvent should fail\n"); +- todo_wine + ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu\n", GetLastError()); + } + +diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c +index 49420e4519f..7a6571475c2 100644 +--- a/dlls/kernel32/tests/sync.c ++++ b/dlls/kernel32/tests/sync.c +@@ -248,9 +248,7 @@ static void test_mutex(void) + + SetLastError(0xdeadbeef); + hOpened = OpenMutexA(0, FALSE, "WineTestMutex"); +- todo_wine + ok(hOpened == NULL, "OpenMutex succeeded\n"); +- todo_wine + ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); +@@ -289,7 +287,7 @@ static void test_mutex(void) + if ((1 << i) == ACCESS_SYSTEM_SECURITY) + todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %lu, access %x\n", GetLastError(), 1 << i); + else +- todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu, , access %x\n", GetLastError(), 1 << i); ++ ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu, , access %x\n", GetLastError(), 1 << i); + ReleaseMutex(hCreated); + failed |=0x1 << i; + } +diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c +index cbc4ad27921..91284fc3c49 100644 +--- a/dlls/ntdll/tests/om.c ++++ b/dlls/ntdll/tests/om.c +@@ -30,6 +30,7 @@ + #include "winternl.h" + #include "wingdi.h" + #include "winuser.h" ++#include "winreg.h" + #include "ddk/wdm.h" + #include "wine/test.h" + +@@ -3392,6 +3393,7 @@ static void test_zero_access(void) + CLIENT_ID cid; + HANDLE h1, h2; + DWORD err; ++ HKEY key; + + size.QuadPart = 4096; + timeout.QuadPart = -10000; +@@ -3410,18 +3412,15 @@ static void test_zero_access(void) + ok( status == STATUS_OBJECT_NAME_EXISTS, "got %#lx.\n", status ); + CloseHandle( h2 ); + status = pNtCreateEvent( &h2, 0, &attr, NotificationEvent, FALSE ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtOpenEvent( &h2, EVENT_ALL_ACCESS, &attr ); + ok( !status, "got %#lx.\n", status ); + CloseHandle( h2 ); + status = pNtOpenEvent( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + InitializeObjectAttributes( &attr, &str, OBJ_INHERIT, 0, NULL ); + status = pNtOpenEvent( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + + status = pNtDuplicateObject( GetCurrentProcess(), h1, GetCurrentProcess(), &h2, 0, 0, 0 ); + ok( !status, "got %#lx.\n", status ); +@@ -3443,11 +3442,9 @@ static void test_zero_access(void) + ok( status == STATUS_OBJECT_NAME_EXISTS, "got %#lx.\n", status ); + CloseHandle( h2 ); + status = pNtCreateMutant( &h2, 0, &attr, FALSE ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtOpenMutant( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + CloseHandle( h1 ); + + status = pNtCreateSemaphore( &h1, 0, &attr, 1, 2 ); +@@ -3461,11 +3458,9 @@ static void test_zero_access(void) + ok( status == STATUS_OBJECT_NAME_EXISTS, "got %#lx.\n", status ); + CloseHandle( h2 ); + status = pNtCreateSemaphore( &h2, 0, &attr, 1, 2 ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtOpenSemaphore( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + CloseHandle( h1 ); + + status = pNtCreateKeyedEvent( &h1, 0, &attr, 0 ); +@@ -3479,11 +3474,9 @@ static void test_zero_access(void) + ok( status == STATUS_OBJECT_NAME_EXISTS, "got %#lx.\n", status ); + CloseHandle( h2 ); + status = pNtCreateKeyedEvent( &h2, 0, &attr, 0 ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtOpenKeyedEvent( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + CloseHandle( h1 ); + + status = pNtCreateIoCompletion( &h1, 0, &attr, 0 ); +@@ -3497,11 +3490,9 @@ static void test_zero_access(void) + ok( status == STATUS_OBJECT_NAME_EXISTS, "got %#lx.\n", status ); + CloseHandle( h2 ); + status = pNtCreateIoCompletion( &h2, 0, &attr, 0 ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtOpenIoCompletion( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + CloseHandle( h1 ); + + status = pNtCreateJobObject( &h1, 0, &attr ); +@@ -3516,11 +3507,9 @@ static void test_zero_access(void) + "got %#lx.\n", status ); + if (NT_SUCCESS(status)) CloseHandle( h2 ); + status = pNtCreateJobObject( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtOpenJobObject( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + CloseHandle( h1 ); + + status = pNtCreateDirectoryObject( &h1, 0, &attr ); +@@ -3534,11 +3523,9 @@ static void test_zero_access(void) + ok( status == STATUS_OBJECT_NAME_EXISTS, "got %#lx.\n", status ); + CloseHandle( h2 ); + status = pNtCreateDirectoryObject( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtOpenDirectoryObject( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + CloseHandle( h1 ); + + status = pNtCreateTimer( &h1, 0, &attr, NotificationTimer ); +@@ -3552,11 +3539,9 @@ static void test_zero_access(void) + ok( status == STATUS_OBJECT_NAME_EXISTS, "got %#lx.\n", status ); + CloseHandle( h2 ); + status = pNtCreateTimer( &h2, 0, &attr, NotificationTimer ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtOpenTimer( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + CloseHandle( h1 ); + + status = pNtCreateSymbolicLinkObject( &h1, 0, &attr, &target ); +@@ -3571,11 +3556,9 @@ static void test_zero_access(void) + "got %#lx.\n", status ); + CloseHandle( h2 ); + status = pNtCreateSymbolicLinkObject( &h2, 0, &attr, &target ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtOpenSymbolicLinkObject( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + CloseHandle( h1 ); + + status = pNtCreateSection( &h1, 0, &attr, &size, PAGE_READWRITE, SEC_COMMIT, 0 ); +@@ -3589,11 +3572,9 @@ static void test_zero_access(void) + ok( status == STATUS_OBJECT_NAME_EXISTS, "got %#lx.\n", status ); + CloseHandle( h2 ); + status = pNtCreateSection( &h2, 0, &attr, &size, PAGE_READWRITE, SEC_COMMIT, 0 ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtOpenSection( &h2, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + CloseHandle( h1 ); + + status = pNtCreateDebugObject( &h1, 0, &attr, 0 ); +@@ -3605,8 +3586,7 @@ static void test_zero_access(void) + ok( status == STATUS_OBJECT_NAME_EXISTS, "got %#lx.\n", status ); + CloseHandle( h2 ); + status = pNtCreateDebugObject( &h2, 0, &attr, 0 ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + CloseHandle( h1 ); + + pRtlInitUnicodeString( &str, L"\\Device\\Null" ); +@@ -3616,8 +3596,7 @@ static void test_zero_access(void) + CloseHandle( h1 ); + status = NtCreateFile( &h1, 0, &attr, &iosb, NULL, 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, 0, NULL, 0 ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h1 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + + pRtlInitUnicodeString( &str, L"\\??\\c:\\windows\\system32\\ntdll.dll" ); + status = NtCreateFile( &h1, GENERIC_READ | SYNCHRONIZE, &attr, &iosb, NULL, 0, +@@ -3626,13 +3605,11 @@ static void test_zero_access(void) + CloseHandle( h1 ); + status = NtCreateFile( &h1, 0, &attr, &iosb, NULL, 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, 0, NULL, 0 ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h1 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + + pRtlInitUnicodeString( &str, L"\\Device\\MailSlot\\abc" ); + status = pNtCreateMailslotFile( &h1, 0, &attr, &iosb, 0, 0, 0, NULL ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h1 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtCreateMailslotFile( &h1, GENERIC_ALL, &attr, &iosb, 0, 0, 0, NULL ); + ok( !status, "got %#lx.\n", status ); + status = pNtCreateMailslotFile( &h2, GENERIC_READ, &attr, &iosb, 0, 0, 0, NULL ); +@@ -3645,8 +3622,7 @@ static void test_zero_access(void) + status = pNtCreateNamedPipeFile( &h1, 0, &attr, &iosb, + FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_CREATE, + FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h1 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtCreateNamedPipeFile( &h1, GENERIC_READ | GENERIC_WRITE, &attr, &iosb, + FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_CREATE, + FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout ); +@@ -3659,22 +3635,29 @@ static void test_zero_access(void) + FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, + FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout ); + todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h2 ); + CloseHandle( h1 ); + + pRtlInitUnicodeString( &str, L"\\REGISTRY\\Machine" ); + status = pNtCreateKey( &h1, 0, &attr, 0, 0, 0, 0 ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h1 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + status = pNtCreateKey( &h1, KEY_READ, &attr, 0, 0, 0, 0 ); + ok( !status, "got %#lx.\n", status ); + CloseHandle( h1 ); + status = pNtOpenKey( &h1, KEY_READ, &attr ); + ok( !status, "got %#lx.\n", status ); + CloseHandle( h1 ); ++ err = RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"Software", 0, KEY_READ | KEY_WOW64_64KEY, &key); ++ ok( !err, "got %#lx.\n", status ); ++ RegCloseKey( key ); ++ err = RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"Software", 0, KEY_READ | KEY_WOW64_32KEY, &key); ++ ok( !err, "got %#lx.\n", status ); ++ RegCloseKey( key ); + status = pNtOpenKey( &h1, 0, &attr ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h1 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); ++ err = RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"Software", 0, KEY_WOW64_64KEY, &key); ++ ok( err == ERROR_ACCESS_DENIED, "got %#lx.\n", status ); ++ err = RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"Software", 0, KEY_WOW64_32KEY, &key); ++ ok( err == ERROR_ACCESS_DENIED, "got %#lx.\n", status ); + + pRtlInitUnicodeString( &str, L"\\REGISTRY\\Machine\\Software\\foobar-test" ); + status = pNtCreateKey( &h1, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); +@@ -3697,26 +3680,22 @@ static void test_zero_access(void) + ok( !status, "got %#lx.\n", status ); + CloseHandle( h1 ); + status = pNtOpenProcessToken( GetCurrentProcess(), 0, &h1 ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h1 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + + status = NtGetNextThread(GetCurrentProcess(), NULL, 0, 0, 0, &h1); +- todo_wine ok( status == STATUS_NO_MORE_ENTRIES, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h1 ); ++ ok( status == STATUS_NO_MORE_ENTRIES, "got %#lx.\n", status ); + + InitializeObjectAttributes( &attr, NULL, 0, 0, NULL ); + cid.UniqueProcess = ULongToHandle( GetCurrentProcessId() ); + cid.UniqueThread = 0; + status = pNtOpenProcess( &h1, 0, &attr, &cid ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h1 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + + InitializeObjectAttributes( &attr, NULL, 0, 0, NULL ); + cid.UniqueProcess = 0; + cid.UniqueThread = ULongToHandle( GetCurrentThreadId() ); + status = pNtOpenThread( &h1, 0, &attr, &cid ); +- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); +- if (NT_SUCCESS(status)) CloseHandle( h1 ); ++ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); + + h1 = CreateWindowStationA( "WinSta0", 0, WINSTA_ALL_ACCESS, NULL ); + err = GetLastError(); +@@ -3728,8 +3707,8 @@ static void test_zero_access(void) + CloseWindowStation( h1 ); + h1 = CreateWindowStationA( "WinSta0", 0, 0, NULL ); + err = GetLastError(); +- todo_wine ok( !h1, "CreateWindowStationA succeeded\n" ); +- todo_wine ok( err == ERROR_ACCESS_DENIED, "CreateWindowStationA failed %lu\n", err ); ++ ok( !h1, "CreateWindowStationA succeeded\n" ); ++ ok( err == ERROR_ACCESS_DENIED, "CreateWindowStationA failed %lu\n", err ); + if (h1) CloseWindowStation( h1 ); + } + else if (err == ERROR_ACCESS_DENIED) win_skip( "Not enough privileges for CreateWindowStation\n" ); +@@ -3739,8 +3718,8 @@ static void test_zero_access(void) + CloseWindowStation( h1 ); + h1 = OpenWindowStationA( "WinSta0", TRUE, 0 ); + err = GetLastError(); +- todo_wine ok( !h1, "OpenWindowStation succeeeded\n" ); +- todo_wine ok( err == ERROR_ACCESS_DENIED, "OpenWindowStation failed %lu\n", err ); ++ ok( !h1, "OpenWindowStation succeeeded\n" ); ++ ok( err == ERROR_ACCESS_DENIED, "OpenWindowStation failed %lu\n", err ); + if (h1) CloseWindowStation( h1 ); + + h1 = CreateDesktopA( "default", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL ); +@@ -3749,8 +3728,8 @@ static void test_zero_access(void) + SetLastError( 0xdeadbeef ); + h1 = CreateDesktopA( "default", NULL, NULL, 0, 0, NULL ); + err = GetLastError(); +- todo_wine ok( !h1, "CreateDesktopA succeeded\n" ); +- todo_wine ok( err == ERROR_ACCESS_DENIED, "CreateDesktopA failed %lu\n", err ); ++ ok( !h1, "CreateDesktopA succeeded\n" ); ++ ok( err == ERROR_ACCESS_DENIED, "CreateDesktopA failed %lu\n", err ); + if (h1) CloseDesktop( h1 ); + + h1 = OpenDesktopA( "default", 0, TRUE, DESKTOP_ALL_ACCESS ); +diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c +index f264f42e98d..2760c1b4472 100644 +--- a/dlls/ntdll/tests/reg.c ++++ b/dlls/ntdll/tests/reg.c +@@ -253,9 +253,7 @@ static void test_NtOpenKey(void) + attr.Length = sizeof(attr); + key = (HANDLE)0xdeadbeef; + status = pNtOpenKey(&key, 0, &attr); +- todo_wine + ok(status == STATUS_ACCESS_DENIED, "Expected STATUS_ACCESS_DENIED, got: 0x%08lx\n", status); +- todo_wine + ok(!key, "key = %p\n", key); + if (status == STATUS_SUCCESS) NtClose(key); + +diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c +index 7194dc403d7..dd8b2f4ffee 100644 +--- a/dlls/ntoskrnl.exe/tests/driver.c ++++ b/dlls/ntoskrnl.exe/tests/driver.c +@@ -2292,19 +2292,15 @@ static void test_permanence(void) + status = ZwOpenDirectoryObject( &handle, DIRECTORY_ALL_ACCESS, &attr ); + ok(!status, "got %#lx\n", status); + status = ZwMakeTemporaryObject( handle ); +- todo_wine + ok(!status, "got %#lx\n", status); + status = ZwMakeTemporaryObject( handle ); +- todo_wine + ok(!status, "got %#lx\n", status); + status = ZwClose( handle ); + ok(!status, "got %#lx\n", status); + status = ZwOpenDirectoryObject( &handle, 0, &attr ); +- todo_wine + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %#lx\n", status); + + status = ZwCreateDirectoryObject( &handle, GENERIC_ALL, &attr ); +- todo_wine + ok(!status, "got %#lx\n", status); + attr.Attributes = OBJ_PERMANENT; + status = ZwOpenDirectoryObject( &handle2, DIRECTORY_ALL_ACCESS, &attr ); +@@ -2312,11 +2308,9 @@ static void test_permanence(void) + status = ZwClose( handle2 ); + ok(!status, "got %#lx\n", status); + status = ZwClose( handle ); +- todo_wine + ok(!status, "got %#lx\n", status); + attr.Attributes = 0; + status = ZwOpenDirectoryObject( &handle, 0, &attr ); +- todo_wine + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %#lx\n", status); + if (!status) ZwClose( handle ); + } +diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c +index c5c0114b2b7..0c902ce783b 100644 +--- a/dlls/setupapi/tests/devinst.c ++++ b/dlls/setupapi/tests/devinst.c +@@ -1948,11 +1948,9 @@ static void test_device_key(void) + + SetLastError(0xdeadbeef); + key = SetupDiOpenDevRegKey(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DRV, 0); +-todo_wine { + ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_DATA || GetLastError() == ERROR_ACCESS_DENIED, /* win2k3 */ + "Got unexpected error %#lx.\n", GetLastError()); +-} + + key = SetupDiOpenDevRegKey(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ); + ok(key != INVALID_HANDLE_VALUE, "Failed to open device key, error %#lx.\n", GetLastError()); +diff --git a/server/device.c b/server/device.c +index cab09700d8c..1f93cca437d 100644 +--- a/server/device.c ++++ b/server/device.c +@@ -1003,7 +1003,7 @@ DECL_HANDLER(get_next_device_request) + + if (iosb && iosb->in_size > get_reply_max_size()) + set_error( STATUS_BUFFER_OVERFLOW ); +- else if (!irp->file || (reply->next = alloc_handle( current->process, irp, 0, 0 ))) ++ else if (!irp->file || (reply->next = alloc_handle_no_access_check( current->process, irp, 0, 0 ))) + { + if (fill_irp_params( manager, irp, &reply->params )) + { +@@ -1137,7 +1137,7 @@ DECL_HANDLER(get_kernel_object_handle) + return; + + if ((ref = kernel_object_from_ptr( manager, req->user_ptr ))) +- reply->handle = alloc_handle( current->process, ref->object, req->access, 0 ); ++ reply->handle = alloc_handle_no_access_check( current->process, ref->object, req->access, 0 ); + else + set_error( STATUS_INVALID_HANDLE ); + +diff --git a/server/handle.c b/server/handle.c +index e65831b3b22..b7e9cf80121 100644 +--- a/server/handle.c ++++ b/server/handle.c +@@ -284,7 +284,12 @@ obj_handle_t alloc_handle( struct process *process, void *ptr, unsigned int acce + { + struct object *obj = ptr; + access = obj->ops->map_access( obj, access ) & ~RESERVED_ALL; +- if (access && !check_object_access( NULL, obj, &access )) return 0; ++ if (!access) ++ { ++ set_error( STATUS_ACCESS_DENIED ); ++ return 0; ++ } ++ if (!check_object_access( NULL, obj, &access )) return 0; + return alloc_handle_entry( process, ptr, access, attr ); + } + +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6385-gdi32-Fix-the-text-s-charset-error-in-obtaining-from-meta-dc/0001-gdi32-Fix-the-text-s-charset-error-in-obtaining-from-meta-dc.patch b/0003-pending-mrs-and-backports/6385-gdi32-Fix-the-text-s-charset-error-in-obtaining-from-meta-dc/0001-gdi32-Fix-the-text-s-charset-error-in-obtaining-from-meta-dc.patch deleted file mode 100644 index c58b198..0000000 --- a/0003-pending-mrs-and-backports/6385-gdi32-Fix-the-text-s-charset-error-in-obtaining-from-meta-dc/0001-gdi32-Fix-the-text-s-charset-error-in-obtaining-from-meta-dc.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 733cc49564b2d01c05e003f6591b1af23ef55bc1 Mon Sep 17 00:00:00 2001 -From: chenjiangyi -Date: Wed, 28 Aug 2024 09:59:07 +0800 -Subject: [PATCH] gdi32: Fix the text's charset error in obtaining from meta - dc. - -Log: get_dc_attr always failed for meta dc,so GdiGetCodePage always -return CP_ACP. And GetTextCharset is similar to this situation. -Finally, leading to an error result of text_mbtowc call by ExtTextOutA -and an error result of METADC_ExtTextOut. - -Signed-off-by: chenjiangyi -Change-Id: Icb6a8d57848935bc5c1b3913c155148af43eca0d ---- - dlls/gdi32/gdi_private.h | 1 + - dlls/gdi32/metadc.c | 37 +++++++++++++++++++++++++++++++++ - dlls/gdi32/text.c | 45 ++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 83 insertions(+) - -diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h -index 8fa5c06e014..0696de8c753 100644 ---- a/dlls/gdi32/gdi_private.h -+++ b/dlls/gdi32/gdi_private.h -@@ -94,6 +94,7 @@ BOOL METADC_ExtTextOut( HDC hdc, INT x, INT y, UINT flags, const RECT *rect, - BOOL METADC_FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush ); - BOOL METADC_FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush, INT x, INT y ); - INT METADC_GetDeviceCaps( HDC hdc, INT cap ); -+UINT METADC_GetTextCharset( HDC hdc ); - BOOL METADC_IntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bottom ); - BOOL METADC_InvertRgn( HDC hdc, HRGN hrgn ); - BOOL METADC_LineTo( HDC hdc, INT x, INT y ); -diff --git a/dlls/gdi32/metadc.c b/dlls/gdi32/metadc.c -index dbfa311b711..3e4b4a4eb2b 100644 ---- a/dlls/gdi32/metadc.c -+++ b/dlls/gdi32/metadc.c -@@ -1269,6 +1269,43 @@ BOOL METADC_ExtEscape( HDC hdc, INT escape, INT input_size, const void *input, - return ret; - } - -+static inline WCHAR facename_tolower( WCHAR c ) -+{ -+ if (c >= 'A' && c <= 'Z') return c - 'A' + 'a'; -+ else if (c > 127) return RtlDowncaseUnicodeChar( c ); -+ else return c; -+} -+ -+static inline int facename_compare( const WCHAR *str1, const WCHAR *str2, SIZE_T len ) -+{ -+ while (len--) -+ { -+ WCHAR c1 = facename_tolower( *str1++ ), c2 = facename_tolower( *str2++ ); -+ if (c1 != c2) return c1 - c2; -+ else if (!c1) return 0; -+ } -+ return 0; -+} -+ -+UINT METADC_GetTextCharset( HDC hdc ) -+{ -+ UINT ret = DEFAULT_CHARSET; -+ struct metadc *metadc; -+ static const WCHAR symbolW[] = {'S','y','m','b','o','l',0}; -+ -+ if(!(metadc = get_metadc_ptr( hdc ))) return ret; -+ if(metadc->font) -+ { -+ LOGFONTW lf; -+ NtGdiExtGetObjectW( metadc->font, sizeof(lf), &lf ); -+ if (!facename_compare( lf.lfFaceName, symbolW, -1 )) -+ lf.lfCharSet = SYMBOL_CHARSET; -+ return lf.lfCharSet; -+ } -+ -+ return ret; -+} -+ - INT METADC_GetDeviceCaps( HDC hdc, INT cap ) - { - if (!get_metadc_ptr( hdc )) return 0; -diff --git a/dlls/gdi32/text.c b/dlls/gdi32/text.c -index ff548306dc3..e7a92fc05f5 100644 ---- a/dlls/gdi32/text.c -+++ b/dlls/gdi32/text.c -@@ -830,7 +830,51 @@ static void logfontex_WtoA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA - */ - DWORD WINAPI GdiGetCodePage( HDC hdc ) - { -+ CHARSETINFO csi; - DC_ATTR *dc_attr = get_dc_attr( hdc ); -+ -+ if(is_meta_dc(hdc)) -+ { -+ UINT charset = METADC_GetTextCharset(hdc); -+ UINT cp = CP_ACP; -+ if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET )) -+ cp = csi.ciACP; -+ else -+ { -+ switch(charset) -+ { -+ case OEM_CHARSET: -+ cp = GetOEMCP(); -+ break; -+ case DEFAULT_CHARSET: -+ cp = GetACP(); -+ break; -+ -+ case VISCII_CHARSET: -+ case TCVN_CHARSET: -+ case KOI8_CHARSET: -+ case ISO3_CHARSET: -+ case ISO4_CHARSET: -+ case ISO10_CHARSET: -+ case CELTIC_CHARSET: -+ /* FIXME: These have no place here, but because x11drv -+ enumerates fonts with these (made up) charsets some apps -+ might use them and then the FIXME below would become -+ annoying. Now we could pick the intended codepage for -+ each of these, but since it's broken anyway we'll just -+ use CP_ACP and hope it'll go away... -+ */ -+ cp = CP_ACP; -+ break; -+ -+ default: -+ FIXME("Can't find codepage for charset %d\n", charset); -+ break; -+ } -+ } -+ return cp; -+ } -+ - return dc_attr ? dc_attr->font_code_page : CP_ACP; - } - -@@ -2086,6 +2130,7 @@ BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, SIZE *aspect_ratio ) - */ - UINT WINAPI GetTextCharset( HDC hdc ) - { -+ if(is_meta_dc(hdc)) return METADC_GetTextCharset(hdc); - /* MSDN docs say this is equivalent */ - return NtGdiGetTextCharsetInfo( hdc, NULL, 0 ); - } --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6585-win32u-Try-the-next-top-level-window-if-hit-testing-the-result-window-returns-HTTRANSPARENT/0001-win32u-Try-the-next-top-level-window-if-hit-testing-the-result-window-returns-HTTRANSPARENT.patch b/0003-pending-mrs-and-backports/6585-win32u-Try-the-next-top-level-window-if-hit-testing-the-result-window-returns-HTTRANSPARENT/0001-win32u-Try-the-next-top-level-window-if-hit-testing-the-result-window-returns-HTTRANSPARENT.patch deleted file mode 100644 index b80e631..0000000 --- a/0003-pending-mrs-and-backports/6585-win32u-Try-the-next-top-level-window-if-hit-testing-the-result-window-returns-HTTRANSPARENT/0001-win32u-Try-the-next-top-level-window-if-hit-testing-the-result-window-returns-HTTRANSPARENT.patch +++ /dev/null @@ -1,51 +0,0 @@ -From e6f9195474ba834177cdedc1fd1bb04efd54bd8c Mon Sep 17 00:00:00 2001 -From: Zhiyi Zhang -Date: Mon, 23 Sep 2024 16:53:41 +0800 -Subject: [PATCH] win32u: Try the next top-level window if hit-testing the - result window returns HTTRANSPARENT. - -Fix clicking Toad for Oracle treeview nodes doesn't function. The left button click is sent to a -top-level TSafeHintWindow, which returns HTTRANSPARENT when handling WM_NCHITTEST. Tests show that -in such cases, the mouse message should be sent to the next top-level window in the z-order. ---- - dlls/user32/tests/input.c | 8 ++++---- - dlls/win32u/message.c | 2 ++ - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c -index 9196e67c15b..677b2714fcc 100644 ---- a/dlls/user32/tests/input.c -+++ b/dlls/user32/tests/input.c -@@ -4233,12 +4233,12 @@ static void test_SendInput_mouse_messages(void) - - mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 ); - wait_messages( 5, FALSE ); -- button_down_hwnd_todo[1].message.hwnd = hwnd; -- ok_seq( button_down_hwnd_todo ); -+ button_down_hwnd[1].message.hwnd = hwnd; -+ ok_seq( button_down_hwnd ); - mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); - wait_messages( 5, FALSE ); -- button_up_hwnd_todo[1].message.hwnd = hwnd; -- ok_seq( button_up_hwnd_todo ); -+ button_up_hwnd[1].message.hwnd = hwnd; -+ ok_seq( button_up_hwnd ); - - ok_ret( 1, DestroyWindow( other ) ); - wait_messages( 0, FALSE ); -diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c -index a0cbfbce95c..3d0db361d78 100644 ---- a/dlls/win32u/message.c -+++ b/dlls/win32u/message.c -@@ -2444,6 +2444,8 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H - is_current_thread_window( next )) - msg->hwnd = window_from_point( next, msg->pt, &hittest ); - } -+ if (!msg->hwnd) /* Try the next top-level window */ -+ msg->hwnd = window_from_point( 0, msg->pt, &hittest ); - } - - if (!msg->hwnd || !is_current_thread_window( msg->hwnd )) --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6800-winegstreamer-Lock-the-media-source-critical-section-while-using-the-event-queue/0001-winegstreamer-Lock-the-media-source-critical-section-while-using-the-event-queue.patch b/0003-pending-mrs-and-backports/6800-winegstreamer-Lock-the-media-source-critical-section-while-using-the-event-queue/0001-winegstreamer-Lock-the-media-source-critical-section-while-using-the-event-queue.patch deleted file mode 100644 index e68399e..0000000 --- a/0003-pending-mrs-and-backports/6800-winegstreamer-Lock-the-media-source-critical-section-while-using-the-event-queue/0001-winegstreamer-Lock-the-media-source-critical-section-while-using-the-event-queue.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 80f9807d6ed9eba1d446d0e9c433d3bc104ff0a9 Mon Sep 17 00:00:00 2001 -From: Conor McCarthy -Date: Tue, 12 Nov 2024 00:16:25 +1000 -Subject: [PATCH] winegstreamer: Lock the media source critical section while - using the event queue. - ---- - dlls/winegstreamer/media_source.c | 66 ++++++++++++++++++++++++++++--- - 1 file changed, 60 insertions(+), 6 deletions(-) - -diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c -index 030d0c1b9a2..74b86d1f7c5 100644 ---- a/dlls/winegstreamer/media_source.c -+++ b/dlls/winegstreamer/media_source.c -@@ -1376,38 +1376,92 @@ static ULONG WINAPI media_source_Release(IMFMediaSource *iface) - static HRESULT WINAPI media_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event) - { - struct media_source *source = impl_from_IMFMediaSource(iface); -+ IMFMediaEventQueue *event_queue = NULL; -+ HRESULT hr = S_OK; - - TRACE("%p, %#lx, %p.\n", iface, flags, event); - -- return IMFMediaEventQueue_GetEvent(source->event_queue, flags, event); -+ EnterCriticalSection(&source->cs); -+ -+ /* GetEvent() is blocking, so we safely get an event queue -+ * pointer and then unlock the CS */ -+ if (source->state == SOURCE_SHUTDOWN) -+ hr = MF_E_SHUTDOWN; -+ else -+ { -+ event_queue = source->event_queue; -+ IMFMediaEventQueue_AddRef(event_queue); -+ } -+ -+ LeaveCriticalSection(&source->cs); -+ -+ if (SUCCEEDED(hr)) -+ { -+ hr = IMFMediaEventQueue_GetEvent(event_queue, flags, event); -+ IMFMediaEventQueue_Release(event_queue); -+ } -+ -+ return hr; - } - - static HRESULT WINAPI media_source_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state) - { - struct media_source *source = impl_from_IMFMediaSource(iface); -+ HRESULT hr; - - TRACE("%p, %p, %p.\n", iface, callback, state); - -- return IMFMediaEventQueue_BeginGetEvent(source->event_queue, callback, state); -+ /* In the event-handling methods we lock the source CS to -+ * ensure the queue isn't shut down before we use it */ -+ EnterCriticalSection(&source->cs); -+ -+ if (source->state == SOURCE_SHUTDOWN) -+ hr = MF_E_SHUTDOWN; -+ else -+ hr = IMFMediaEventQueue_BeginGetEvent(source->event_queue, callback, state); -+ -+ LeaveCriticalSection(&source->cs); -+ -+ return hr; - } - - static HRESULT WINAPI media_source_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event) - { - struct media_source *source = impl_from_IMFMediaSource(iface); -+ HRESULT hr; - - TRACE("%p, %p, %p.\n", iface, result, event); - -- return IMFMediaEventQueue_EndGetEvent(source->event_queue, result, event); -+ EnterCriticalSection(&source->cs); -+ -+ if (source->state == SOURCE_SHUTDOWN) -+ hr = MF_E_SHUTDOWN; -+ else -+ hr = IMFMediaEventQueue_EndGetEvent(source->event_queue, result, event); -+ -+ LeaveCriticalSection(&source->cs); -+ -+ return hr; - } - - static HRESULT WINAPI media_source_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type, -- HRESULT hr, const PROPVARIANT *value) -+ HRESULT status, const PROPVARIANT *value) - { - struct media_source *source = impl_from_IMFMediaSource(iface); -+ HRESULT hr; - -- TRACE("%p, %lu, %s, %#lx, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value); -+ TRACE("%p, %lu, %s, %#lx, %p.\n", iface, event_type, debugstr_guid(ext_type), status, value); -+ -+ EnterCriticalSection(&source->cs); - -- return IMFMediaEventQueue_QueueEventParamVar(source->event_queue, event_type, ext_type, hr, value); -+ if (source->state == SOURCE_SHUTDOWN) -+ hr = MF_E_SHUTDOWN; -+ else -+ hr = IMFMediaEventQueue_QueueEventParamVar(source->event_queue, event_type, ext_type, status, value); -+ -+ LeaveCriticalSection(&source->cs); -+ -+ return hr; - } - - static HRESULT WINAPI media_source_GetCharacteristics(IMFMediaSource *iface, DWORD *characteristics) --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6838-msi-Dynamically-determine-supported-package-architectures/0001-msi-Dynamically-determine-supported-package-architectures.patch b/0003-pending-mrs-and-backports/6838-msi-Dynamically-determine-supported-package-architectures/0001-msi-Dynamically-determine-supported-package-architectures.patch deleted file mode 100644 index 46aedb5..0000000 --- a/0003-pending-mrs-and-backports/6838-msi-Dynamically-determine-supported-package-architectures/0001-msi-Dynamically-determine-supported-package-architectures.patch +++ /dev/null @@ -1,74 +0,0 @@ -From ae5cb5e456689038535285fd81f16bf1ff77c95b Mon Sep 17 00:00:00 2001 -From: Billy Laws -Date: Wed, 4 Sep 2024 13:36:54 +0000 -Subject: [PATCH] msi: Dynamically determine supported package architectures. - ---- - dlls/msi/package.c | 46 ++++++++++++++++++++++++++++++---------------- - 1 file changed, 30 insertions(+), 16 deletions(-) - -diff --git a/dlls/msi/package.c b/dlls/msi/package.c -index 89b4c09dfa4..699c599c410 100644 ---- a/dlls/msi/package.c -+++ b/dlls/msi/package.c -@@ -1158,27 +1158,41 @@ static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package ) - return ERROR_SUCCESS; - } - -+static BOOLEAN validate_package_platform( enum platform platform ) -+{ -+ USHORT proc_machine, native_machine; -+ IsWow64Process2( GetCurrentProcess(), &proc_machine, &native_machine ); -+ switch (platform) -+ { -+ case PLATFORM_UNRECOGNIZED: -+ return TRUE; -+ case PLATFORM_INTEL: -+ return native_machine == IMAGE_FILE_MACHINE_I386 || -+ native_machine == IMAGE_FILE_MACHINE_AMD64 || -+ native_machine == IMAGE_FILE_MACHINE_ARM64; -+ case PLATFORM_X64: -+ return native_machine == IMAGE_FILE_MACHINE_AMD64 || -+ native_machine == IMAGE_FILE_MACHINE_ARM64; -+ case PLATFORM_ARM: -+ return native_machine == IMAGE_FILE_MACHINE_ARM; -+ case PLATFORM_ARM64: -+ return native_machine == IMAGE_FILE_MACHINE_ARM64; -+ case PLATFORM_INTEL64: -+ default: -+ return FALSE; -+ } -+} -+ - static UINT validate_package( MSIPACKAGE *package ) - { - UINT i; - -- if (package->platform == PLATFORM_INTEL64) -- return ERROR_INSTALL_PLATFORM_UNSUPPORTED; --#ifndef __arm__ -- if (package->platform == PLATFORM_ARM) -- return ERROR_INSTALL_PLATFORM_UNSUPPORTED; --#endif --#ifndef __aarch64__ -- if (package->platform == PLATFORM_ARM64) -+ if (!validate_package_platform( package->platform )) - return ERROR_INSTALL_PLATFORM_UNSUPPORTED; --#endif -- if (package->platform == PLATFORM_X64) -- { -- if (!is_64bit && !is_wow64) -- return ERROR_INSTALL_PLATFORM_UNSUPPORTED; -- if (package->version < 200) -- return ERROR_INSTALL_PACKAGE_INVALID; -- } -+ -+ if (package->platform == PLATFORM_X64 && package->version < 200) -+ return ERROR_INSTALL_PACKAGE_INVALID; -+ - if (!package->num_langids) - { - return ERROR_SUCCESS; --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6904-ntdll-dll-Update-NtQueryDirectoryFile-to-align-with-current-Windows-behaviour/0001-ntdll-Update-NtQueryDirectoryFile-to-purge-cache-if-scan-is-reset-with-a-new-mask.patch b/0003-pending-mrs-and-backports/6904-ntdll-dll-Update-NtQueryDirectoryFile-to-align-with-current-Windows-behaviour/0001-ntdll-Update-NtQueryDirectoryFile-to-purge-cache-if-scan-is-reset-with-a-new-mask.patch new file mode 100644 index 0000000..d98ceb7 --- /dev/null +++ b/0003-pending-mrs-and-backports/6904-ntdll-dll-Update-NtQueryDirectoryFile-to-align-with-current-Windows-behaviour/0001-ntdll-Update-NtQueryDirectoryFile-to-purge-cache-if-scan-is-reset-with-a-new-mask.patch @@ -0,0 +1,138 @@ +From 2d3ccc3847589c80a0591418b62d2d0677c71a48 Mon Sep 17 00:00:00 2001 +From: Eugene McArdle +Date: Fri, 29 Nov 2024 10:32:05 +1000 +Subject: [PATCH] ntdll: Update NtQueryDirectoryFile to purge cache if scan is + reset with a new mask + +--- + dlls/ntdll/unix/file.c | 55 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 53 insertions(+), 2 deletions(-) + +diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c +index 13dc36b42ff..3baa4aa611d 100644 +--- a/dlls/ntdll/unix/file.c ++++ b/dlls/ntdll/unix/file.c +@@ -225,6 +225,7 @@ struct dir_data + struct file_identity id; /* directory file identity */ + struct dir_data_names *names; /* directory file names */ + struct dir_data_buffer *buffer; /* head of data buffers list */ ++ UNICODE_STRING mask; /* the mask used when creating the cache entry */ + }; + + static const unsigned int dir_data_buffer_initial_size = 4096; +@@ -565,6 +566,7 @@ static void free_dir_data( struct dir_data *data ) + free( buffer ); + } + free( data->names ); ++ if (data->mask.Buffer) free( data->mask.Buffer ); + free( data ); + } + +@@ -2606,6 +2608,14 @@ static NTSTATUS init_cached_dir_data( struct dir_data **data_ret, int fd, const + return status; + } + ++ /* if a mask was specified then copy it into the cache entry */ ++ if (mask && mask->Length) ++ { ++ data->mask.Length = data->mask.MaximumLength = mask->Length; ++ if (!(data->mask.Buffer = calloc( 1, mask->Length ))) return STATUS_NO_MEMORY; ++ memcpy(data->mask.Buffer, mask->Buffer, mask->Length); ++ } ++ + /* sort filenames, but not "." and ".." */ + i = 0; + if (i < data->count && !strcmp( data->names[i].unix_name, "." )) i++; +@@ -2628,17 +2638,35 @@ static NTSTATUS init_cached_dir_data( struct dir_data **data_ret, int fd, const + } + + ++/*********************************************************************** ++ * ustring_equal ++ * ++ * Simplified version of RtlEqualUnicodeString that performs only case-sensitive comparisons. ++ */ ++static BOOLEAN ustring_equal( const UNICODE_STRING *a, const UNICODE_STRING *b ) ++{ ++ USHORT length_a = (a ? a->Length : 0); ++ USHORT length_b = (b ? b->Length : 0); ++ if (length_a != length_b) return FALSE; ++ ++ if (length_a == 0 && length_b == 0) return TRUE; ++ return (!memcmp(a->Buffer, b->Buffer, a->Length)); ++} ++ ++ + /*********************************************************************** + * get_cached_dir_data + * + * Retrieve the cached directory data, or initialize it if necessary. + */ + static unsigned int get_cached_dir_data( HANDLE handle, struct dir_data **data_ret, int fd, +- const UNICODE_STRING *mask ) ++ const UNICODE_STRING *mask, BOOLEAN restart_scan, ++ BOOLEAN *fresh_handle ) + { + unsigned int i; + int entry = -1, free_entries[16]; + unsigned int status; ++ *fresh_handle = TRUE; + + SERVER_START_REQ( get_directory_cache_entry ) + { +@@ -2675,6 +2703,21 @@ static unsigned int get_cached_dir_data( HANDLE handle, struct dir_data **data_r + dir_data_cache_size = size; + } + ++ /* If we have an existing cache entry then set the flag to indicate that the handle is not fresh */ ++ if (dir_data_cache[entry]) *fresh_handle = FALSE; ++ ++ /* If we have an existing cache entry, but restart_scan is true and a new non-empty mask ++ was specified then we need to invalidate the existing cache entry and create a new one ++ */ ++ if (dir_data_cache[entry] && restart_scan && mask && ++ !ustring_equal(&dir_data_cache[entry]->mask, mask)) ++ { ++ TRACE( "invalidating existing cache entry for handle %p, old mask: \"%s\", new mask: \"%s\"\n", ++ handle, debugstr_us(&(dir_data_cache[entry]->mask)), debugstr_us(mask)); ++ free_dir_data( dir_data_cache[entry] ); ++ dir_data_cache[entry] = NULL; ++ } ++ + if (!dir_data_cache[entry]) status = init_cached_dir_data( &dir_data_cache[entry], fd, mask ); + + *data_ret = dir_data_cache[entry]; +@@ -2694,6 +2737,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event, PIO_APC_ROUTI + enum server_fd_type type; + struct dir_data *data; + unsigned int status; ++ BOOLEAN fresh_handle = TRUE; + + TRACE("(%p %p %p %p %p %p 0x%08x 0x%08x 0x%08x %s 0x%08x\n", + handle, event, apc_routine, apc_context, io, buffer, +@@ -2746,7 +2790,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event, PIO_APC_ROUTI + cwd = open( ".", O_RDONLY ); + if (fchdir( fd ) != -1) + { +- if (!(status = get_cached_dir_data( handle, &data, fd, mask ))) ++ if (!(status = get_cached_dir_data( handle, &data, fd, mask, restart_scan, &fresh_handle ))) + { + union file_directory_info *last_info = NULL; + +@@ -2768,6 +2812,13 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event, PIO_APC_ROUTI + } + else status = errno_to_status( errno ); + ++ /* Return STATUS_NO_MORE_FILES if a mask did not match a file and the handle had previously been used */ ++ if (status == STATUS_NO_SUCH_FILE && !fresh_handle) ++ { ++ status = STATUS_NO_MORE_FILES; ++ io->Status = status; ++ } ++ + mutex_unlock( &dir_mutex ); + + if (needs_close) close( fd ); +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6904-ntdll-dll-Update-NtQueryDirectoryFile-to-align-with-current-Windows-behaviour/0002-ntdll-Test-updated-NtQueryDirectoryFile-behaviour-if-scan-is-reset-with-a-new-mask.patch b/0003-pending-mrs-and-backports/6904-ntdll-dll-Update-NtQueryDirectoryFile-to-align-with-current-Windows-behaviour/0002-ntdll-Test-updated-NtQueryDirectoryFile-behaviour-if-scan-is-reset-with-a-new-mask.patch new file mode 100644 index 0000000..b92ecfe --- /dev/null +++ b/0003-pending-mrs-and-backports/6904-ntdll-dll-Update-NtQueryDirectoryFile-to-align-with-current-Windows-behaviour/0002-ntdll-Test-updated-NtQueryDirectoryFile-behaviour-if-scan-is-reset-with-a-new-mask.patch @@ -0,0 +1,194 @@ +From 08d3fc4d1f2b81e96dfc0de176926990a451705a Mon Sep 17 00:00:00 2001 +From: Eugene McArdle +Date: Fri, 29 Nov 2024 10:32:31 +1000 +Subject: [PATCH] ntdll: Test updated NtQueryDirectoryFile behaviour if scan is + reset with a new mask + +--- + dlls/ntdll/tests/directory.c | 164 +++++++++++++++++++++++++++++++++++ + 1 file changed, 164 insertions(+) + +diff --git a/dlls/ntdll/tests/directory.c b/dlls/ntdll/tests/directory.c +index 52ff9936560..27027d41d9d 100644 +--- a/dlls/ntdll/tests/directory.c ++++ b/dlls/ntdll/tests/directory.c +@@ -964,6 +964,169 @@ done: + pRtlFreeUnicodeString(&ntdirname); + } + ++static void set_up_mask_test(const char *testdir) ++{ ++ BOOL ret; ++ char buf[MAX_PATH + 5]; ++ HANDLE h; ++ ++ ret = CreateDirectoryA(testdir, NULL); ++ ok( ret, "couldn't create dir '%s', error %ld\n", testdir, GetLastError() ); ++ ++ sprintf(buf, "%s\\%s", testdir, "a-file.h"); ++ h = CreateFileA(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, ++ FILE_ATTRIBUTE_NORMAL, 0); ++ ok( h != INVALID_HANDLE_VALUE, "failed to create temp file '%s'\n", buf ); ++ CloseHandle(h); ++ ++ sprintf(buf, "%s\\%s", testdir, "another-file.h"); ++ h = CreateFileA(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, ++ FILE_ATTRIBUTE_NORMAL, 0); ++ ok( h != INVALID_HANDLE_VALUE, "failed to create temp file '%s'\n", buf ); ++ CloseHandle(h); ++} ++ ++static void tear_down_mask_test(const char *testdir) ++{ ++ int ret; ++ char buf[MAX_PATH]; ++ ++ sprintf(buf, "%s\\%s", testdir, "a-file.h"); ++ ret = DeleteFileA(buf); ++ ok( ret || (GetLastError() == ERROR_FILE_NOT_FOUND) || (GetLastError() == ERROR_PATH_NOT_FOUND), ++ "Failed to rm %s, error %ld\n", buf, GetLastError() ); ++ ++ sprintf(buf, "%s\\%s", testdir, "another-file.h"); ++ ret = DeleteFileA(buf); ++ ok( ret || (GetLastError() == ERROR_FILE_NOT_FOUND) || (GetLastError() == ERROR_PATH_NOT_FOUND), ++ "Failed to rm %s, error %ld\n", buf, GetLastError() ); ++ ++ RemoveDirectoryA(testdir); ++} ++ ++ ++/* Performs a query with NtQueryDirectoryFile() */ ++static BOOL test_NtQueryDirectoryFile_mask(HANDLE handle, BOOL restart_scan, UNICODE_STRING mask, ++ BOOL expect_success, BOOL validate_only) ++{ ++ NTSTATUS status; ++ IO_STATUS_BLOCK io; ++ UINT data_size = sizeof(FILE_DIRECTORY_INFORMATION) + (MAX_PATH * sizeof(wchar_t)); ++ BYTE data[8192]; ++ FILE_DIRECTORY_INFORMATION *dir_info; ++ WCHAR *name; ++ ULONG name_len; ++ ULONG mask_len = mask.Length / sizeof(WCHAR); ++ ++ /* Perform the query */ ++ status = pNtQueryDirectoryFile( handle, NULL, NULL, NULL, &io, data, data_size, ++ FileDirectoryInformation, TRUE, &mask, restart_scan ); ++ if (expect_success) ++ { ++ if (validate_only && status != STATUS_SUCCESS) return FALSE; ++ ++ ok( status == STATUS_SUCCESS, "could not find file mask: '%s', restart: %d, error %ld\n", ++ wine_dbgstr_wn(mask.Buffer, mask_len), restart_scan, GetLastError() ); ++ /* Print the query parameters and the result */ ++ if (status == 0) { ++ dir_info = (FILE_DIRECTORY_INFORMATION *)data; ++ name = dir_info->FileName; ++ name_len = dir_info->FileNameLength / sizeof(WCHAR); ++ ++ ok( name_len == mask_len, "unexpected filename length %lu, expected %lu\n", name_len, mask_len ); ++ ok( !memcmp(name, mask.Buffer, mask_len), "unexpected filename %s, expected %s\n", ++ wine_dbgstr_wn(name, name_len), wine_dbgstr_wn(mask.Buffer, mask_len) ); ++ } ++ } ++ else ++ { ++ if (validate_only && status == STATUS_SUCCESS) return FALSE; ++ /* Print the query parameters and the result */ ++ if (status == 0) { ++ dir_info = (FILE_DIRECTORY_INFORMATION *)data; ++ name = dir_info->FileName; ++ name_len = dir_info->FileNameLength / sizeof(WCHAR); ++ ++ ok ( status != STATUS_SUCCESS, "unexpectedly found file. mask: '%s', found %s\n", ++ wine_dbgstr_wn(mask.Buffer, mask_len), wine_dbgstr_wn(name, name_len) ); ++ } ++ } ++ return TRUE; ++} ++ ++static void test_NtQueryDirectoryFile_change_mask(void) ++{ ++ NTSTATUS status; ++ HANDLE dirh; ++ char testdir[MAX_PATH]; ++ OBJECT_ATTRIBUTES attr; ++ IO_STATUS_BLOCK io; ++ UNICODE_STRING ntdirname; ++ WCHAR testdir_w[MAX_PATH]; ++ ++ UNICODE_STRING atestfile; ++ UNICODE_STRING anothertestfile; ++ UNICODE_STRING notatestfile; ++ ++ BOOL run_updated_tests = TRUE; ++ ++ pRtlInitUnicodeString(&atestfile, L"a-file.h"); ++ pRtlInitUnicodeString(&anothertestfile, L"another-file.h"); ++ pRtlInitUnicodeString(¬atestfile, L"not-a-file.h"); ++ ++ /* Clean up from prior aborted run, if any, then set up test files */ ++ ok( GetTempPathA(MAX_PATH, testdir), "couldn't get temp dir\n" ); ++ strcat(testdir, "mask.tmp"); ++ tear_down_mask_test(testdir); ++ set_up_mask_test(testdir); ++ ++ pRtlMultiByteToUnicodeN(testdir_w, sizeof(testdir_w), NULL, testdir, strlen(testdir) + 1); ++ if (!pRtlDosPathNameToNtPathName_U(testdir_w, &ntdirname, NULL, NULL)) ++ { ++ ok( 0, "RtlDosPathNametoNtPathName_U failed\n" ); ++ goto done; ++ } ++ InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL); ++ ++ /* Open a handle for our test directory */ ++ status = pNtOpenFile(&dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ, ++ FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE); ++ ok( status == STATUS_SUCCESS, "failed to open dir '%s', ret 0x%lx, error %ld\n", testdir, status, GetLastError() ); ++ if (status != STATUS_SUCCESS) ++ { ++ skip("can't test if we can't open the directory\n"); ++ goto done; ++ } ++ ++ /* Verify that updated windows 8 and higher behaviour is supported */ ++ if (!winetest_platform_is_wine && !test_NtQueryDirectoryFile_mask(dirh, TRUE, atestfile, TRUE, TRUE)) ++ run_updated_tests = FALSE; ++ if (!winetest_platform_is_wine && !test_NtQueryDirectoryFile_mask(dirh, TRUE, notatestfile, FALSE, TRUE)) ++ run_updated_tests = FALSE; ++ ++ if (!run_updated_tests) ++ { ++ skip("Win8+ NtQueryDirectoryMask behaviour not supported"); ++ goto done; ++ } ++ ++ /* Run tests - all searches for `notatestfile` are expected to fail */ ++ test_NtQueryDirectoryFile_mask(dirh, TRUE, atestfile, TRUE, FALSE); ++ test_NtQueryDirectoryFile_mask(dirh, TRUE, anothertestfile, TRUE, FALSE); ++ test_NtQueryDirectoryFile_mask(dirh, TRUE, notatestfile, FALSE, FALSE); ++ ++ test_NtQueryDirectoryFile_mask(dirh, TRUE, atestfile, TRUE, FALSE); ++ test_NtQueryDirectoryFile_mask(dirh, FALSE, notatestfile, FALSE, FALSE); ++ ++ test_NtQueryDirectoryFile_mask(dirh, TRUE, atestfile, TRUE, FALSE); ++ /* Since we are not resetting the scan, and are using an incompatible mask, this should also fail */ ++ test_NtQueryDirectoryFile_mask(dirh, FALSE, anothertestfile, FALSE, FALSE); ++ ++ /* Cleanup */ ++done: ++ tear_down_mask_test(testdir); ++} ++ + static NTSTATUS get_file_id( FILE_INTERNAL_INFORMATION *info, const WCHAR *root, const WCHAR *name ) + { + OBJECT_ATTRIBUTES attr; +@@ -1157,5 +1320,6 @@ START_TEST(directory) + test_directory_sort( sysdir ); + test_NtQueryDirectoryFile(); + test_NtQueryDirectoryFile_case(); ++ test_NtQueryDirectoryFile_change_mask(); + test_redirection(); + } +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6904-ntdll-dll-Update-NtQueryDirectoryFile-to-align-with-current-Windows-behaviour/0003-ntdll-Add-tests-to-confirm-filemasks-are-tied-to-handles-and-not-directories.patch b/0003-pending-mrs-and-backports/6904-ntdll-dll-Update-NtQueryDirectoryFile-to-align-with-current-Windows-behaviour/0003-ntdll-Add-tests-to-confirm-filemasks-are-tied-to-handles-and-not-directories.patch new file mode 100644 index 0000000..8829305 --- /dev/null +++ b/0003-pending-mrs-and-backports/6904-ntdll-dll-Update-NtQueryDirectoryFile-to-align-with-current-Windows-behaviour/0003-ntdll-Add-tests-to-confirm-filemasks-are-tied-to-handles-and-not-directories.patch @@ -0,0 +1,104 @@ +From 0f3b34247974c7dc9c885b9a33cf9302d4c8d1e9 Mon Sep 17 00:00:00 2001 +From: Eugene McArdle +Date: Fri, 6 Dec 2024 10:39:03 +1000 +Subject: [PATCH] ntdll: Add tests to confirm filemasks are tied to handles and + not directories + +--- + dlls/ntdll/tests/directory.c | 41 +++++++++++++++++++++++++----------- + 1 file changed, 29 insertions(+), 12 deletions(-) + +diff --git a/dlls/ntdll/tests/directory.c b/dlls/ntdll/tests/directory.c +index 27027d41d9d..b07654ee1ff 100644 +--- a/dlls/ntdll/tests/directory.c ++++ b/dlls/ntdll/tests/directory.c +@@ -1025,8 +1025,8 @@ static BOOL test_NtQueryDirectoryFile_mask(HANDLE handle, BOOL restart_scan, UNI + { + if (validate_only && status != STATUS_SUCCESS) return FALSE; + +- ok( status == STATUS_SUCCESS, "could not find file mask: '%s', restart: %d, error %ld\n", +- wine_dbgstr_wn(mask.Buffer, mask_len), restart_scan, GetLastError() ); ++ ok( status == STATUS_SUCCESS, "could not find file mask: '%s', restart: %d, status 0x%lx\n", ++ wine_dbgstr_wn(mask.Buffer, mask_len), restart_scan, status ); + /* Print the query parameters and the result */ + if (status == 0) { + dir_info = (FILE_DIRECTORY_INFORMATION *)data; +@@ -1058,6 +1058,7 @@ static void test_NtQueryDirectoryFile_change_mask(void) + { + NTSTATUS status; + HANDLE dirh; ++ HANDLE dirh_alt; + char testdir[MAX_PATH]; + OBJECT_ATTRIBUTES attr; + IO_STATUS_BLOCK io; +@@ -1068,8 +1069,6 @@ static void test_NtQueryDirectoryFile_change_mask(void) + UNICODE_STRING anothertestfile; + UNICODE_STRING notatestfile; + +- BOOL run_updated_tests = TRUE; +- + pRtlInitUnicodeString(&atestfile, L"a-file.h"); + pRtlInitUnicodeString(&anothertestfile, L"another-file.h"); + pRtlInitUnicodeString(¬atestfile, L"not-a-file.h"); +@@ -1098,19 +1097,34 @@ static void test_NtQueryDirectoryFile_change_mask(void) + goto done; + } + ++ /* Open a second handle for our test directory */ ++ status = pNtOpenFile(&dirh_alt, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ, ++ FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE); ++ ok( status == STATUS_SUCCESS, "failed to open second handle to dir '%s', ret 0x%lx, error %ld\n", testdir, status, GetLastError() ); ++ if (status != STATUS_SUCCESS) ++ { ++ skip("can't test if we can't open a second handle to the directory\n"); ++ goto done; ++ } ++ + /* Verify that updated windows 8 and higher behaviour is supported */ +- if (!winetest_platform_is_wine && !test_NtQueryDirectoryFile_mask(dirh, TRUE, atestfile, TRUE, TRUE)) +- run_updated_tests = FALSE; ++ test_NtQueryDirectoryFile_mask(dirh, TRUE, atestfile, TRUE, TRUE); + if (!winetest_platform_is_wine && !test_NtQueryDirectoryFile_mask(dirh, TRUE, notatestfile, FALSE, TRUE)) +- run_updated_tests = FALSE; +- +- if (!run_updated_tests) + { +- skip("Win8+ NtQueryDirectoryMask behaviour not supported"); ++ skip("Win8+ NtQueryDirectoryMask behaviour not supported\n"); + goto done; + } + +- /* Run tests - all searches for `notatestfile` are expected to fail */ ++ /* Test that caches for two handles to a single directory do not interfere with each other*/ ++ /* Use dirh to search for a non-existent file, putting it into a state with an empty cache */ ++ test_NtQueryDirectoryFile_mask(dirh, TRUE, notatestfile, FALSE, FALSE); ++ /* Confirm that dirh is in a state where it fails to find atestfile */ ++ test_NtQueryDirectoryFile_mask(dirh, FALSE, atestfile, FALSE, FALSE); ++ /* Confirm that dirh_alt is able to find atestfile */ ++ test_NtQueryDirectoryFile_mask(dirh_alt, FALSE, atestfile, TRUE, FALSE); ++ ++ /* All searches for `notatestfile` are expected to fail */ ++ /* Tests should also fail if the scan is not reset, and the mask changes to an incompatible one */ + test_NtQueryDirectoryFile_mask(dirh, TRUE, atestfile, TRUE, FALSE); + test_NtQueryDirectoryFile_mask(dirh, TRUE, anothertestfile, TRUE, FALSE); + test_NtQueryDirectoryFile_mask(dirh, TRUE, notatestfile, FALSE, FALSE); +@@ -1119,12 +1133,15 @@ static void test_NtQueryDirectoryFile_change_mask(void) + test_NtQueryDirectoryFile_mask(dirh, FALSE, notatestfile, FALSE, FALSE); + + test_NtQueryDirectoryFile_mask(dirh, TRUE, atestfile, TRUE, FALSE); +- /* Since we are not resetting the scan, and are using an incompatible mask, this should also fail */ + test_NtQueryDirectoryFile_mask(dirh, FALSE, anothertestfile, FALSE, FALSE); + + /* Cleanup */ + done: + tear_down_mask_test(testdir); ++ pRtlFreeUnicodeString(&ntdirname); ++ pRtlFreeUnicodeString(&atestfile); ++ pRtlFreeUnicodeString(&anothertestfile); ++ pRtlFreeUnicodeString(¬atestfile); + } + + static NTSTATUS get_file_id( FILE_INTERNAL_INFORMATION *info, const WCHAR *root, const WCHAR *name ) +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6904-ntdll-dll-Update-NtQueryDirectoryFile-to-align-with-current-Windows-behaviour/0004-ntdll-Simplify-check-that-unexpected-files-were-not-found.patch b/0003-pending-mrs-and-backports/6904-ntdll-dll-Update-NtQueryDirectoryFile-to-align-with-current-Windows-behaviour/0004-ntdll-Simplify-check-that-unexpected-files-were-not-found.patch new file mode 100644 index 0000000..5d7face --- /dev/null +++ b/0003-pending-mrs-and-backports/6904-ntdll-dll-Update-NtQueryDirectoryFile-to-align-with-current-Windows-behaviour/0004-ntdll-Simplify-check-that-unexpected-files-were-not-found.patch @@ -0,0 +1,34 @@ +From 8be04266fbc0410f50277d7ed1999dab65ee9735 Mon Sep 17 00:00:00 2001 +From: Eugene McArdle +Date: Mon, 9 Dec 2024 09:28:26 +1000 +Subject: [PATCH] ntdll: Simplify check that unexpected files were not found + +--- + dlls/ntdll/tests/directory.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/dlls/ntdll/tests/directory.c b/dlls/ntdll/tests/directory.c +index b07654ee1ff..b98d399d7e2 100644 +--- a/dlls/ntdll/tests/directory.c ++++ b/dlls/ntdll/tests/directory.c +@@ -1041,15 +1041,8 @@ static BOOL test_NtQueryDirectoryFile_mask(HANDLE handle, BOOL restart_scan, UNI + else + { + if (validate_only && status == STATUS_SUCCESS) return FALSE; +- /* Print the query parameters and the result */ +- if (status == 0) { +- dir_info = (FILE_DIRECTORY_INFORMATION *)data; +- name = dir_info->FileName; +- name_len = dir_info->FileNameLength / sizeof(WCHAR); +- +- ok ( status != STATUS_SUCCESS, "unexpectedly found file. mask: '%s', found %s\n", +- wine_dbgstr_wn(mask.Buffer, mask_len), wine_dbgstr_wn(name, name_len) ); +- } ++ ++ ok ( status == STATUS_NO_MORE_FILES, "unexpectedly found file\n" ); + } + return TRUE; + } +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6914-win32u-Use-LCD-optimezed-rendering-mode-for-text-drawing/0001-win32u-Use-LCD-optimezed-rendering-mode-for-text-drawing.patch b/0003-pending-mrs-and-backports/6914-win32u-Use-LCD-optimezed-rendering-mode-for-text-drawing/0001-win32u-Use-LCD-optimezed-rendering-mode-for-text-drawing.patch new file mode 100644 index 0000000..4f2ae39 --- /dev/null +++ b/0003-pending-mrs-and-backports/6914-win32u-Use-LCD-optimezed-rendering-mode-for-text-drawing/0001-win32u-Use-LCD-optimezed-rendering-mode-for-text-drawing.patch @@ -0,0 +1,30 @@ +From bb8e6206f560fdcb227d563a2338b34b0dad56a0 Mon Sep 17 00:00:00 2001 +From: chenjiangyi +Date: Thu, 28 Nov 2024 11:06:24 +0800 +Subject: [PATCH] win32u: Use LCD-optimezed rendering mode for text drawing. + +Log: + +Signed-off-by: chenjiangyi +Change-Id: If35310eb8df08f39e04066b59c6b907d89c7dd9b +--- + dlls/win32u/freetype.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/dlls/win32u/freetype.c b/dlls/win32u/freetype.c +index d1e46a681ea..fc24c008610 100644 +--- a/dlls/win32u/freetype.c ++++ b/dlls/win32u/freetype.c +@@ -1499,6 +1499,9 @@ static UINT parse_aa_pattern( FcPattern *pattern ) + if (pFcPatternGetBool( pattern, FC_ANTIALIAS, 0, &antialias ) == FcResultMatch) + aa_flags = antialias ? GGO_GRAY4_BITMAP : GGO_BITMAP; + ++ if (is_subpixel_rendering_enabled()) ++ aa_flags = WINE_GGO_HRGB_BITMAP; ++ + if (pFcPatternGetInteger( pattern, FC_RGBA, 0, &rgba ) == FcResultMatch) + { + switch (rgba) +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6978-win32u-Always-load-the-user-driver-before-entering-display-lock/0001-win32u-Skip-updating-the-cache-on-driver-load-if-we-re-already-updating-it.patch b/0003-pending-mrs-and-backports/6978-win32u-Always-load-the-user-driver-before-entering-display-lock/0001-win32u-Skip-updating-the-cache-on-driver-load-if-we-re-already-updating-it.patch new file mode 100644 index 0000000..7fa47d3 --- /dev/null +++ b/0003-pending-mrs-and-backports/6978-win32u-Always-load-the-user-driver-before-entering-display-lock/0001-win32u-Skip-updating-the-cache-on-driver-load-if-we-re-already-updating-it.patch @@ -0,0 +1,84 @@ +From dd354156a70cc6c4ddbdd5afbac056d81b015fb2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Sat, 7 Dec 2024 09:58:41 +0100 +Subject: [PATCH] win32u: Skip updating the cache on driver load if we're + already updating it. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57506 +--- + dlls/win32u/driver.c | 11 ++++++++++- + dlls/win32u/ntgdi_private.h | 1 + + dlls/win32u/sysparams.c | 4 ++-- + 3 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c +index e2ef78f1818..22e48fa6782 100644 +--- a/dlls/win32u/driver.c ++++ b/dlls/win32u/driver.c +@@ -1006,7 +1006,7 @@ static BOOL load_desktop_driver( HWND hwnd ) + * Each entry point simply loads the real driver and chains to it. + */ + +-static const struct user_driver_funcs *load_driver(void) ++static void load_display_driver(void) + { + USEROBJECTFLAGS flags; + HWINSTA winstation; +@@ -1020,11 +1020,20 @@ static const struct user_driver_funcs *load_driver(void) + + __wine_set_user_driver( &null_user_driver, WINE_GDI_DRIVER_VERSION ); + } ++} + ++static const struct user_driver_funcs *load_driver(void) ++{ ++ load_display_driver(); + update_display_cache( FALSE ); + return user_driver; + } + ++void init_display_driver(void) ++{ ++ if (user_driver == &lazy_load_driver) load_display_driver(); ++} ++ + /********************************************************************** + * get_display_driver + */ +diff --git a/dlls/win32u/ntgdi_private.h b/dlls/win32u/ntgdi_private.h +index 679eea6538d..ce54a6591a0 100644 +--- a/dlls/win32u/ntgdi_private.h ++++ b/dlls/win32u/ntgdi_private.h +@@ -227,6 +227,7 @@ extern const struct gdi_dc_funcs dib_driver; + extern const struct gdi_dc_funcs path_driver; + extern const struct gdi_dc_funcs font_driver; + extern const struct gdi_dc_funcs *get_display_driver(void); ++extern void init_display_driver(void); + + /* font.c */ + +diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c +index 230c3faa262..2ae72397bc5 100644 +--- a/dlls/win32u/sysparams.c ++++ b/dlls/win32u/sysparams.c +@@ -2243,6 +2243,8 @@ static BOOL lock_display_devices( BOOL force ) + WCHAR name[MAX_PATH]; + BOOL ret = TRUE; + ++ init_display_driver(); /* make sure to load the driver before anything else */ ++ + /* services do not have any adapters, only a virtual monitor */ + if (NtUserGetObjectInformation( winstation, UOI_NAME, name, sizeof(name), NULL ) + && !wcscmp( name, wine_service_station_name )) +@@ -2254,8 +2256,6 @@ static BOOL lock_display_devices( BOOL force ) + return TRUE; + } + +- if (!force) get_display_driver(); /* make sure at least to load the user driver */ +- + pthread_mutex_lock( &display_lock ); + + if (!force && !update_display_cache_from_registry()) force = TRUE; +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6984-msvcrt-Don-t-leak-find-handle-or-error-in-findfirst-/0001-msvcrt-Don-t-leak-find-handle-or-error-in-findfirst-.patch b/0003-pending-mrs-and-backports/6984-msvcrt-Don-t-leak-find-handle-or-error-in-findfirst-/0001-msvcrt-Don-t-leak-find-handle-or-error-in-findfirst-.patch new file mode 100644 index 0000000..aea3d62 --- /dev/null +++ b/0003-pending-mrs-and-backports/6984-msvcrt-Don-t-leak-find-handle-or-error-in-findfirst-/0001-msvcrt-Don-t-leak-find-handle-or-error-in-findfirst-.patch @@ -0,0 +1,55 @@ +From 435ffe8163d793604fc1cff7bd6a34ee29c2ecb7 Mon Sep 17 00:00:00 2001 +From: Piotr Caban +Date: Mon, 9 Dec 2024 11:36:32 +0100 +Subject: [PATCH] msvcrt: Don't leak find handle or error in _findfirst(). + +--- + dlls/msvcrt/dir.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/dlls/msvcrt/dir.c b/dlls/msvcrt/dir.c +index 7a36b74ee6b..a047ca47aab 100644 +--- a/dlls/msvcrt/dir.c ++++ b/dlls/msvcrt/dir.c +@@ -391,7 +391,11 @@ intptr_t CDECL _findfirst32(const char *fspec, struct _finddata32_t *ft) + if (fspec && !(fspecW = wstrdupa_utf8(fspec))) return -1; + ret = _wfindfirst32(fspecW, &wft); + free(fspecW); +- if (!finddata32_wtoa(&wft, ft)) return -1; ++ if (ret != -1 && !finddata32_wtoa(&wft, ft)) ++ { ++ _findclose(ret); ++ return -1; ++ } + return ret; + } + +@@ -461,7 +465,11 @@ intptr_t CDECL _findfirst64(const char *fspec, struct _finddata64_t *ft) + if (fspec && !(fspecW = wstrdupa_utf8(fspec))) return -1; + ret = _wfindfirst64(fspecW, &wft); + free(fspecW); +- if (!finddata64_wtoa(&wft, ft)) return -1; ++ if (ret != -1 && !finddata64_wtoa(&wft, ft)) ++ { ++ _findclose(ret); ++ return -1; ++ } + return ret; + } + +@@ -510,7 +518,11 @@ intptr_t CDECL _findfirst64i32(const char *fspec, struct _finddata64i32_t *ft) + if (fspec && !(fspecW = wstrdupa_utf8(fspec))) return -1; + ret = _wfindfirst64i32(fspecW, &wft); + free(fspecW); +- if (!finddata64i32_wtoa(&wft, ft)) return -1; ++ if (ret != -1 && !finddata64i32_wtoa(&wft, ft)) ++ { ++ _findclose(ret); ++ return -1; ++ } + return ret; + } + +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/9999-misc-loose/0085-ps6072-server-kernelbase-Force-WoW-sharing-on-HKCU.patch b/0003-pending-mrs-and-backports/9999-misc-loose/0085-ps6072-server-kernelbase-Force-WoW-sharing-on-HKCU.patch deleted file mode 100644 index 6426d80..0000000 --- a/0003-pending-mrs-and-backports/9999-misc-loose/0085-ps6072-server-kernelbase-Force-WoW-sharing-on-HKCU.patch +++ /dev/null @@ -1,395 +0,0 @@ -From f282b92782e763a55658be9036a7568456dcc906 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Fri, 12 Jul 2024 15:06:05 -0600 -Subject: [PATCH 1/5] server: Renamed KEY_WOWSHARE constant to KEY_WOWREFLECT. - ---- - server/registry.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/server/registry.c b/server/registry.c -index 804cfcc638b..aab18fc6061 100644 ---- a/server/registry.c -+++ b/server/registry.c -@@ -97,7 +97,7 @@ struct key - #define KEY_DELETED 0x0002 /* key has been deleted */ - #define KEY_DIRTY 0x0004 /* key has been modified */ - #define KEY_SYMLINK 0x0008 /* key is a symbolic link */ --#define KEY_WOWSHARE 0x0010 /* key is a Wow64 shared key (used for Software\Classes) */ -+#define KEY_WOWREFLECT 0x0010 /* key is a Wow64 shared and reflected key (used for Software\Classes) */ - #define KEY_PREDEF 0x0020 /* key is marked as predefined */ - - #define OBJ_KEY_WOW64 0x100000 /* magic flag added to attributes for WoW64 redirection */ -@@ -518,7 +518,7 @@ static struct object *key_lookup_name( struct object *obj, struct unicode_str *n - } - - key = (struct key *)obj; -- if (key && (key->flags & KEY_WOWSHARE) && (attr & OBJ_KEY_WOW64) && !name->str) -+ if (key && (key->flags & KEY_WOWREFLECT) && (attr & OBJ_KEY_WOW64) && !name->str) - { - key = get_parent( key ); - release_object( obj ); -@@ -545,7 +545,7 @@ static struct object *key_lookup_name( struct object *obj, struct unicode_str *n - - if (!(found = find_subkey( key, &tmp, &index ))) - { -- if ((key->flags & KEY_WOWSHARE) && (attr & OBJ_KEY_WOW64)) -+ if ((key->flags & KEY_WOWREFLECT) && (attr & OBJ_KEY_WOW64)) - { - /* try in the 64-bit parent */ - key = get_parent( key ); -@@ -777,7 +777,7 @@ static struct key *grab_wow6432node( struct key *key ) - struct key *ret = key->wow6432node; - - if (!ret) return key; -- if (ret->flags & KEY_WOWSHARE) return key; -+ if (ret->flags & KEY_WOWREFLECT) return key; - grab_object( ret ); - release_object( key ); - return ret; -@@ -823,7 +823,7 @@ static struct key *open_key( struct key *parent, const struct unicode_str *name, - if (parent && !(access & KEY_WOW64_64KEY) && !is_wow6432node( name->str, name->len )) - { - key = get_wow6432node( parent ); -- if (key && ((access & KEY_WOW64_32KEY) || (key->flags & KEY_WOWSHARE))) -+ if (key && ((access & KEY_WOW64_32KEY) || (key->flags & KEY_WOWREFLECT))) - parent = key; - } - -@@ -849,7 +849,7 @@ static struct key *create_key( struct key *parent, const struct unicode_str *nam - if (parent && !(access & KEY_WOW64_64KEY) && !is_wow6432node( name->str, name->len )) - { - key = get_wow6432node( parent ); -- if (key && ((access & KEY_WOW64_32KEY) || (key->flags & KEY_WOWSHARE))) -+ if (key && ((access & KEY_WOW64_32KEY) || (key->flags & KEY_WOWREFLECT))) - parent = key; - } - -@@ -1954,7 +1954,7 @@ void init_registry(void) - } - if ((key = create_key_recursive( hklm, &name, current_time ))) - { -- key->flags |= KEY_WOWSHARE; -+ key->flags |= KEY_WOWREFLECT; - release_object( key ); - } - /* FIXME: handle HKCU too */ --- -GitLab - - -From 0a98b57783431bc0d8be5fa42eb16167056b1413 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 11 Jul 2024 19:10:31 -0600 -Subject: [PATCH 2/5] server: Force WoW sharing on HKCU/Software key. - ---- - server/registry.c | 18 +++++++++++++----- - 1 file changed, 13 insertions(+), 5 deletions(-) - -diff --git a/server/registry.c b/server/registry.c -index aab18fc6061..507793e5ed3 100644 ---- a/server/registry.c -+++ b/server/registry.c -@@ -99,6 +99,7 @@ struct key - #define KEY_SYMLINK 0x0008 /* key is a symbolic link */ - #define KEY_WOWREFLECT 0x0010 /* key is a Wow64 shared and reflected key (used for Software\Classes) */ - #define KEY_PREDEF 0x0020 /* key is marked as predefined */ -+#define KEY_WOWSHARE 0x0040 /* key is Wow64 shared */ - - #define OBJ_KEY_WOW64 0x100000 /* magic flag added to attributes for WoW64 redirection */ - -@@ -604,7 +605,7 @@ static int key_link_name( struct object *obj, struct object_name *name, struct o - for (i = ++parent_key->last_subkey; i > index; i--) - parent_key->subkeys[i] = parent_key->subkeys[i - 1]; - parent_key->subkeys[index] = (struct key *)grab_object( key ); -- if (is_wow6432node( name->name, name->len ) && -+ if (!(parent_key->flags & KEY_WOWSHARE) && is_wow6432node( name->name, name->len ) && - !is_wow6432node( parent_key->obj.name->name, parent_key->obj.name->len )) - parent_key->wow6432node = key; - name->parent = parent; -@@ -1886,13 +1887,14 @@ void init_registry(void) - 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', - 'P','e','r','f','l','i','b','\\', - '0','0','9'}; -+ static const WCHAR software[] = {'S','o','f','t','w','a','r','e',}; - static const struct unicode_str root_name = { REGISTRY, sizeof(REGISTRY) }; - static const struct unicode_str HKLM_name = { HKLM, sizeof(HKLM) }; - static const struct unicode_str HKU_name = { HKU_default, sizeof(HKU_default) }; - static const struct unicode_str perflib_name = { perflib, sizeof(perflib) }; - - WCHAR *current_user_path; -- struct unicode_str current_user_str; -+ struct unicode_str current_user_str, name; - struct key *key, *hklm, *hkcu; - unsigned int i; - char *p; -@@ -1944,8 +1946,6 @@ void init_registry(void) - /* set the shared flag on Software\Classes\Wow6432Node for all platforms */ - for (i = 1; i < supported_machines_count; i++) - { -- struct unicode_str name; -- - switch (supported_machines[i]) - { - case IMAGE_FILE_MACHINE_I386: name.str = classes_i386; name.len = sizeof(classes_i386); break; -@@ -1957,7 +1957,15 @@ void init_registry(void) - key->flags |= KEY_WOWREFLECT; - release_object( key ); - } -- /* FIXME: handle HKCU too */ -+ } -+ -+ name.str = software; -+ name.len = sizeof(software); -+ if ((key = create_key_recursive( hkcu, &name, current_time ))) -+ { -+ key->flags |= KEY_WOWSHARE; -+ key->wow6432node = NULL; -+ release_object( key ); - } - - if ((key = create_key_recursive( hklm, &perflib_name, current_time ))) --- -GitLab - - -From d01eb50114a1f06053854584686fdc61abf95ce0 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Fri, 12 Jul 2024 16:27:35 -0600 -Subject: [PATCH 3/5] kernelbase: Factor out get_key_name(). - ---- - dlls/kernelbase/registry.c | 31 +++++++++++++++++++------------ - 1 file changed, 19 insertions(+), 12 deletions(-) - -diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c -index 8471376bf96..24b4bd45d70 100644 ---- a/dlls/kernelbase/registry.c -+++ b/dlls/kernelbase/registry.c -@@ -112,20 +112,15 @@ static BOOL is_classes_root( const UNICODE_STRING *name ) - return (len >= classes_root_len - 1 && !wcsnicmp( name->Buffer, classes_root, min( len, classes_root_len ) )); - } - --static BOOL is_classes_wow6432node( HKEY key ) -+static KEY_NAME_INFORMATION *get_key_name( HKEY key, char *buffer, DWORD len ) - { -- char buffer[256], *buf_ptr = buffer; -+ char *buf_ptr = buffer; - KEY_NAME_INFORMATION *info = (KEY_NAME_INFORMATION *)buffer; -- DWORD len = sizeof(buffer); -- UNICODE_STRING name; - NTSTATUS status; -- BOOL ret = FALSE; - -- /* Obtain the name of the root key */ -- status = NtQueryKey( key, KeyNameInformation, info, len, &len ); -- if (status && status != STATUS_BUFFER_OVERFLOW) return FALSE; -+ status = NtQueryKey( key, KeyNameInformation, buf_ptr, len, &len ); -+ if (status && status != STATUS_BUFFER_OVERFLOW) return NULL; - -- /* Retry with a dynamically allocated buffer */ - while (status == STATUS_BUFFER_OVERFLOW) - { - if (buf_ptr != buffer) heap_free( buf_ptr ); -@@ -133,9 +128,22 @@ static BOOL is_classes_wow6432node( HKEY key ) - info = (KEY_NAME_INFORMATION *)buf_ptr; - status = NtQueryKey( key, KeyNameInformation, info, len, &len ); - } -+ if (!status) return (KEY_NAME_INFORMATION *)buf_ptr; -+ if (buf_ptr != buffer) heap_free( buf_ptr ); -+ return NULL; -+} -+ -+static BOOL is_classes_wow6432node( HKEY key ) -+{ -+ KEY_NAME_INFORMATION *info; -+ char buffer[256]; -+ UNICODE_STRING name; -+ BOOL ret = FALSE; -+ -+ if (!(info = get_key_name( key, buffer, sizeof(buffer) ))) return FALSE; - - /* Check if the key ends in Wow6432Node and if the root is the Classes key*/ -- if (!status && info->NameLength / sizeof(WCHAR) >= 11) -+ if (info->NameLength / sizeof(WCHAR) >= 11) - { - name.Buffer = info->Name + info->NameLength / sizeof(WCHAR) - 11; - name.Length = 11 * sizeof(WCHAR); -@@ -146,8 +154,7 @@ static BOOL is_classes_wow6432node( HKEY key ) - ret = is_classes_root( &name ); - } - } -- -- if (buf_ptr != buffer) heap_free( buf_ptr ); -+ if ((char *)info != buffer) heap_free( info ); - - return ret; - } --- -GitLab - - -From 1c20cda407bbaf672bc1153f55fe6b61e032dba7 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Fri, 12 Jul 2024 16:21:45 -0600 -Subject: [PATCH 4/5] kernelbase: Force WoW sharing on HKCU/Software key. - ---- - dlls/kernelbase/registry.c | 36 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 36 insertions(+) - -diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c -index 24b4bd45d70..bb67eb4176a 100644 ---- a/dlls/kernelbase/registry.c -+++ b/dlls/kernelbase/registry.c -@@ -159,6 +159,37 @@ static BOOL is_classes_wow6432node( HKEY key ) - return ret; - } - -+static BOOL is_wow6432_shared( HANDLE key ) -+{ -+ static const WCHAR users_root[] = L"\\Registry\\User\\"; -+ const DWORD users_root_len = ARRAY_SIZE( users_root ) - 1; -+ static const WCHAR software[] = L"\\Software"; -+ const DWORD software_len = ARRAY_SIZE( software ) - 1; -+ KEY_NAME_INFORMATION *info; -+ char buffer[256]; -+ BOOL ret = FALSE; -+ WCHAR *name; -+ DWORD len; -+ -+ if (!(info = get_key_name( key, buffer, sizeof(buffer) ))) return FALSE; -+ len = info->NameLength / sizeof(WCHAR); -+ if (len <= users_root_len) goto done; -+ name = info->Name; -+ if (wcsnicmp( name, users_root, users_root_len )) goto done; -+ name += users_root_len; -+ len -= users_root_len; -+ while (len && *name != '\\') -+ { -+ ++name; -+ --len; -+ } -+ if (len != software_len) goto done; -+ ret = !wcsnicmp( name, software, software_len ); -+done: -+ if ((char *)info != buffer) heap_free( info ); -+ return ret; -+} -+ - /* Open the Wow6432Node subkey of the specified key */ - static HANDLE open_wow6432node( HANDLE key ) - { -@@ -173,6 +204,11 @@ static HANDLE open_wow6432node( HANDLE key ) - attr.SecurityDescriptor = NULL; - attr.SecurityQualityOfService = NULL; - if (NtOpenKeyEx( &ret, MAXIMUM_ALLOWED | KEY_WOW64_64KEY, &attr, 0 )) return key; -+ if (is_wow6432_shared( key )) -+ { -+ NtClose( ret ); -+ return key; -+ } - return ret; - } - --- -GitLab - - -From 28c47bb721e8a5df0cccc82ec993fc36ac453d35 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Fri, 12 Jul 2024 17:01:23 -0600 -Subject: [PATCH 5/5] advapi32/tests: Add tests for WoW shared HKCU/Software - key. - ---- - dlls/advapi32/tests/registry.c | 72 ++++++++++++++++++++++++++++++++++ - 1 file changed, 72 insertions(+) - -diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c -index 0f77b2fa066..d21bd8fe741 100644 ---- a/dlls/advapi32/tests/registry.c -+++ b/dlls/advapi32/tests/registry.c -@@ -3375,6 +3375,78 @@ static void test_redirection(void) - - RegDeleteKeyA( key32, "" ); - RegCloseKey( key32 ); -+ -+ /* HKCU\\Software is shared. */ -+ err = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Wow6432Node\\tmp", 0, NULL, 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, NULL, &key, NULL ); -+ ok( !err, "got %#lx.\n", err ); -+ RegDeleteKeyA( key, "" ); -+ RegCloseKey( key ); -+ -+ err = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\TestKey", 0, NULL, 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, NULL, &root64, NULL ); -+ ok( !err, "got %#lx.\n", err ); -+ err = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\Wow6432Node\\TestKey", 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &root32 ); -+ ok ( err == ERROR_FILE_NOT_FOUND, "got %#lx.\n", err ); -+ -+ err = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Wow6432Node\\TestKey", 0, NULL, 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, NULL, &root32, NULL ); -+ ok( !err, "got %#lx.\n", err ); -+ -+ dw = 1; -+ err = RegSetKeyValueA( root64, NULL, "val", REG_DWORD, &dw, sizeof(dw) ); -+ ok( !err, "got %#lx.\n", err ); -+ -+ dw = 2; -+ err = RegSetKeyValueA( root32, NULL, "val", REG_DWORD, &dw, sizeof(dw) ); -+ ok( !err, "got %#lx.\n", err ); -+ -+ err = RegCreateKeyExA( root64, "subkey", 0, NULL, 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, NULL, &key64, NULL ); -+ ok( !err, "got %#lx.\n", err ); -+ dw = 1; -+ err = RegSetKeyValueA( key64, NULL, "val", REG_DWORD, &dw, sizeof(dw) ); -+ ok( !err, "got %#lx.\n", err ); -+ -+ err = RegCreateKeyExA( root32, "subkey", 0, NULL, 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, NULL, &key32, NULL ); -+ ok( !err, "got %#lx.\n", err ); -+ dw = 2; -+ err = RegSetKeyValueA( key32, NULL, "val", REG_DWORD, &dw, sizeof(dw) ); -+ ok( !err, "got %#lx.\n", err ); -+ -+ err = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\TestKey", 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &key ); -+ ok( !err, "got %#lx.\n", err ); -+ len = sizeof(dw); -+ err = RegQueryValueExA( key, "val", NULL, NULL, (BYTE *)&dw, &len ); -+ ok( !err, "got %#lx.\n", err ); -+ ok( dw == 1, "got %lu.\n", dw ); -+ RegCloseKey( key ); -+ err = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\TestKey", 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, &key ); -+ ok( !err, "got %#lx.\n", err ); -+ len = sizeof(dw); -+ err = RegQueryValueExA( key, "val", NULL, NULL, (BYTE *)&dw, &len ); -+ ok( !err, "got %#lx.\n", err ); -+ ok( dw == 1, "got %lu.\n", dw ); -+ RegCloseKey( key ); -+ err = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\TestKey\\subkey", 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &key ); -+ ok( !err, "got %#lx.\n", err ); -+ len = sizeof(dw); -+ err = RegQueryValueExA( key, "val", NULL, NULL, (BYTE *)&dw, &len ); -+ ok( !err, "got %#lx.\n", err ); -+ ok( dw == 1, "got %lu.\n", dw ); -+ RegCloseKey( key ); -+ err = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\TestKey\\subkey", 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, &key ); -+ ok( !err, "got %#lx.\n", err ); -+ len = sizeof(dw); -+ err = RegQueryValueExA( key, "val", NULL, NULL, (BYTE *)&dw, &len ); -+ ok( !err, "got %#lx.\n", err ); -+ ok( dw == 1, "got %lu.\n", dw ); -+ RegCloseKey( key ); -+ -+ RegDeleteKeyA( key64, "" ); -+ RegCloseKey( key64 ); -+ RegDeleteKeyA( key32, "" ); -+ RegCloseKey( key32 ); -+ RegDeleteKeyA( root32, "" ); -+ RegCloseKey( root32 ); -+ RegDeleteKeyA( root64, "" ); -+ RegCloseKey( root64 ); - } - - static void test_classesroot(void) --- -GitLab - diff --git a/0003-pending-mrs-and-backports/9999-misc-loose/0090-ps6047-server-Deny-opening-handles-to-objects-with-zero-access.patch b/0003-pending-mrs-and-backports/9999-misc-loose/0090-ps6047-server-Deny-opening-handles-to-objects-with-zero-access.patch deleted file mode 100644 index d7974fc..0000000 --- a/0003-pending-mrs-and-backports/9999-misc-loose/0090-ps6047-server-Deny-opening-handles-to-objects-with-zero-access.patch +++ /dev/null @@ -1,442 +0,0 @@ -From 5bda1b2026d7f4c9d80ce97e19e678d07cea056e Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Wed, 10 Jul 2024 16:20:22 -0600 -Subject: [PATCH 1/4] ntdll/tests: Add tests for opening some objects with zero - access. - ---- - dlls/ntdll/tests/om.c | 82 +++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 82 insertions(+) - -diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c -index fb45fe777b7..db767d9d56b 100644 ---- a/dlls/ntdll/tests/om.c -+++ b/dlls/ntdll/tests/om.c -@@ -73,6 +73,7 @@ static NTSTATUS (WINAPI *pNtCreateDebugObject)( HANDLE *, ACCESS_MASK, OBJECT_AT - static NTSTATUS (WINAPI *pNtGetNextThread)(HANDLE process, HANDLE thread, ACCESS_MASK access, ULONG attributes, - ULONG flags, HANDLE *handle); - static NTSTATUS (WINAPI *pNtOpenProcessToken)(HANDLE,DWORD,HANDLE*); -+static NTSTATUS (WINAPI *pNtOpenThread)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, const CLIENT_ID * ); - static NTSTATUS (WINAPI *pNtOpenThreadToken)(HANDLE,DWORD,BOOLEAN,HANDLE*); - static NTSTATUS (WINAPI *pNtDuplicateToken)(HANDLE,ACCESS_MASK,OBJECT_ATTRIBUTES*,BOOLEAN,TOKEN_TYPE,HANDLE*); - static NTSTATUS (WINAPI *pNtDuplicateObject)(HANDLE,HANDLE,HANDLE,HANDLE*,ACCESS_MASK,ULONG,ULONG); -@@ -3380,6 +3381,85 @@ static void test_object_permanence(void) - ok( status == STATUS_SUCCESS, "NtSetInformationThread returned %08lx\n", status ); - } - -+static void test_zero_access(void) -+{ -+ OBJECT_ATTRIBUTES attr; -+ UNICODE_STRING str; -+ NTSTATUS status; -+ WCHAR name[256]; -+ CLIENT_ID cid; -+ HANDLE h1, h2; -+ -+ swprintf( name, ARRAY_SIZE(name), L"\\Sessions\\%u\\BaseNamedObjects\\test_object", NtCurrentTeb()->Peb->SessionId ); -+ pRtlInitUnicodeString( &str, name ); -+ InitializeObjectAttributes( &attr, &str, 0, 0, NULL ); -+ -+ status = pNtCreateEvent( &h1, 0, &attr, NotificationEvent, FALSE ); -+ ok( !status, "got %#lx.\n", status ); -+ -+ status = pNtOpenEvent( &h2, EVENT_ALL_ACCESS, &attr ); -+ ok( !status, "got %#lx.\n", status ); -+ CloseHandle( h2 ); -+ -+ status = NtOpenEvent(&h2, 0, &attr); -+ todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -+ if (!status) CloseHandle( h2 ); -+ -+ InitializeObjectAttributes( &attr, &str, OBJ_INHERIT, 0, NULL ); -+ status = NtOpenEvent(&h2, 0, &attr); -+ todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -+ if (!status) CloseHandle( h2 ); -+ -+ status = pNtDuplicateObject( GetCurrentProcess(), h1, GetCurrentProcess(), &h2, 0, 0, 0 ); -+ ok( !status, "got %#lx.\n", status ); -+ CloseHandle( h2 ); -+ status = pNtDuplicateObject( GetCurrentProcess(), h1, GetCurrentProcess(), &h2, EVENT_ALL_ACCESS, 0, 0 ); -+ ok( !status, "got %#lx.\n", status ); -+ CloseHandle( h2 ); -+ -+ CloseHandle( h1 ); -+ -+ InitializeObjectAttributes( &attr, &str, 0, 0, NULL ); -+ status = pNtCreateMutant( &h1, 0, &attr, FALSE ); -+ ok( !status, "got %#lx.\n", status ); -+ status = NtOpenMutant(&h2, 0, &attr); -+ todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -+ if (!status) CloseHandle( h2 ); -+ CloseHandle( h1 ); -+ -+ status = pNtCreateTimer( &h1, 0, &attr, NotificationTimer ); -+ ok( !status, "got %#lx.\n", status ); -+ status = pNtOpenTimer( &h2, 0, &attr ); -+ todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -+ if (!status) CloseHandle( h2 ); -+ CloseHandle( h1 ); -+ -+ status = NtGetNextThread(GetCurrentProcess(), NULL, 0, 0, 0, &h1); -+ todo_wine ok( status == STATUS_NO_MORE_ENTRIES, "got %#lx.\n", status ); -+ if (!status) CloseHandle( h1 ); -+ -+ InitializeObjectAttributes( &attr, NULL, 0, 0, NULL ); -+ cid.UniqueProcess = ULongToHandle( GetCurrentProcessId() ); -+ cid.UniqueThread = 0; -+ status = pNtOpenProcess( &h1, 0, &attr, &cid ); -+ todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -+ if (!status) CloseHandle( h1 ); -+ -+ InitializeObjectAttributes( &attr, NULL, 0, 0, NULL ); -+ cid.UniqueProcess = 0; -+ cid.UniqueThread = ULongToHandle( GetCurrentThreadId() ); -+ status = pNtOpenThread( &h1, 0, &attr, &cid ); -+ todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -+ if (!status) CloseHandle( h1 ); -+ -+ InitializeObjectAttributes( &attr, &str, OBJ_OPENIF, 0, NULL ); -+ swprintf( name, ARRAY_SIZE(name), L"\\Sessions\\%u", NtCurrentTeb()->Peb->SessionId ); -+ RtlInitUnicodeString( &str, name ); -+ pNtOpenDirectoryObject( &h1, 0, &attr ); -+ todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -+ if (!status) CloseHandle( h1 ); -+} -+ - START_TEST(om) - { - HMODULE hntdll = GetModuleHandleA("ntdll.dll"); -@@ -3424,6 +3504,7 @@ START_TEST(om) - pNtDuplicateToken = (void *)GetProcAddress(hntdll, "NtDuplicateToken"); - pNtDuplicateObject = (void *)GetProcAddress(hntdll, "NtDuplicateObject"); - pNtCompareObjects = (void *)GetProcAddress(hntdll, "NtCompareObjects"); -+ pNtOpenThread = (void *)GetProcAddress(hntdll, "NtOpenThread"); - - test_null_in_object_name(); - test_case_sensitive(); -@@ -3444,4 +3525,5 @@ START_TEST(om) - test_query_directory(); - test_object_permanence(); - test_NtAllocateReserveObject(); -+ test_zero_access(); - } --- -GitLab - - -From 83b2763eb36de57afe7c9983f4db91153fdaa6ef Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Wed, 10 Jul 2024 16:41:20 -0600 -Subject: [PATCH 2/4] ntoskrnl.exe/tests: Open directory object with nonzero - access in test_permanent(). - ---- - dlls/ntoskrnl.exe/tests/driver.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c -index 751f2acff96..7ddbad36fee 100644 ---- a/dlls/ntoskrnl.exe/tests/driver.c -+++ b/dlls/ntoskrnl.exe/tests/driver.c -@@ -2289,7 +2289,7 @@ static void test_permanence(void) - ok(!status, "got %#lx\n", status); - - attr.Attributes = 0; -- status = ZwOpenDirectoryObject( &handle, 0, &attr ); -+ status = ZwOpenDirectoryObject( &handle, DIRECTORY_ALL_ACCESS, &attr ); - ok(!status, "got %#lx\n", status); - status = ZwMakeTemporaryObject( handle ); - ok(!status, "got %#lx\n", status); -@@ -2303,7 +2303,7 @@ static void test_permanence(void) - status = ZwCreateDirectoryObject( &handle, GENERIC_ALL, &attr ); - ok(!status, "got %#lx\n", status); - attr.Attributes = OBJ_PERMANENT; -- status = ZwOpenDirectoryObject( &handle2, 0, &attr ); -+ status = ZwOpenDirectoryObject( &handle2, DIRECTORY_ALL_ACCESS, &attr ); - ok(status == STATUS_SUCCESS, "got %#lx\n", status); - status = ZwClose( handle2 ); - ok(!status, "got %#lx\n", status); --- -GitLab - - -From 1509b7d34b6644319e79b2136e29800a97066ecb Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Wed, 10 Jul 2024 16:43:25 -0600 -Subject: [PATCH 3/4] server: Do not allow zero access mask when opening some - objects. - ---- - dlls/advapi32/tests/security.c | 4 ---- - dlls/kernel32/tests/sync.c | 2 -- - dlls/ntdll/tests/om.c | 21 +++++++-------------- - dlls/user32/tests/winstation.c | 4 ++++ - server/handle.c | 11 ++++++++++- - server/handle.h | 2 ++ - server/process.c | 2 +- - server/thread.c | 2 +- - 8 files changed, 25 insertions(+), 23 deletions(-) - -diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c -index 0917b144648..84a6139b3a8 100644 ---- a/dlls/advapi32/tests/security.c -+++ b/dlls/advapi32/tests/security.c -@@ -5542,9 +5542,7 @@ static void test_mutex_security(HANDLE token) - - SetLastError(0xdeadbeef); - dup = OpenMutexA(0, FALSE, "WineTestMutex"); -- todo_wine - ok(!dup, "OpenMutex should fail\n"); -- todo_wine - ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu\n", GetLastError()); - } - -@@ -5599,9 +5597,7 @@ static void test_event_security(HANDLE token) - - SetLastError(0xdeadbeef); - dup = OpenEventA(0, FALSE, "WineTestEvent"); -- todo_wine - ok(!dup, "OpenEvent should fail\n"); -- todo_wine - ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu\n", GetLastError()); - } - -diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index c06ced47298..abadc4b1397 100644 ---- a/dlls/kernel32/tests/sync.c -+++ b/dlls/kernel32/tests/sync.c -@@ -247,9 +247,7 @@ static void test_mutex(void) - - SetLastError(0xdeadbeef); - hOpened = OpenMutexA(0, FALSE, "WineTestMutex"); -- todo_wine - ok(hOpened == NULL, "OpenMutex succeeded\n"); -- todo_wine - ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu\n", GetLastError()); - - SetLastError(0xdeadbeef); -diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c -index db767d9d56b..fd23038500a 100644 ---- a/dlls/ntdll/tests/om.c -+++ b/dlls/ntdll/tests/om.c -@@ -3402,13 +3402,11 @@ static void test_zero_access(void) - CloseHandle( h2 ); - - status = NtOpenEvent(&h2, 0, &attr); -- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -- if (!status) CloseHandle( h2 ); -+ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); - - InitializeObjectAttributes( &attr, &str, OBJ_INHERIT, 0, NULL ); - status = NtOpenEvent(&h2, 0, &attr); -- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -- if (!status) CloseHandle( h2 ); -+ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); - - status = pNtDuplicateObject( GetCurrentProcess(), h1, GetCurrentProcess(), &h2, 0, 0, 0 ); - ok( !status, "got %#lx.\n", status ); -@@ -3423,15 +3421,13 @@ static void test_zero_access(void) - status = pNtCreateMutant( &h1, 0, &attr, FALSE ); - ok( !status, "got %#lx.\n", status ); - status = NtOpenMutant(&h2, 0, &attr); -- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -- if (!status) CloseHandle( h2 ); -+ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); - CloseHandle( h1 ); - - status = pNtCreateTimer( &h1, 0, &attr, NotificationTimer ); - ok( !status, "got %#lx.\n", status ); - status = pNtOpenTimer( &h2, 0, &attr ); -- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -- if (!status) CloseHandle( h2 ); -+ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); - CloseHandle( h1 ); - - status = NtGetNextThread(GetCurrentProcess(), NULL, 0, 0, 0, &h1); -@@ -3442,22 +3438,19 @@ static void test_zero_access(void) - cid.UniqueProcess = ULongToHandle( GetCurrentProcessId() ); - cid.UniqueThread = 0; - status = pNtOpenProcess( &h1, 0, &attr, &cid ); -- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -- if (!status) CloseHandle( h1 ); -+ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); - - InitializeObjectAttributes( &attr, NULL, 0, 0, NULL ); - cid.UniqueProcess = 0; - cid.UniqueThread = ULongToHandle( GetCurrentThreadId() ); - status = pNtOpenThread( &h1, 0, &attr, &cid ); -- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -- if (!status) CloseHandle( h1 ); -+ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); - - InitializeObjectAttributes( &attr, &str, OBJ_OPENIF, 0, NULL ); - swprintf( name, ARRAY_SIZE(name), L"\\Sessions\\%u", NtCurrentTeb()->Peb->SessionId ); - RtlInitUnicodeString( &str, name ); - pNtOpenDirectoryObject( &h1, 0, &attr ); -- todo_wine ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); -- if (!status) CloseHandle( h1 ); -+ ok( status == STATUS_ACCESS_DENIED, "got %#lx.\n", status ); - } - - START_TEST(om) -diff --git a/dlls/user32/tests/winstation.c b/dlls/user32/tests/winstation.c -index bcbb55ee918..9294db4934f 100644 ---- a/dlls/user32/tests/winstation.c -+++ b/dlls/user32/tests/winstation.c -@@ -172,6 +172,10 @@ static void test_handles(void) - else if (le == ERROR_ACCESS_DENIED) - win_skip( "Not enough privileges for CreateWindowStation\n" ); - -+ w2 = OpenWindowStationA("winsta0", TRUE, 0 ); -+ ok( !w2, "got non-NULL.\n" ); -+ ok( GetLastError() == ERROR_ACCESS_DENIED, "got %ld.\n", GetLastError() ); -+ - w2 = OpenWindowStationA("winsta0", TRUE, WINSTA_ALL_ACCESS ); - ok( w2 != 0, "OpenWindowStation failed\n" ); - ok( w2 != w1, "OpenWindowStation returned default handle\n" ); -diff --git a/server/handle.c b/server/handle.c -index ef243e06e0b..7d19402ef7d 100644 ---- a/server/handle.c -+++ b/server/handle.c -@@ -288,6 +288,15 @@ obj_handle_t alloc_handle( struct process *process, void *ptr, unsigned int acce - return alloc_handle_entry( process, ptr, access, attr ); - } - -+/* allocate handle for opening an object by userspace request */ -+obj_handle_t alloc_handle_user_open( struct process *process, void *obj, unsigned int access, unsigned int attr ) -+{ -+ if (access) return alloc_handle( process, obj, access, attr ); -+ -+ set_error( STATUS_ACCESS_DENIED ); -+ return 0; -+} -+ - /* allocate a global handle for an object, incrementing its refcount */ - /* return the handle, or 0 on error */ - static obj_handle_t alloc_global_handle_no_access_check( void *obj, unsigned int access ) -@@ -644,7 +653,7 @@ obj_handle_t open_object( struct process *process, obj_handle_t parent, unsigned - - if ((obj = open_named_object( root, ops, name, attributes ))) - { -- handle = alloc_handle( process, obj, access, attributes ); -+ handle = alloc_handle_user_open( process, obj, access, attributes ); - release_object( obj ); - } - if (root) release_object( root ); -diff --git a/server/handle.h b/server/handle.h -index 1d02e040258..ab8ee382297 100644 ---- a/server/handle.h -+++ b/server/handle.h -@@ -38,6 +38,8 @@ extern obj_handle_t alloc_handle( struct process *process, void *obj, - unsigned int access, unsigned int attr ); - extern obj_handle_t alloc_handle_no_access_check( struct process *process, void *ptr, - unsigned int access, unsigned int attr ); -+extern obj_handle_t alloc_handle_user_open( struct process *process, void *obj, -+ unsigned int access, unsigned int attr ); - extern unsigned int close_handle( struct process *process, obj_handle_t handle ); - extern struct object *get_handle_obj( struct process *process, obj_handle_t handle, - unsigned int access, const struct object_ops *ops ); -diff --git a/server/process.c b/server/process.c -index 155dc050d95..488c9a66417 100644 ---- a/server/process.c -+++ b/server/process.c -@@ -1442,7 +1442,7 @@ DECL_HANDLER(open_process) - reply->handle = 0; - if (process) - { -- reply->handle = alloc_handle( current->process, process, req->access, req->attributes ); -+ reply->handle = alloc_handle_user_open( current->process, process, req->access, req->attributes ); - release_object( process ); - } - } -diff --git a/server/thread.c b/server/thread.c -index 6542e1584ab..0ba34511cd5 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -1477,7 +1477,7 @@ DECL_HANDLER(open_thread) - reply->handle = 0; - if (thread) - { -- reply->handle = alloc_handle( current->process, thread, req->access, req->attributes ); -+ reply->handle = alloc_handle_user_open( current->process, thread, req->access, req->attributes ); - release_object( thread ); - } - } --- -GitLab - - -From 847d9411278ac3e91b20949e1184761aa6ce25e3 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Wed, 10 Jul 2024 16:53:49 -0600 -Subject: [PATCH 4/4] server: Skip inaccessible threads in (get_next_thread). - ---- - dlls/ntdll/tests/om.c | 3 +-- - server/thread.c | 10 +++++++--- - 2 files changed, 8 insertions(+), 5 deletions(-) - -diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c -index fd23038500a..bb6cf9059e1 100644 ---- a/dlls/ntdll/tests/om.c -+++ b/dlls/ntdll/tests/om.c -@@ -3431,8 +3431,7 @@ static void test_zero_access(void) - CloseHandle( h1 ); - - status = NtGetNextThread(GetCurrentProcess(), NULL, 0, 0, 0, &h1); -- todo_wine ok( status == STATUS_NO_MORE_ENTRIES, "got %#lx.\n", status ); -- if (!status) CloseHandle( h1 ); -+ ok( status == STATUS_NO_MORE_ENTRIES, "got %#lx.\n", status ); - - InitializeObjectAttributes( &attr, NULL, 0, 0, NULL ); - cid.UniqueProcess = ULongToHandle( GetCurrentProcessId() ); -diff --git a/server/thread.c b/server/thread.c -index 0ba34511cd5..b3cf550349a 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -2023,9 +2023,13 @@ DECL_HANDLER(get_next_thread) - thread = LIST_ENTRY( ptr, struct thread, entry ); - if (thread->process == process) - { -- reply->handle = alloc_handle( current->process, thread, req->access, req->attributes ); -- release_object( process ); -- return; -+ reply->handle = alloc_handle_user_open( current->process, thread, req->access, req->attributes ); -+ if (get_error() != STATUS_ACCESS_DENIED) -+ { -+ release_object( process ); -+ return; -+ } -+ clear_error(); - } - ptr = req->flags ? list_prev( &thread_list, &thread->entry ) - : list_next( &thread_list, &thread->entry ); --- -GitLab - -From 322ce67c5916b0eb67350274142cfb8dbd972295 Mon Sep 17 00:00:00 2001 -From: Arkadiusz Hiler -Date: Wed, 4 Sep 2024 12:47:30 +0300 -Subject: [PATCH] ntoskrnl.exe: Use non-zero access mask when deleting symbolic - links. - -Fixes: d6d9d726f02c ("server: Do not allow zero access mask when opening some objects.") -CW-Bug-Id: #24206 -CW-Bug-Id: #24016 ---- - dlls/ntoskrnl.exe/ntoskrnl.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c -index 4668b58ef16..b62ef007250 100644 ---- a/dlls/ntoskrnl.exe/ntoskrnl.c -+++ b/dlls/ntoskrnl.exe/ntoskrnl.c -@@ -1803,7 +1803,7 @@ NTSTATUS WINAPI IoDeleteSymbolicLink( UNICODE_STRING *name ) - attr.SecurityDescriptor = NULL; - attr.SecurityQualityOfService = NULL; - -- if (!(status = NtOpenSymbolicLinkObject( &handle, DELETE, &attr ))) -+ if (!(status = NtOpenSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr ))) - { - NtMakeTemporaryObject( handle ); - NtClose( handle ); diff --git a/0003-pending-mrs-and-backports/9999-misc-loose/0105-ps6125-server-Ensure-in-pending-delete-on-close-that-path-to-unlink.patch b/0003-pending-mrs-and-backports/9999-misc-loose/0105-ps6125-server-Ensure-in-pending-delete-on-close-that-path-to-unlink.patch deleted file mode 100644 index 6a28444..0000000 --- a/0003-pending-mrs-and-backports/9999-misc-loose/0105-ps6125-server-Ensure-in-pending-delete-on-close-that-path-to-unlink.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0ef37d1fee67d5698ebbd1e21446a1bdc3244dbb Mon Sep 17 00:00:00 2001 -From: Eric Pouech -Date: Sun, 30 Jun 2024 09:54:37 +0200 -Subject: [PATCH] server: Ensure in pending delete on close that path to unlink - are unique. - -This avoids the server piling up closed_fd objects when several delete are -called on the same path. - -Signed-off-by: Eric Pouech ---- - server/fd.c | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -diff --git a/server/fd.c b/server/fd.c -index f28937466fc..b5f5cd24574 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -1171,6 +1171,18 @@ static struct inode *get_inode( dev_t dev, ino_t ino, int unix_fd ) - return inode; - } - -+static int inode_has_pending_close( struct inode *inode, const char *path ) -+{ -+ struct fd *fd; -+ -+ LIST_FOR_EACH_ENTRY( fd, &inode->closed, struct fd, inode_entry ) -+ { -+ if (fd->closed && !strcmp( fd->closed->unix_name, path )) -+ return 1; -+ } -+ return 0; -+} -+ - /* add fd to the inode list of file descriptors to close */ - static void inode_add_closed_fd( struct inode *inode, struct closed_fd *fd ) - { -@@ -1187,7 +1199,7 @@ static void inode_add_closed_fd( struct inode *inode, struct closed_fd *fd ) - free( fd->unix_name ); - free( fd ); - } -- else if (fd->disp_flags & FILE_DISPOSITION_DELETE) -+ else if ((fd->disp_flags & FILE_DISPOSITION_DELETE) && !inode_has_pending_close( inode, fd->unix_name )) - { - /* close the fd but keep the structure around for unlink */ - if (fd->unix_fd != -1) close( fd->unix_fd ); --- -GitLab - diff --git a/0004-build-fix-undebug-optimize/0001-ntdll-Unroll-memcpy-instead-of-preventing-optimisati.patch b/0004-build-fix-undebug-optimize/0001-ntdll-Unroll-memcpy-instead-of-preventing-optimisati.patch deleted file mode 100644 index d7f655c..0000000 --- a/0004-build-fix-undebug-optimize/0001-ntdll-Unroll-memcpy-instead-of-preventing-optimisati.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 9d81d53f8f3460314c8b26cf800cab0433dd1a94 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Mon, 24 May 2021 19:21:13 +0200 -Subject: [PATCH 1/4] ntdll: Unroll memcpy instead of preventing optimisations. - ---- - dlls/ntdll/string.c | 115 +++++++++++++++++++++++++++++++++----------- - 1 file changed, 87 insertions(+), 28 deletions(-) - -diff --git a/dlls/ntdll/string.c b/dlls/ntdll/string.c -index a48496b65c6..39762015262 100644 ---- a/dlls/ntdll/string.c -+++ b/dlls/ntdll/string.c -@@ -95,53 +95,112 @@ int __cdecl memcmp( const void *ptr1, const void *ptr2, size_t n ) - } - - --/********************************************************************* -- * memcpy (NTDLL.@) -- * -- * NOTES -- * Behaves like memmove. -- */ --void * __cdecl memcpy( void *dst, const void *src, size_t n ) -+static FORCEINLINE void memmove_unaligned_24( char *d, const char *s, size_t n ) - { -- volatile unsigned char *d = dst; /* avoid gcc optimizations */ -- const unsigned char *s = src; -+ typedef uint64_t DECLSPEC_ALIGN(1) unaligned_ui64; -+ typedef uint32_t DECLSPEC_ALIGN(1) unaligned_ui32; -+ typedef uint16_t DECLSPEC_ALIGN(1) unaligned_ui16; -+ uint64_t tmp0, tmp1, tmpn; - -- if ((size_t)dst - (size_t)src >= n) -+ if (n >= 16) - { -- while (n--) *d++ = *s++; -+ tmp0 = *(unaligned_ui64 *)s; -+ tmp1 = *(unaligned_ui64 *)(s + 8); -+ tmpn = *(unaligned_ui64 *)(s + n - 8); -+ *(unaligned_ui64 *)d = tmp0; -+ *(unaligned_ui64 *)(d + 8) = tmp1; -+ *(unaligned_ui64 *)(d + n - 8) = tmpn; - } -- else -+ else if (n >= 8) - { -- d += n - 1; -- s += n - 1; -- while (n--) *d-- = *s--; -+ tmp0 = *(unaligned_ui64 *)s; -+ tmpn = *(unaligned_ui64 *)(s + n - 8); -+ *(unaligned_ui64 *)d = tmp0; -+ *(unaligned_ui64 *)(d + n - 8) = tmpn; -+ } -+ else if (n >= 4) -+ { -+ tmp0 = *(unaligned_ui32 *)s; -+ tmpn = *(unaligned_ui32 *)(s + n - 4); -+ *(unaligned_ui32 *)d = tmp0; -+ *(unaligned_ui32 *)(d + n - 4) = tmpn; -+ } -+ else if (n >= 2) -+ { -+ tmp0 = *(unaligned_ui16 *)s; -+ tmpn = *(unaligned_ui16 *)(s + n - 2); -+ *(unaligned_ui16 *)d = tmp0; -+ *(unaligned_ui16 *)(d + n - 2) = tmpn; -+ } -+ else if (n >= 1) -+ { -+ *(uint8_t *)d = *(uint8_t *)s; - } -- return dst; - } - -- --/********************************************************************* -- * memmove (NTDLL.@) -- */ --void * __cdecl memmove( void *dst, const void *src, size_t n ) -+static FORCEINLINE void *memmove_unrolled( char *dst, const char *src, size_t n ) - { -- volatile unsigned char *d = dst; /* avoid gcc optimizations */ -- const unsigned char *s = src; -+ typedef uint64_t DECLSPEC_ALIGN(1) unaligned_ui64; -+ uint64_t tmp0, tmp1, tmp2; -+ char *end; - -- if ((size_t)dst - (size_t)src >= n) -+ if (n <= 24) memmove_unaligned_24( dst, src, n ); -+ else if ((size_t)dst - (size_t)src >= n) - { -- while (n--) *d++ = *s++; -+ end = dst + n; src += n; -+ do -+ { -+ tmp0 = *(unaligned_ui64 *)(src - n + 0); -+ tmp1 = *(unaligned_ui64 *)(src - n + 8); -+ tmp2 = *(unaligned_ui64 *)(src - n + 16); -+ *(unaligned_ui64*)(end - n + 0) = tmp0; -+ *(unaligned_ui64*)(end - n + 8) = tmp1; -+ *(unaligned_ui64*)(end - n + 16) = tmp2; -+ n -= 24; -+ } -+ while (n >= 24); -+ memmove_unaligned_24( end - n, src - n, n ); - } - else - { -- d += n - 1; -- s += n - 1; -- while (n--) *d-- = *s--; -+ do -+ { -+ tmp0 = *(unaligned_ui64 *)(src + n - 8); -+ tmp1 = *(unaligned_ui64 *)(src + n - 16); -+ tmp2 = *(unaligned_ui64 *)(src + n - 24); -+ *(unaligned_ui64*)(dst + n - 8) = tmp0; -+ *(unaligned_ui64*)(dst + n - 16) = tmp1; -+ *(unaligned_ui64*)(dst + n - 24) = tmp2; -+ n -= 24; -+ } -+ while (n >= 24); -+ memmove_unaligned_24( dst, src, n ); - } - return dst; - } - - -+/********************************************************************* -+ * memcpy (NTDLL.@) -+ * -+ * NOTES -+ * Behaves like memmove. -+ */ -+void * __cdecl memcpy( void *dst, const void *src, size_t n ) -+{ -+ return memmove_unrolled( dst, src, n ); -+} -+ -+ -+/********************************************************************* -+ * memmove (NTDLL.@) -+ */ -+void * __cdecl memmove( void *dst, const void *src, size_t n ) -+{ -+ return memmove_unrolled( dst, src, n ); -+} -+ -+ - /********************************************************************* - * memcpy_s (MSVCRT.@) - */ --- -2.45.0 - diff --git a/0004-build-fix-undebug-optimize/5500-include-Allow-regular-atomic-builtins-if-they-re-not.patch b/0004-build-fix-undebug-optimize/5500-include-Allow-regular-atomic-builtins-if-they-re-not.patch new file mode 100644 index 0000000..a1f4311 --- /dev/null +++ b/0004-build-fix-undebug-optimize/5500-include-Allow-regular-atomic-builtins-if-they-re-not.patch @@ -0,0 +1,43 @@ +From e681a9165e2708dd2128499d58582ac1175518ab Mon Sep 17 00:00:00 2001 +From: William Horvath +Date: Thu, 5 Dec 2024 19:25:37 -0800 +Subject: [PATCH] include: Allow regular atomic builtins if they're not bugged. + +--- + include/winnt.h | 6 ++++---- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/include/winnt.h b/include/winnt.h +index cf94ac3b034..be88d868c1e 100644 +--- a/include/winnt.h ++++ b/include/winnt.h +@@ -7257,7 +7257,7 @@ static FORCEINLINE LONGLONG WINAPI InterlockedCompareExchange64( LONGLONG volati + static FORCEINLINE LONG WINAPI InterlockedExchange( LONG volatile *dest, LONG val ) + { + LONG ret; +-#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) ++#if defined(__clang__) || ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))) + ret = __atomic_exchange_n( dest, val, __ATOMIC_SEQ_CST ); + #elif defined(__i386__) || defined(__x86_64__) + __asm__ __volatile__( "lock; xchgl %0,(%1)" +@@ -7316,7 +7316,7 @@ static FORCEINLINE LONGLONG WINAPI InterlockedDecrement64( LONGLONG volatile *de + static FORCEINLINE void * WINAPI InterlockedExchangePointer( void *volatile *dest, void *val ) + { + void *ret; +-#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) ++#if defined(__clang__) || ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))) + ret = __atomic_exchange_n( dest, val, __ATOMIC_SEQ_CST ); + #elif defined(__x86_64__) + __asm__ __volatile__( "lock; xchgq %0,(%1)" : "=r" (ret) :"r" (dest), "0" (val) : "memory" ); +@@ -7353,7 +7353,7 @@ static FORCEINLINE void MemoryBarrier(void) + __sync_synchronize(); + } + +-#if defined(__x86_64__) || defined(__i386__) ++#if !(defined(__clang__) || (__GNUC__ > 6)) && (defined(__x86_64__) || defined(__i386__)) + /* On x86, Support old GCC with either no or buggy (GCC BZ#81316) __atomic_* support */ + #define __WINE_ATOMIC_LOAD_ACQUIRE(ptr, ret) do { *(ret) = *(ptr); __asm__ __volatile__( "" ::: "memory" ); } while (0) + #define __WINE_ATOMIC_LOAD_RELAXED(ptr, ret) do { *(ret) = *(ptr); } while (0) +-- +2.47.1 + diff --git a/0004-build-fix-undebug-optimize/5700-include-Allow-YieldProcessor-on-Clang-MSVC-mode.patch b/0004-build-fix-undebug-optimize/5700-include-Allow-YieldProcessor-on-Clang-MSVC-mode.patch new file mode 100644 index 0000000..f488c28 --- /dev/null +++ b/0004-build-fix-undebug-optimize/5700-include-Allow-YieldProcessor-on-Clang-MSVC-mode.patch @@ -0,0 +1,25 @@ +From 829b3ddcb329400add3cc8304876d39721d79c67 Mon Sep 17 00:00:00 2001 +From: William Horvath +Date: Thu, 5 Dec 2024 18:30:00 -0800 +Subject: [PATCH] include: Allow YieldProcessor() on Clang MSVC mode. + +--- + include/winnt.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/winnt.h b/include/winnt.h +index 883ca26d409..d2ca7967be5 100644 +--- a/include/winnt.h ++++ b/include/winnt.h +@@ -7478,7 +7478,7 @@ static FORCEINLINE unsigned char InterlockedCompareExchange128( volatile __int64 + + static FORCEINLINE void YieldProcessor(void) + { +-#ifdef __GNUC__ ++#if defined(__GNUC__) || defined(__clang__) + #if defined(__i386__) || defined(__x86_64__) + __asm__ __volatile__( "rep; nop" : : : "memory" ); + #elif defined(__arm__) || defined(__aarch64__) +-- +2.47.1 + diff --git a/0004-build-fix-undebug-optimize/6000-msvcrt-Allow-SSE-if-_MSVCR_VER-0.patch b/0004-build-fix-undebug-optimize/6000-msvcrt-Allow-SSE-if-_MSVCR_VER-0.patch deleted file mode 100644 index bd1475a..0000000 --- a/0004-build-fix-undebug-optimize/6000-msvcrt-Allow-SSE-if-_MSVCR_VER-0.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 5a0aea0b23c60be816d4201e9d77ed826ff818ed Mon Sep 17 00:00:00 2001 -From: William Horvath -Date: Thu, 14 Nov 2024 04:47:53 -0800 -Subject: [PATCH] msvcrt: Allow SSE if _MSVCR_VER == 0 - ---- - dlls/msvcrt/math.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c -index be345fb7a4a..dbb0ee5e540 100644 ---- a/dlls/msvcrt/math.c -+++ b/dlls/msvcrt/math.c -@@ -70,7 +70,7 @@ static BOOL sse2_enabled; - void msvcrt_init_math( void *module ) - { - sse2_supported = IsProcessorFeaturePresent( PF_XMMI64_INSTRUCTIONS_AVAILABLE ); --#if _MSVCR_VER <=71 -+#if _MSVCR_VER > 0 && _MSVCR_VER <=71 - sse2_enabled = FALSE; - #else - sse2_enabled = sse2_supported; --- -2.47.0 - diff --git a/0004-build-fix-undebug-optimize/6000-server-Disable-debug-features-if-NDEBUG-is-d.patch b/0004-build-fix-undebug-optimize/6000-server-Disable-debug-features-if-NDEBUG-is-d.patch new file mode 100644 index 0000000..cbb1f27 --- /dev/null +++ b/0004-build-fix-undebug-optimize/6000-server-Disable-debug-features-if-NDEBUG-is-d.patch @@ -0,0 +1,27 @@ +From b4f3bbfe08ce92cc78b21543a149e8f876c7235e Mon Sep 17 00:00:00 2001 +From: William Horvath +Date: Thu, 5 Dec 2024 17:50:13 -0800 +Subject: [PATCH] server: Disable debug features if NDEBUG is defined. + +Co-authored-by: Torge Matthies +--- + server/object.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/server/object.h b/server/object.h +index 20d242f3079..c27407e8375 100644 +--- a/server/object.h ++++ b/server/object.h +@@ -26,7 +26,9 @@ + #include "wine/server_protocol.h" + #include "wine/list.h" + ++#ifndef NDEBUG + #define DEBUG_OBJECTS ++#endif + + /* kernel objects */ + +-- +2.47.1 + diff --git a/0004-build-fix-undebug-optimize/7000-makedep-add-per-source-cflags-and-per-program-ldflag.patch b/0004-build-fix-undebug-optimize/7000-makedep-add-per-source-cflags-and-per-program-ldflag.patch new file mode 100644 index 0000000..55e7d4d --- /dev/null +++ b/0004-build-fix-undebug-optimize/7000-makedep-add-per-source-cflags-and-per-program-ldflag.patch @@ -0,0 +1,77 @@ +From ba270452e93b535342cea706cbb904d6758919b6 Mon Sep 17 00:00:00 2001 +From: Stelios Tsampas +Date: Thu, 21 Nov 2024 00:59:01 +0200 +Subject: [PATCH 2/3] makedep: add per-source cflags and per-program ldflags + variables + +Co-authored-by: William Horvath +--- + tools/makedep.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/tools/makedep.c b/tools/makedep.c +index c1937363c39..2980c26d01a 100644 +--- a/tools/makedep.c ++++ b/tools/makedep.c +@@ -470,6 +470,19 @@ static const char *get_base_name( const char *name ) + return base; + } + ++/******************************************************************* ++ * replace_char ++ */ ++char* replace_char(char* str, char find, char replace) ++{ ++ char *current_pos; ++ current_pos = strchr(str, find); ++ while (current_pos) { ++ *current_pos = replace; ++ current_pos = strchr(current_pos + 1, find); ++ }; ++ return str; ++} + + /******************************************************************* + * replace_filename +@@ -3199,6 +3212,7 @@ static void output_source_one_arch( struct makefile *make, struct incl_file *sou + unsigned int arch ) + { + const char *obj_name, *var_cc, *var_cflags; ++ char obj2[256] = {0}; + struct compile_command *cmd; + struct strarray cflags = empty_strarray; + +@@ -3271,6 +3285,11 @@ static void output_source_one_arch( struct makefile *make, struct incl_file *sou + output_filenames( defines ); + output_filenames( cflags ); + output_filename( var_cflags ); ++ strncpy( obj2, obj, sizeof( obj2 ) ); ++ obj2[ sizeof( obj2 ) - 1] = '\0'; ++ replace_char( obj2, '-', '_' ); ++ replace_char( obj2, '.', '_' ); ++ output_filename( arch_make_variable( strmake( "%s_CFLAGS", basename( obj2 ) ), arch )); + output( "\n" ); + + if (make->testdll && strendswith( source->name, ".c" ) && +@@ -3708,6 +3727,7 @@ static void output_programs( struct makefile *make ) + { + unsigned int i, j; + unsigned int arch = 0; /* programs are always native */ ++ char program2[256] = {0}; + + for (i = 0; i < make->programs.count; i++) + { +@@ -3733,6 +3753,10 @@ static void output_programs( struct makefile *make ) + output_filenames_obj_dir( make, objs ); + output_filenames( all_libs ); + output_filename( "$(LDFLAGS)" ); ++ strncpy( program2, program, sizeof( program2 ) ); ++ program2[ sizeof( program2 ) - 1] = '\0'; ++ replace_char( program2, '-', '_' ); ++ output_filename( arch_make_variable( strmake( "%s_LDFLAGS", basename( program2 ) ), arch )); + output( "\n" ); + strarray_add( &make->all_targets[arch], program ); + +-- +2.47.0 + diff --git a/0004-build-fix-undebug-optimize/ps0264-p0001-server-Disable-debug-features-if-NDEBUG-is-d.patch b/0004-build-fix-undebug-optimize/ps0264-p0001-server-Disable-debug-features-if-NDEBUG-is-d.patch deleted file mode 100644 index 601bedb..0000000 --- a/0004-build-fix-undebug-optimize/ps0264-p0001-server-Disable-debug-features-if-NDEBUG-is-d.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 77563dc4b72b25c9c0072384dbc8286dd0cc6d69 Mon Sep 17 00:00:00 2001 -From: Torge Matthies -Date: 20 Jun 2024 -Subject: [PATCH 1/3] server: Disable debug features if NDEBUG is defined. (updated for shared memory upstream) - -Signed-off-by: Torge Matthies ---- - server/object.c | 8 ++++++-- - server/object.h | 2 ++ - 2 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/server/object.c b/server/object.c -index 11111111111..11111111111 100644 ---- a/server/object.c -+++ b/server/object.c -@@ -102,6 +102,7 @@ void close_objects(void) - - /*****************************************************************/ - -+#ifndef NDEBUG - /* mark a block of memory as uninitialized for debugging purposes */ - static inline void mark_block_uninitialized( void *ptr, size_t size ) - { -@@ -112,13 +113,16 @@ static inline void mark_block_uninitialized( void *ptr, size_t size ) - VALGRIND_DISCARD( VALGRIND_MAKE_WRITABLE( ptr, size )); - #endif - } -+#endif - - /* malloc replacement */ - void *mem_alloc( size_t size ) - { - void *ptr = malloc( size ); -- if (ptr) mark_block_uninitialized( ptr, size ); -- else set_error( STATUS_NO_MEMORY ); -+ if (!ptr) set_error( STATUS_NO_MEMORY ); -+#ifndef NDEBUG -+ else mark_block_uninitialized( ptr, size ); -+#endif - return ptr; - } - -diff --git a/server/object.h b/server/object.h -index 11111111111..11111111111 100644 ---- a/server/object.h -+++ b/server/object.h -@@ -26,7 +26,9 @@ - #include "wine/server_protocol.h" - #include "wine/list.h" - -+#ifndef NDEBUG - #define DEBUG_OBJECTS -+#endif - - /* kernel objects */ - -diff --git a/server/mapping.c b/server/mapping.c -index 71dfaae..035d45c 100644 ---- a/server/mapping.c -+++ b/server/mapping.c -@@ -1391,7 +1391,9 @@ const volatile void *alloc_shared_object(void) - SHARED_WRITE_BEGIN( &object->obj.shm, object_shm_t ) - { - /* mark the object data as uninitialized */ -+#ifndef NDEBUG - mark_block_uninitialized( (void *)shared, sizeof(*shared) ); -+#endif - CONTAINING_RECORD( shared, shared_object_t, shm )->id = ++session.last_object_id; - } - SHARED_WRITE_END; diff --git a/0007-proton-esync-fsync/0260-fsync-remove-clock_gettime-syscall-from-get_wait_end.patch b/0007-proton-esync-fsync/0260-fsync-remove-clock_gettime-syscall-from-get_wait_end.patch index c17ea8a..18f28c8 100644 --- a/0007-proton-esync-fsync/0260-fsync-remove-clock_gettime-syscall-from-get_wait_end.patch +++ b/0007-proton-esync-fsync/0260-fsync-remove-clock_gettime-syscall-from-get_wait_end.patch @@ -60,7 +60,7 @@ index 90ed801f11e..87bc12662ad 100644 - - nt_end -= SECS_1601_TO_1970 * TICKSPERSEC; - end->tv_sec = nt_end / (ULONGLONG)TICKSPERSEC; -+ end->tv_sec = nt_end / TICKSPERSEC; ++ end->tv_sec = nt_end / (ULONGLONG)TICKSPERSEC; end->tv_nsec = (nt_end % TICKSPERSEC) * 100; } diff --git a/0007-proton-esync-fsync/0261-fsync-Use-monitorx-mwaitx-and-spin-before-relying-on.patch b/0007-proton-esync-fsync/0261-fsync-Use-monitorx-mwaitx-and-spin-before-relying-on.patch index 4f62b14..ace35f7 100644 --- a/0007-proton-esync-fsync/0261-fsync-Use-monitorx-mwaitx-and-spin-before-relying-on.patch +++ b/0007-proton-esync-fsync/0261-fsync-Use-monitorx-mwaitx-and-spin-before-relying-on.patch @@ -55,16 +55,16 @@ index 169ceab10ad..40b10b0d8d2 100644 + } \ + } while (0) + -+/* Time to wait in mwaitx, tuned based on a synchronization benchmark -+ * that probably captures 0 real-world scenarios. */ ++/* Time to wait in mwaitx, values ++ * probably capture 0 real-world scenarios. */ +#define MUTEX_MON_TIMEOUT 1000 +#define AUTO_MON_TIMEOUT 1000 -+#define MANUAL_MON_TIMEOUT 2000 ++#define MANUAL_MON_TIMEOUT 1000 +#define SEM_MON_TIMEOUT 1000 + +/* Conservative spin config */ -+#define SPIN_MAX_RETRIES 4 /* Maximum retries before switching to pure yields */ -+#define SPIN_MAX_YIELDS 12 /* Maximum number of pure yields before giving up */ ++#define SPIN_MAX_RETRIES 3 /* Maximum retries before switching to pure yields */ ++#define SPIN_MAX_YIELDS 9 /* Maximum number of pure yields before giving up */ + +/* Fast path attempt to detect a value change using monitorx/mwaitx instructions + spinning + * Returns STATUS_SUCCESS if the value changed, STATUS_UNSUCCESSFUL otherwise. diff --git a/0009-windowing-system-integration/0001-misc-osu-related/0021-winex11-Improved-osu-childwindow-hack.patch b/0009-windowing-system-integration/0001-misc-osu-related/0021-winex11-Improved-osu-childwindow-hack.patch index 448f545..fbf7597 100644 --- a/0009-windowing-system-integration/0001-misc-osu-related/0021-winex11-Improved-osu-childwindow-hack.patch +++ b/0009-windowing-system-integration/0001-misc-osu-related/0021-winex11-Improved-osu-childwindow-hack.patch @@ -10,9 +10,8 @@ the composition-free page-flipping rendering path instead of blitting. --- dlls/ntdll/unix/loader.c | 9 +++++ dlls/winex11.drv/init.c | 69 +++++++++++++++++++++++++++++++++++++-- - dlls/winex11.drv/opengl.c | 3 +- dlls/winex11.drv/x11drv.h | 12 +++++++ - 4 files changed, 89 insertions(+), 4 deletions(-) + 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 6e432a943cc..190d3332c7f 100644 @@ -117,27 +116,6 @@ index 0f5b91d469e..0eb24f7dbc0 100644 return FALSE; } -diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c -index dce5f68c35f..5c5bb8f0602 100644 ---- a/dlls/winex11.drv/opengl.c -+++ b/dlls/winex11.drv/opengl.c -@@ -790,6 +790,7 @@ static void init_pixel_formats( Display *display ) - int fmt_id, nCfgs, i, run, bmp_formats; - GLXFBConfig* cfgs; - XVisualInfo *visinfo; -+ int tmp_value; - - cfgs = pglXGetFBConfigs(display, DefaultScreen(display), &nCfgs); - if (NULL == cfgs || 0 == nCfgs) { -@@ -833,7 +834,7 @@ static void init_pixel_formats( Display *display ) - * As of the introduction of composition managers at least Nvidia now also offers ARGB visuals - * with a depth of 32 in addition to the default 24 bit. In order to prevent BadMatch errors we only - * list formats with the same depth. */ -- if(visinfo->depth != default_visual.depth) -+ if((visinfo->depth != default_visual.depth) || (use_osu_child_hack() && !pglXGetFBConfigAttrib( display, cfgs[i], GLX_STENCIL_SIZE, &tmp_value ) && tmp_value)) - { - XFree(visinfo); - continue; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index c54a33c43a7..637afaa5e3b 100644 --- a/dlls/winex11.drv/x11drv.h diff --git a/0009-windowing-system-integration/0001-misc-osu-related/0022-winex11-Disable-update_user_time-if-the-WM-doesn-t-s.patch b/0009-windowing-system-integration/0001-misc-osu-related/0022-winex11-Disable-update_user_time-if-the-WM-doesn-t-s.patch index abe82a9..10ce36a 100644 --- a/0009-windowing-system-integration/0001-misc-osu-related/0022-winex11-Disable-update_user_time-if-the-WM-doesn-t-s.patch +++ b/0009-windowing-system-integration/0001-misc-osu-related/0022-winex11-Disable-update_user_time-if-the-WM-doesn-t-s.patch @@ -17,7 +17,7 @@ index 74d445a9e0a..fcaef1f4c87 100644 static XContext host_window_context = 0; /* time of last user event and window where it's stored */ -+static BOOL is_netwm_supported( Display *display, Atom atom ); ++static BOOL is_netwm_supported( Atom atom ); static Time last_user_time; static Window user_time_window; +static BOOL user_time_supported = TRUE; @@ -34,8 +34,8 @@ index 74d445a9e0a..fcaef1f4c87 100644 - XChangeProperty( display, window, x11drv_atom(_NET_WM_USER_TIME_WINDOW), - XA_WINDOW, 32, PropModeReplace, (unsigned char *)&user_time_window, 1 ); + if (user_time_supported && -+ is_netwm_supported(display, x11drv_atom(_NET_WM_USER_TIME_WINDOW)) && -+ is_netwm_supported(display, x11drv_atom(_NET_WM_USER_TIME))) ++ is_netwm_supported( x11drv_atom(_NET_WM_USER_TIME_WINDOW) ) && ++ is_netwm_supported( x11drv_atom(_NET_WM_USER_TIME) )) + { + update_user_time( 0 ); /* make sure that the user time window exists */ + if (user_time_window) diff --git a/0009-windowing-system-integration/0002-rbernon-patchsets/0007-winex11.drv-Do-not-enable-disable-XInput2-when-clipp.patch b/0009-windowing-system-integration/0001-misc-osu-related/0030-winex11.drv-Do-not-enable-disable-XInput2-when-clipp.patch similarity index 100% rename from 0009-windowing-system-integration/0002-rbernon-patchsets/0007-winex11.drv-Do-not-enable-disable-XInput2-when-clipp.patch rename to 0009-windowing-system-integration/0001-misc-osu-related/0030-winex11.drv-Do-not-enable-disable-XInput2-when-clipp.patch diff --git a/0009-windowing-system-integration/0002-rbernon-patchsets/0004-user32-Notify-the-driver-of-icon-destruction-before-.patch b/0009-windowing-system-integration/0002-rbernon-patchsets/0004-user32-Notify-the-driver-of-icon-destruction-before-.patch deleted file mode 100644 index b72d0ad..0000000 --- a/0009-windowing-system-integration/0002-rbernon-patchsets/0004-user32-Notify-the-driver-of-icon-destruction-before-.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 771f0fccf0298dd02ea0c41baf2a30bed9b001d5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Thu, 24 Feb 2022 17:10:39 +0100 -Subject: [PATCH 4/7] user32: Notify the driver of icon destruction before - releasing it. - -To prevent a race condition when sending desktop destroy notifications -with the handle possibly re-used. ---- - dlls/win32u/cursoricon.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/dlls/win32u/cursoricon.c b/dlls/win32u/cursoricon.c -index 11111111111..11111111111 100644 ---- a/dlls/win32u/cursoricon.c -+++ b/dlls/win32u/cursoricon.c -@@ -198,6 +198,7 @@ static BOOL free_icon_handle( HICON handle ) - { - struct cursoricon_object *obj = free_user_handle( handle, NTUSER_OBJ_ICON ); - -+ user_driver->pDestroyCursorIcon( handle ); - if (obj == OBJ_OTHER_PROCESS) WARN( "icon handle %p from other process\n", handle ); - else if (obj) - { -@@ -236,7 +237,6 @@ static BOOL free_icon_handle( HICON handle ) - if (!IS_INTRESOURCE( obj->resname )) free( obj->resname ); - free( obj ); - KeUserDispatchCallback( ¶ms.dispatch, sizeof(params), &ret_ptr, &ret_len ); -- user_driver->pDestroyCursorIcon( handle ); - return TRUE; - } - return FALSE; --- -0.0.0 - diff --git a/0009-windowing-system-integration/0002-rbernon-patchsets/0005-winex11.drv-Properly-cache-HCURSOR-to-Cursor-associa.patch b/0009-windowing-system-integration/0002-rbernon-patchsets/0005-winex11.drv-Properly-cache-HCURSOR-to-Cursor-associa.patch deleted file mode 100644 index 4af64c3..0000000 --- a/0009-windowing-system-integration/0002-rbernon-patchsets/0005-winex11.drv-Properly-cache-HCURSOR-to-Cursor-associa.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 964ab7685b0879d39eb46ac87624a1a17d2c975d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Fri, 22 Jan 2021 13:44:19 +0100 -Subject: [PATCH 5/7] winex11.drv: Properly cache HCURSOR to Cursor - associations. - ---- - dlls/winex11.drv/mouse.c | 61 ++++++++++++++++++++++++---------------- - 1 file changed, 37 insertions(+), 24 deletions(-) - -diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c -index 11111111111..11111111111 100644 ---- a/dlls/winex11.drv/mouse.c -+++ b/dlls/winex11.drv/mouse.c -@@ -202,35 +202,46 @@ static Cursor get_empty_cursor(void) - return cursor; - } - -+static Cursor get_cursor( HCURSOR handle ) -+{ -+ Cursor cursor, prev; -+ -+ if (!handle) return get_empty_cursor(); -+ -+ XLockDisplay( gdi_display ); -+ if (!XFindContext( gdi_display, (XID)handle, cursor_context, (char **)&cursor )) -+ { -+ XUnlockDisplay( gdi_display ); -+ return cursor; -+ } -+ XUnlockDisplay( gdi_display ); -+ -+ /* try to create it */ -+ if (!(cursor = create_cursor( handle ))) return None; -+ -+ XLockDisplay( gdi_display ); -+ if (!XFindContext( gdi_display, (XID)handle, cursor_context, (char **)&prev )) -+ { -+ /* someone else was here first */ -+ XFreeCursor( gdi_display, cursor ); -+ cursor = prev; -+ } -+ else -+ { -+ XSaveContext( gdi_display, (XID)handle, cursor_context, (char *)cursor ); -+ TRACE( "cursor %p created %lx\n", handle, cursor ); -+ } -+ XUnlockDisplay( gdi_display ); -+ -+ return cursor; -+} -+ - /*********************************************************************** - * set_window_cursor - */ - void set_window_cursor( Window window, HCURSOR handle ) - { -- Cursor cursor, prev; -- -- if (!handle) cursor = get_empty_cursor(); -- else if (XFindContext( gdi_display, (XID)handle, cursor_context, (char **)&cursor )) -- { -- /* try to create it */ -- if (!(cursor = create_cursor( handle ))) return; -- -- XLockDisplay( gdi_display ); -- if (!XFindContext( gdi_display, (XID)handle, cursor_context, (char **)&prev )) -- { -- /* someone else was here first */ -- XFreeCursor( gdi_display, cursor ); -- cursor = prev; -- } -- else -- { -- XSaveContext( gdi_display, (XID)handle, cursor_context, (char *)cursor ); -- TRACE( "cursor %p created %lx\n", handle, cursor ); -- } -- XUnlockDisplay( gdi_display ); -- } -- -- XDefineCursor( gdi_display, window, cursor ); -+ XDefineCursor( gdi_display, window, get_cursor( handle ) ); - /* make the change take effect immediately */ - XFlush( gdi_display ); - } -@@ -1418,12 +1429,14 @@ void X11DRV_DestroyCursorIcon( HCURSOR handle ) - { - Cursor cursor; - -+ XLockDisplay( gdi_display ); - if (!XFindContext( gdi_display, (XID)handle, cursor_context, (char **)&cursor )) - { - TRACE( "%p xid %lx\n", handle, cursor ); - XFreeCursor( gdi_display, cursor ); - XDeleteContext( gdi_display, (XID)handle, cursor_context ); - } -+ XUnlockDisplay( gdi_display ); - } - - /*********************************************************************** --- -0.0.0 - diff --git a/0009-windowing-system-integration/0002-rbernon-patchsets/0006-winex11.drv-Notify-desktop-of-HICON-cursors-creation.patch b/0009-windowing-system-integration/0002-rbernon-patchsets/0006-winex11.drv-Notify-desktop-of-HICON-cursors-creation.patch deleted file mode 100644 index 2f73f20..0000000 --- a/0009-windowing-system-integration/0002-rbernon-patchsets/0006-winex11.drv-Notify-desktop-of-HICON-cursors-creation.patch +++ /dev/null @@ -1,76 +0,0 @@ -From fb6969a57a4871673f53cfca50008c0b3b7f8c0c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Fri, 22 Jan 2021 13:48:04 +0100 -Subject: [PATCH 6/7] winex11.drv: Notify desktop of HICON cursors creation. - ---- - dlls/winex11.drv/mouse.c | 2 ++ - dlls/winex11.drv/window.c | 15 +++++++++++++++ - dlls/winex11.drv/x11drv.h | 1 + - 3 files changed, 18 insertions(+) - -diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c -index 11111111111..11111111111 100644 ---- a/dlls/winex11.drv/mouse.c -+++ b/dlls/winex11.drv/mouse.c -@@ -229,10 +229,12 @@ static Cursor get_cursor( HCURSOR handle ) - else - { - XSaveContext( gdi_display, (XID)handle, cursor_context, (char *)cursor ); -+ XSync( gdi_display, FALSE ); /* make sure it's actually created */ - TRACE( "cursor %p created %lx\n", handle, cursor ); - } - XUnlockDisplay( gdi_display ); - -+ send_notify_message( NtUserGetDesktopWindow(), WM_X11DRV_DESKTOP_SET_HICON_CURSOR, (WPARAM)handle, cursor ); - return cursor; - } - -diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c -index 11111111111..11111111111 100644 ---- a/dlls/winex11.drv/window.c -+++ b/dlls/winex11.drv/window.c -@@ -3009,6 +3009,18 @@ done: - return swp; - } - -+/*********************************************************************** -+ * x11drv_desktop_set_hicon_cursor -+ * -+ * Function called upon receiving a WM_X11DRV_DESKTOP_SET_HICON_CURSOR. -+ */ -+static void x11drv_desktop_set_hicon_cursor( HICON handle, Cursor cursor ) -+{ -+ XLockDisplay( gdi_display ); -+ if (cursor) XSaveContext( gdi_display, (XID)handle, cursor_context, (char *)cursor ); -+ else XDeleteContext( gdi_display, (XID)handle, cursor_context ); -+ XUnlockDisplay( gdi_display ); -+} - - /********************************************************************** - * SetWindowIcon (X11DRV.@) -@@ -3275,6 +3287,9 @@ LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) - release_win_data( data ); - } - return 0; -+ case WM_X11DRV_DESKTOP_SET_HICON_CURSOR: -+ x11drv_desktop_set_hicon_cursor( (HICON)wp, (Cursor)lp ); -+ return 0; - case WM_X11DRV_DELETE_TAB: - taskbar_delete_tab( hwnd ); - return 0; -diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h -index 11111111111..11111111111 100644 ---- a/dlls/winex11.drv/x11drv.h -+++ b/dlls/winex11.drv/x11drv.h -@@ -606,6 +606,7 @@ enum x11drv_window_messages - { - WM_X11DRV_UPDATE_CLIPBOARD = WM_WINE_FIRST_DRIVER_MSG, - WM_X11DRV_SET_WIN_REGION, -+ WM_X11DRV_DESKTOP_SET_HICON_CURSOR, - WM_X11DRV_DELETE_TAB, - WM_X11DRV_ADD_TAB - }; --- -0.0.0 - diff --git a/0009-windowing-system-integration/0003-rendering/0050-user32-Send-WM_NCPAINT-as-notify-message-in-send_ncp.patch b/0009-windowing-system-integration/0003-rendering/0050-user32-Send-WM_NCPAINT-as-notify-message-in-send_ncp.patch new file mode 100644 index 0000000..d223a9e --- /dev/null +++ b/0009-windowing-system-integration/0003-rendering/0050-user32-Send-WM_NCPAINT-as-notify-message-in-send_ncp.patch @@ -0,0 +1,27 @@ +From edb36b7614415ba1f3039e71fafca82284c533f7 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Wed, 13 Jul 2022 19:56:49 -0500 +Subject: [PATCH 0855/1793] user32: Send WM_NCPAINT as notify message in + send_ncpaint(). + +CW-Bug-Id: #20969 +--- + dlls/win32u/dce.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c +index f70a2a32be9..649b82cdb6b 100644 +--- a/dlls/win32u/dce.c ++++ b/dlls/win32u/dce.c +@@ -1208,7 +1208,7 @@ static HRGN send_ncpaint( HWND hwnd, HWND *child, UINT *flags ) + if (style & WS_VSCROLL) + set_standard_scroll_painted( hwnd, SB_VERT, FALSE ); + +- send_message( hwnd, WM_NCPAINT, (WPARAM)whole_rgn, 0 ); ++ send_notify_message( hwnd, WM_NCPAINT, (WPARAM)whole_rgn, 0, FALSE ); + } + if (whole_rgn > (HRGN)1) NtGdiDeleteObjectApp( whole_rgn ); + } +-- +2.46.0 + diff --git a/0009-windowing-system-integration/0003-rendering/0205-user32-Allow-using-surface-to-paint-the-client-area-.patch b/0009-windowing-system-integration/0003-rendering/0205-user32-Allow-using-surface-to-paint-the-client-area-.patch new file mode 100644 index 0000000..8a2d791 --- /dev/null +++ b/0009-windowing-system-integration/0003-rendering/0205-user32-Allow-using-surface-to-paint-the-client-area-.patch @@ -0,0 +1,71 @@ +From bb4bbce23d1a6ac910b527cf8828022a1167c753 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Fri, 10 Sep 2021 21:51:14 +0300 +Subject: [PATCH 0205/2346] user32: Allow using surface to paint the client + area of OpenGL windows. + +CW-Bug-ID: #19216 +--- + dlls/win32u/dce.c | 16 +++++----------- + server/window.c | 3 ++- + 2 files changed, 7 insertions(+), 12 deletions(-) + +diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c +index 5df30550cae..f70a2a32be9 100644 +--- a/dlls/win32u/dce.c ++++ b/dlls/win32u/dce.c +@@ -463,7 +463,6 @@ static void update_visible_region( struct dce *dce ) + HRGN vis_rgn = 0; + HWND top_win = 0; + DWORD flags = dce->flags; +- DWORD paint_flags = 0; + size_t size = 256; + RECT win_rect, top_rect; + WND *win; +@@ -500,7 +499,6 @@ static void update_visible_region( struct dce *dce ) + top_win = wine_server_ptr_handle( reply->top_win ); + win_rect = wine_server_get_rect( reply->win_rect ); + top_rect = wine_server_get_rect( reply->top_rect ); +- paint_flags = reply->paint_flags; + } + else size = reply->total_size; + } +@@ -515,16 +513,12 @@ static void update_visible_region( struct dce *dce ) + if (dce->clip_rgn) NtGdiCombineRgn( vis_rgn, vis_rgn, dce->clip_rgn, + (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF ); + +- /* don't use a surface to paint the client area of OpenGL windows */ +- if (!(paint_flags & SET_WINPOS_PIXEL_FORMAT) || (flags & DCX_WINDOW)) ++ win = get_win_ptr( top_win ); ++ if (win && win != WND_DESKTOP && win != WND_OTHER_PROCESS) + { +- win = get_win_ptr( top_win ); +- if (win && win != WND_DESKTOP && win != WND_OTHER_PROCESS) +- { +- surface = win->surface; +- if (surface) window_surface_add_ref( surface ); +- release_win_ptr( win ); +- } ++ surface = win->surface; ++ if (surface) window_surface_add_ref( surface ); ++ release_win_ptr( win ); + } + + if (!surface) SetRectEmpty( &top_rect ); +diff --git a/server/window.c b/server/window.c +index 242e93f303a..a2b277d413a 100644 +--- a/server/window.c ++++ b/server/window.c +@@ -1248,7 +1248,8 @@ static struct region *get_surface_region( struct window *win ) + set_region_rect( clip, &win->client_rect ); + if (win->win_region && !intersect_window_region( clip, win )) goto error; + +- if ((win->paint_flags & PAINT_HAS_PIXEL_FORMAT) && !subtract_region( region, region, clip )) ++ if (!(win->ex_style & WS_EX_LAYERED) && (win->paint_flags & PAINT_HAS_PIXEL_FORMAT) ++ && !subtract_region( region, region, clip )) + goto error; + + /* clip children */ +-- +2.47.0 + diff --git a/0009-windowing-system-integration/0003-rendering/0856-user32-Flush-driver-display-in-ReleaseDC-for-other-p.patch b/0009-windowing-system-integration/0003-rendering/0856-user32-Flush-driver-display-in-ReleaseDC-for-other-p.patch new file mode 100644 index 0000000..d3cd1c4 --- /dev/null +++ b/0009-windowing-system-integration/0003-rendering/0856-user32-Flush-driver-display-in-ReleaseDC-for-other-p.patch @@ -0,0 +1,28 @@ +From c6fc9aac47ffdc5644f9aace4ad365e66bb1fbce Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Tue, 24 May 2022 16:27:08 -0500 +Subject: [PATCH 0856/2346] user32: Flush driver display in ReleaseDC() for + other process window. + +CW-Bug-Id: #19779 +--- + dlls/win32u/dce.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c +index 649b82cdb6b..d7aa75b3039 100644 +--- a/dlls/win32u/dce.c ++++ b/dlls/win32u/dce.c +@@ -1020,6 +1020,9 @@ HDC WINAPI NtUserGetDCEx( HWND hwnd, HRGN clip_rgn, DWORD flags ) + */ + INT WINAPI NtUserReleaseDC( HWND hwnd, HDC hdc ) + { ++ if (hwnd && !is_current_process_window( hwnd )) ++ user_driver->pProcessEvents( 0 ); ++ + return release_dc( hwnd, hdc, FALSE ); + } + +-- +2.47.0 + diff --git a/0009-windowing-system-integration/0004-proton/0040-winex11-Always-ignore-MotionNotify-event-after-SetCu.patch b/0009-windowing-system-integration/0004-proton/0040-winex11-Always-ignore-MotionNotify-event-after-SetCu.patch deleted file mode 100644 index 36d9c4d..0000000 --- a/0009-windowing-system-integration/0004-proton/0040-winex11-Always-ignore-MotionNotify-event-after-SetCu.patch +++ /dev/null @@ -1,38 +0,0 @@ -From f4939225cf18a90bc73da2c13af3d6f498c4bb6e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Fri, 8 Sep 2023 14:24:11 +0200 -Subject: [PATCH 0317/1562] winex11: Always ignore MotionNotify event after - SetCursorPos. - -Trying to workaround spurious Wayland mouse motion. - -CW-Bug-Id: #22650 ---- - dlls/winex11.drv/mouse.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c -index c052bdd692c..b8bd05f76db 100644 ---- a/dlls/winex11.drv/mouse.c -+++ b/dlls/winex11.drv/mouse.c -@@ -1667,7 +1667,7 @@ BOOL X11DRV_MotionNotify( HWND hwnd, XEvent *xev ) - input.mi.time = x11drv_time_to_ticks( event->time ); - input.mi.dwExtraInfo = 0; - -- if (!hwnd && is_old_motion_event( event->serial )) -+ if (is_old_motion_event( event->serial )) - { - TRACE( "pos %d,%d old serial %lu, ignoring\n", event->x, event->y, event->serial ); - return FALSE; -#@@ -1929,7 +1929,7 @@ static BOOL X11DRV_XIDeviceEvent( XIDeviceEvent *event ) -# TRACE( "evtype %u hwnd %p/%lx pos %f,%f detail %u flags %#x serial %lu\n", -# event->evtype, hwnd, event->event, event->event_x, event->event_y, event->detail, event->flags, event->serial ); -# -#- if (!hwnd && is_old_motion_event( event->serial )) -#+ if (is_old_motion_event( event->serial )) -# { -# TRACE( "pos %f,%f old serial %lu, ignoring\n", event->event_x, event->event_y, event->serial ); -# return FALSE; --- -2.45.2 - diff --git a/0009-windowing-system-integration/0004-proton/0042-HACK-winex11-Drop-X11DRV_GetCursorPos-entirely.patch b/0009-windowing-system-integration/0004-proton/0042-HACK-winex11-Drop-X11DRV_GetCursorPos-entirely.patch deleted file mode 100644 index 7bac190..0000000 --- a/0009-windowing-system-integration/0004-proton/0042-HACK-winex11-Drop-X11DRV_GetCursorPos-entirely.patch +++ /dev/null @@ -1,71 +0,0 @@ -From dd5cb640c2c4f3729da6eb317af76a28f0c1bf0d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Wed, 29 Nov 2023 14:52:21 +0100 -Subject: [PATCH 0318/1562] HACK: winex11: Drop X11DRV_GetCursorPos entirely. - -CW-Bug-Id: #22849 ---- - dlls/winex11.drv/init.c | 1 - - dlls/winex11.drv/mouse.c | 25 ------------------------- - dlls/winex11.drv/x11drv.h | 1 - - 3 files changed, 27 deletions(-) - -diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c -index b85246ee19d..5576fdd50e6 100644 ---- a/dlls/winex11.drv/init.c -+++ b/dlls/winex11.drv/init.c -@@ -403,7 +403,6 @@ static const struct user_driver_funcs x11drv_funcs = - .pNotifyIMEStatus = X11DRV_NotifyIMEStatus, - .pDestroyCursorIcon = X11DRV_DestroyCursorIcon, - .pSetCursor = X11DRV_SetCursor, -- .pGetCursorPos = X11DRV_GetCursorPos, - .pSetCursorPos = X11DRV_SetCursorPos, - .pClipCursor = X11DRV_ClipCursor, - .pSystrayDockInit = X11DRV_SystrayDockInit, -diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c -index b8bd05f76db..53e8080339b 100644 ---- a/dlls/winex11.drv/mouse.c -+++ b/dlls/winex11.drv/mouse.c -@@ -1508,27 +1508,6 @@ BOOL X11DRV_SetCursorPos( INT x, INT y ) - return TRUE; - } - --/*********************************************************************** -- * GetCursorPos (X11DRV.@) -- */ --BOOL X11DRV_GetCursorPos(LPPOINT pos) --{ -- Display *display = thread_init_display(); -- Window root, child; -- int rootX, rootY, winX, winY; -- unsigned int xstate; -- BOOL ret; -- -- ret = XQueryPointer( display, root_window, &root, &child, &rootX, &rootY, &winX, &winY, &xstate ); -- if (ret) -- { -- POINT old = *pos; -- *pos = root_to_virtual_screen( winX, winY ); -- TRACE( "pointer at %s server pos %s\n", wine_dbgstr_point(pos), wine_dbgstr_point(&old) ); -- } -- return ret; --} -- - /*********************************************************************** - * ClipCursor (X11DRV.@) - */ -diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h -index 620eadee8ae..c9ebb4ce7dd 100644 ---- a/dlls/winex11.drv/x11drv.h -+++ b/dlls/winex11.drv/x11drv.h -@@ -217,7 +217,6 @@ extern void X11DRV_NotifyIMEStatus( HWND hwnd, UINT status ); - extern void X11DRV_DestroyCursorIcon( HCURSOR handle ); - extern void X11DRV_SetCursor( HWND hwnd, HCURSOR handle ); - extern BOOL X11DRV_SetCursorPos( INT x, INT y ); --extern BOOL X11DRV_GetCursorPos( LPPOINT pos ); - extern BOOL X11DRV_ClipCursor( const RECT *clip, BOOL reset ); - extern void X11DRV_SystrayDockInit( HWND systray ); - extern BOOL X11DRV_SystrayDockInsert( HWND owner, UINT cx, UINT cy, void *icon ); --- -2.45.2 - diff --git a/0012-audio/0001-winepulse-Rely-on-PulseAudio-write-callbacks-instead.patch b/0012-audio/0001-winepulse-Rely-on-PulseAudio-write-callbacks-instead.patch index 733b3c9..97172b0 100644 --- a/0012-audio/0001-winepulse-Rely-on-PulseAudio-write-callbacks-instead.patch +++ b/0012-audio/0001-winepulse-Rely-on-PulseAudio-write-callbacks-instead.patch @@ -508,6 +508,16 @@ index 615c3a8fdc8..9c7509e1089 100644 - pa_usec_t last_time; - UINT32 adv_bytes; - int success; +- +- pulse_lock(); +- delay.QuadPart = -stream->mmdev_period_usec * 10; +- pa_stream_get_time(stream->stream, &last_time); +- pulse_unlock(); +- +- while (!stream->please_quit) +- { +- pa_usec_t now, adv_usec = 0; +- int err; + while (bytes >= stream->capture_period) { + size_t src_len, copy, rem = stream->capture_period; + while (rem) { @@ -518,25 +528,15 @@ index 615c3a8fdc8..9c7509e1089 100644 + src_len -= stream->peek_ofs; + assert(src_len <= bytes); -- pulse_lock(); -- delay.QuadPart = -stream->mmdev_period_usec * 10; -- pa_stream_get_time(stream->stream, &last_time); -- pulse_unlock(); +- NtDelayExecution(FALSE, &delay); + copy = rem; + if (copy > src_len) + copy = src_len; -- while (!stream->please_quit) -- { -- pa_usec_t now, adv_usec = 0; -- int err; +- pulse_lock(); + src_len -= copy; + rem -= copy; -- NtDelayExecution(FALSE, &delay); -- -- pulse_lock(); -- - delay.QuadPart = -stream->mmdev_period_usec * 10; - - wait_pa_operation_complete(pa_stream_update_timing_info(stream->stream, pulse_op_cb, &success)); @@ -882,12 +882,13 @@ index 615c3a8fdc8..9c7509e1089 100644 + else + { + enum write_buffer_flags wr_flags = 0; -+ -+ if (params->flags & AUDCLNT_BUFFERFLAGS_SILENT) wr_flags |= WINEPULSE_WRITE_SILENT; -+ if (!stream->locked_ptr) wr_flags |= WINEPULSE_WRITE_NOFREE; - /* push as much data as we can to pulseaudio too */ - pulse_write(stream); ++ if (params->flags & AUDCLNT_BUFFERFLAGS_SILENT) wr_flags |= WINEPULSE_WRITE_SILENT; ++ if (!stream->locked_ptr) wr_flags |= WINEPULSE_WRITE_NOFREE; + +- TRACE("Released %u, held %lu\n", params->written_frames, stream->held_bytes / pa_frame_size(&stream->ss)); + write_buffer(stream, stream->locked_ptr ? stream->locked_ptr : stream->tmp_buffer, written_bytes, wr_flags); + stream->pad += written_bytes; + } @@ -895,8 +896,7 @@ index 615c3a8fdc8..9c7509e1089 100644 + int success; + wait_pa_operation_complete(pa_stream_trigger(stream->stream, pulse_op_cb, &success)); + } - -- TRACE("Released %u, held %lu\n", params->written_frames, stream->held_bytes / pa_frame_size(&stream->ss)); ++ + stream->locked = 0; + stream->locked_ptr = NULL; + TRACE("Released %u, pad %zu\n", params->written_frames, stream->pad / pa_frame_size(&stream->ss)); @@ -971,48 +971,23 @@ index 615c3a8fdc8..9c7509e1089 100644 if (stream->share == AUDCLNT_SHAREMODE_EXCLUSIVE || params->device) *params->pos /= pa_frame_size(&stream->ss); -@@ -2510,11 +2530,15 @@ static NTSTATUS pulse_set_sample_rate(void *args) - - new_ss = stream->ss; - new_ss.rate = params->rate; -- new_bufsize_frames = ceil((stream->duration / 10000000.) * new_ss.rate); -- size = new_bufsize_frames * 2 * pa_frame_size(&stream->ss); - -- if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&new_buffer, -- zero_bits, &size, MEM_COMMIT, PAGE_READWRITE)) { -+ if (stream->duration < 20000000) -+ new_bufsize_frames = ceil((stream->duration / 10000000.) * new_ss.rate); -+ else -+ new_bufsize_frames = 2 * new_ss.rate; -+ size = stream->bufsize_bytes = new_bufsize_frames * pa_frame_size(&stream->ss); -+ -+ if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&new_buffer, zero_bits, &size, MEM_COMMIT, PAGE_READWRITE)) -+ { - hr = E_OUTOFMEMORY; - goto exit; - } -@@ -2533,17 +2557,15 @@ static NTSTATUS pulse_set_sample_rate(void *args) +@@ -2521,12 +2541,11 @@ static NTSTATUS pulse_set_sample_rate(void *args) wait_pa_operation_complete(pa_stream_flush(stream->stream, pulse_op_cb, &success)); stream->clock_lastpos = stream->clock_written = 0; - stream->pa_offs_bytes = stream->lcl_offs_bytes = 0; - stream->held_bytes = stream->pa_held_bytes = 0; - stream->period_bytes = pa_frame_size(&new_ss) * muldiv(stream->mmdev_period_usec, new_ss.rate, 1000000); -- stream->real_bufsize_bytes = size; + stream->wri_offs_bytes = stream->lcl_offs_bytes = stream->held_bytes = 0; + stream->period_bytes = pa_frame_size(&new_ss) * muldiv(stream->def_period / 10, new_ss.rate, 1000000); - stream->bufsize_frames = new_bufsize_frames; stream->ss = new_ss; - size = 0; - NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer, &size, MEM_RELEASE); - -- silence_buffer(new_ss.format, new_buffer, stream->real_bufsize_bytes); -+ silence_buffer(new_ss.format, new_buffer, stream->bufsize_bytes); - stream->local_buffer = new_buffer; +- silence_buffer(new_ss.format, stream->local_buffer, stream->real_bufsize_bytes); ++ silence_buffer(new_ss.format, stream->local_buffer, stream->bufsize_bytes); exit: -@@ -2661,7 +2683,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = + pulse_unlock(); +@@ -2643,7 +2662,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = pulse_start, pulse_stop, pulse_reset, @@ -1021,7 +996,7 @@ index 615c3a8fdc8..9c7509e1089 100644 pulse_get_render_buffer, pulse_release_render_buffer, pulse_get_capture_buffer, -@@ -3159,7 +3181,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = +@@ -3141,7 +3160,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = pulse_start, pulse_stop, pulse_reset, diff --git a/0012-audio/0004-winepulse-Try-memlocking-the-audio-buffer.patch b/0012-audio/0004-winepulse-Try-memlocking-the-audio-buffer.patch index 3162e71..a4837b1 100644 --- a/0012-audio/0004-winepulse-Try-memlocking-the-audio-buffer.patch +++ b/0012-audio/0004-winepulse-Try-memlocking-the-audio-buffer.patch @@ -65,15 +65,6 @@ index e697eb2459f..74de31d91a7 100644 return TRUE; } -@@ -2571,6 +2589,8 @@ static NTSTATUS pulse_set_sample_rate(void *args) - silence_buffer(new_ss.format, new_buffer, size); - stream->local_buffer = new_buffer; - -+ try_memlock(stream, size); -+ - exit: - pulse_unlock(); - -- 2.46.0 diff --git a/0012-audio/0005-winepulse-Specify-the-buffer-to-try-memlocking.patch b/0012-audio/0005-winepulse-Specify-the-buffer-to-try-memlocking.patch index 2d4f4f1..c9bba88 100644 --- a/0012-audio/0005-winepulse-Specify-the-buffer-to-try-memlocking.patch +++ b/0012-audio/0005-winepulse-Specify-the-buffer-to-try-memlocking.patch @@ -56,15 +56,6 @@ index de4e272ffc8..9bf4044a122 100644 return TRUE; } -@@ -2610,7 +2623,7 @@ static NTSTATUS pulse_set_sample_rate(void *args) - silence_buffer(new_ss.format, new_buffer, size); - stream->local_buffer = new_buffer; - -- try_memlock(stream, size); -+ try_memlock(stream, size, BUFTYPE_LOCAL); - - exit: - pulse_unlock(); -- 2.46.2 diff --git a/0013-server-optimization/0001-misc/0001-Revert-ntdll-Manually-write-byte-code-for-the-xsavec.patch b/0013-server-optimization/0001-misc/0001-Revert-ntdll-Manually-write-byte-code-for-the-xsavec.patch new file mode 100644 index 0000000..cc42012 --- /dev/null +++ b/0013-server-optimization/0001-misc/0001-Revert-ntdll-Manually-write-byte-code-for-the-xsavec.patch @@ -0,0 +1,44 @@ +From: William Horvath +Date: Tue, 3 Dec 2024 21:56:01 -0800 +Subject: [PATCH] Revert "ntdll: Manually write byte code for the xsavec + instruction." + +This reverts commit 5250493177f3dcb1ab455e018c1c3046198db746. +--- + dlls/ntdll/unix/signal_i386.c | 4 +--- + dlls/ntdll/unix/signal_x86_64.c | 4 +--- + 2 files changed, 2 insertions(+), 6 deletions(-) + +diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c +index 11111111111..11111111111 100644 +--- a/dlls/ntdll/unix/signal_i386.c ++++ b/dlls/ntdll/unix/signal_i386.c +@@ -2659,9 +2659,7 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, + "movl %edi,0x274(%ecx)\n\t" + "movl %edi,0x278(%ecx)\n\t" + "movl %edi,0x27c(%ecx)\n\t" +- /* The xsavec instruction is not supported by +- * binutils < 2.25. */ +- ".byte 0x0f, 0xc7, 0x61, 0x40\n\t" /* xsavec 0x40(%ecx) */ ++ "xsavec 0x40(%ecx)\n\t" + "jmp 4f\n" + "1:\txsave 0x40(%ecx)\n\t" + "jmp 4f\n" +diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c +index 11111111111..11111111111 100644 +--- a/dlls/ntdll/unix/signal_x86_64.c ++++ b/dlls/ntdll/unix/signal_x86_64.c +@@ -2967,9 +2967,7 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, + "movq %rbp,0x2e8(%rcx)\n\t" + "movq %rbp,0x2f0(%rcx)\n\t" + "movq %rbp,0x2f8(%rcx)\n\t" +- /* The xsavec instruction is not supported by +- * binutils < 2.25. */ +- ".byte 0x48, 0x0f, 0xc7, 0xa1, 0xc0, 0x00, 0x00, 0x00\n\t" /* xsavec64 0xc0(%rcx) */ ++ "xsavec64 0xc0(%rcx)\n\t" + "jmp 3f\n" + "1:\txsave64 0xc0(%rcx)\n\t" + "jmp 3f\n" +-- +0.0.0 + diff --git a/0013-server-optimization/0001-misc/0296-HACK-user32-Remove-hooks-that-time-out.patch b/0013-server-optimization/0001-misc/0296-HACK-user32-Remove-hooks-that-time-out.patch new file mode 100644 index 0000000..5d56099 --- /dev/null +++ b/0013-server-optimization/0001-misc/0296-HACK-user32-Remove-hooks-that-time-out.patch @@ -0,0 +1,58 @@ +From c2b7453b05b74b012c2417f6953846680a6bd3fb Mon Sep 17 00:00:00 2001 +From: Zebediah Figura +Date: Wed, 20 Jun 2018 15:07:28 -0500 +Subject: [PATCH 0296/2346] HACK: user32: Remove hooks that time out. + +In accordance with Win7+ behaviour. +--- + dlls/win32u/hook.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/dlls/win32u/hook.c b/dlls/win32u/hook.c +index 378eda40abb..7cdd327a9f5 100644 +--- a/dlls/win32u/hook.c ++++ b/dlls/win32u/hook.c +@@ -204,6 +204,7 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, siz + size_t message_size, BOOL ansi ) + { + DWORD_PTR ret = 0; ++ LRESULT lres = 0; + + if (info->tid) + { +@@ -218,20 +219,26 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, siz + switch(info->id) + { + case WH_KEYBOARD_LL: +- send_internal_message_timeout( info->pid, info->tid, WM_WINE_KEYBOARD_LL_HOOK, +- info->wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG, +- get_ll_hook_timeout(), &ret ); ++ lres = send_internal_message_timeout( info->pid, info->tid, WM_WINE_KEYBOARD_LL_HOOK, ++ info->wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG, ++ get_ll_hook_timeout(), &ret ); + break; + case WH_MOUSE_LL: +- send_internal_message_timeout( info->pid, info->tid, WM_WINE_MOUSE_LL_HOOK, +- info->wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG, +- get_ll_hook_timeout(), &ret ); ++ lres = send_internal_message_timeout( info->pid, info->tid, WM_WINE_MOUSE_LL_HOOK, ++ info->wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG, ++ get_ll_hook_timeout(), &ret ); + break; + default: + ERR("Unknown hook id %d\n", info->id); + assert(0); + break; + } ++ ++ if (!lres && RtlGetLastWin32Error() == ERROR_TIMEOUT) ++ { ++ TRACE( "Hook %p timed out; removing it.\n", info->handle ); ++ NtUserUnhookWindowsHookEx( info->handle ); ++ } + } + else if (info->proc) + { +-- +2.47.0 + diff --git a/0013-server-optimization/0001-misc/0698-server-Improve-STATUS_CANNOT_DELETE-checks-for-direc.patch b/0013-server-optimization/0001-misc/0698-server-Improve-STATUS_CANNOT_DELETE-checks-for-direc.patch deleted file mode 100644 index 67549f5..0000000 --- a/0013-server-optimization/0001-misc/0698-server-Improve-STATUS_CANNOT_DELETE-checks-for-direc.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 717894cbb4d2fe3902fafc3200c8a4fa2e09c443 Mon Sep 17 00:00:00 2001 -From: Sebastian Lackner -Date: Sun, 16 Oct 2016 03:21:42 +0200 -Subject: [PATCH 0698/1562] server: Improve STATUS_CANNOT_DELETE checks for - directory case. - -Wine-Staging: server-File_Permissions ---- - server/fd.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/server/fd.c b/server/fd.c -index d18ed4fc8e4..6cf8fb3ad06 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -1914,6 +1914,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam - int root_fd = -1; - int rw_mode; - char *path; -+ int created = (flags & O_CREAT); - - if (((options & FILE_DELETE_ON_CLOSE) && !(access & DELETE)) || - ((options & FILE_DIRECTORY_FILE) && (flags & O_TRUNC))) -@@ -1952,6 +1953,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam - file_set_error(); - goto error; - } -+ created = 0; - } - flags &= ~(O_CREAT | O_EXCL | O_TRUNC); - } -@@ -2034,7 +2036,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam - } - - /* can't unlink files if we don't have permission to access */ -- if ((options & FILE_DELETE_ON_CLOSE) && !(flags & O_CREAT) && -+ if ((options & FILE_DELETE_ON_CLOSE) && !created && - !(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH))) - { - set_error( STATUS_CANNOT_DELETE ); --- -2.45.2 - diff --git a/0013-server-optimization/0001-misc/0699-server-Allow-to-open-files-without-any-permission-bi.patch b/0013-server-optimization/0001-misc/0699-server-Allow-to-open-files-without-any-permission-bi.patch deleted file mode 100644 index 661c4a1..0000000 --- a/0013-server-optimization/0001-misc/0699-server-Allow-to-open-files-without-any-permission-bi.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 2da7fe668973eeeb828ad59ab68189cf410e7460 Mon Sep 17 00:00:00 2001 -From: Sebastian Lackner -Date: Fri, 3 Apr 2015 03:58:47 +0200 -Subject: [PATCH 0699/1562] server: Allow to open files without any permission - bits. (try 2) - -Changes in v2: -* As suggested by Piotr, fix the problem for both files and directories. -* Pay attention to requested access attributes - this fixes a couple more todo_wine's. - -Wine-Staging: server-File_Permissions ---- - dlls/advapi32/tests/security.c | 32 ++++++++++++-------------------- - server/fd.c | 21 +++++++++++++++++++++ - 2 files changed, 33 insertions(+), 20 deletions(-) - -# diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c -# index 2840f6bd75a..9569272e0db 100644 -# --- a/dlls/advapi32/tests/security.c -# +++ b/dlls/advapi32/tests/security.c -# @@ -3782,17 +3782,13 @@ static void test_CreateDirectoryA(void) -# error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, -# OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, -# (PSID *)&owner, NULL, &pDacl, NULL, &pSD); -# - todo_wine -# ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %ld\n", error); -# - if (error == ERROR_SUCCESS) -# - { -# - bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); -# - ok(bret, "GetAclInformation failed\n"); -# - todo_wine -# - ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%ld != 0).\n", -# - acl_size.AceCount); -# - LocalFree(pSD); -# - } -# + bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); -# + ok(bret, "GetAclInformation failed\n"); -# + todo_wine -# + ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%ld != 0).\n", -# + acl_size.AceCount); -# + LocalFree(pSD); -# CloseHandle(hTemp); - -# /* Test inheritance of ACLs in NtCreateFile without security descriptor */ -# @@ -3861,17 +3857,13 @@ static void test_CreateDirectoryA(void) -# error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, -# OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, -# (PSID *)&owner, NULL, &pDacl, NULL, &pSD); -# - todo_wine -# ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %ld\n", error); -# - if (error == ERROR_SUCCESS) -# - { -# - bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); -# - ok(bret, "GetAclInformation failed\n"); -# - todo_wine -# - ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%ld != 0).\n", -# - acl_size.AceCount); -# - LocalFree(pSD); -# - } -# + bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); -# + ok(bret, "GetAclInformation failed\n"); -# + todo_wine -# + ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%ld != 0).\n", -# + acl_size.AceCount); -# + LocalFree(pSD); -# CloseHandle(hTemp); - -# done: -diff --git a/server/fd.c b/server/fd.c -index 6cf8fb3ad06..d789895628b 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -1914,6 +1914,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam - int root_fd = -1; - int rw_mode; - char *path; -+ int do_chmod = 0; - int created = (flags & O_CREAT); - - if (((options & FILE_DELETE_ON_CLOSE) && !(access & DELETE)) || -@@ -1973,6 +1974,23 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam - if ((access & FILE_UNIX_WRITE_ACCESS) || (flags & O_CREAT)) - fd->unix_fd = open( name, O_RDONLY | (flags & ~(O_TRUNC | O_CREAT | O_EXCL)), *mode ); - } -+ else if (errno == EACCES) -+ { -+ /* try to change permissions temporarily to open a file descriptor */ -+ if (!(access & (FILE_UNIX_WRITE_ACCESS | FILE_UNIX_READ_ACCESS | DELETE)) && -+ !stat( name, &st ) && st.st_uid == getuid() && -+ !chmod( name, st.st_mode | S_IRUSR )) -+ { -+ fd->unix_fd = open( name, O_RDONLY | (flags & ~(O_TRUNC | O_CREAT | O_EXCL)), *mode ); -+ *mode = st.st_mode; -+ do_chmod = 1; -+ } -+ else -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ goto error; -+ } -+ } - - if (fd->unix_fd == -1) - { -@@ -1981,6 +1999,8 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam - set_error( STATUS_OBJECT_NAME_INVALID ); - else - file_set_error(); -+ -+ if (do_chmod) chmod( name, *mode ); - goto error; - } - } -@@ -1996,6 +2016,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam - closed_fd->unix_fd = fd->unix_fd; - closed_fd->disp_flags = 0; - closed_fd->unix_name = fd->unix_name; -+ if (do_chmod) chmod( name, *mode ); - fstat( fd->unix_fd, &st ); - *mode = st.st_mode; - --- -2.45.2 - diff --git a/0013-server-optimization/0001-misc/0700-server-When-creating-new-directories-temporarily-giv.patch b/0013-server-optimization/0001-misc/0700-server-When-creating-new-directories-temporarily-giv.patch deleted file mode 100644 index 007df32..0000000 --- a/0013-server-optimization/0001-misc/0700-server-When-creating-new-directories-temporarily-giv.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 29b2b9931b5359026bb367e8dbc4090f8046feaf Mon Sep 17 00:00:00 2001 -From: Sebastian Lackner -Date: Fri, 3 Apr 2015 03:58:53 +0200 -Subject: [PATCH 0700/1562] server: When creating new directories temporarily - give read-permissions until they are opened. - -Wine-Staging: server-File_Permissions ---- - server/fd.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/server/fd.c b/server/fd.c -index d789895628b..07f44b94cff 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -1947,7 +1947,12 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam - /* create the directory if needed */ - if ((options & FILE_DIRECTORY_FILE) && (flags & O_CREAT)) - { -- if (mkdir( name, *mode ) == -1) -+ if (mkdir( name, *mode | S_IRUSR ) != -1) -+ { -+ /* remove S_IRUSR later, after we have opened the directory */ -+ do_chmod = !(*mode & S_IRUSR); -+ } -+ else - { - if (errno != EEXIST || (flags & O_EXCL)) - { --- -2.45.2 - diff --git a/0013-server-optimization/0001-misc/0704-server-FILE_WRITE_ATTRIBUTES-should-succeed-for-read.patch b/0013-server-optimization/0001-misc/0704-server-FILE_WRITE_ATTRIBUTES-should-succeed-for-read.patch deleted file mode 100644 index 2e7c870..0000000 --- a/0013-server-optimization/0001-misc/0704-server-FILE_WRITE_ATTRIBUTES-should-succeed-for-read.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 072c122e04e6c70251253256e37d9c4ed6540942 Mon Sep 17 00:00:00 2001 -From: Sebastian Lackner -Date: Wed, 3 Jun 2015 05:43:31 +0200 -Subject: [PATCH 0704/1562] server: FILE_WRITE_ATTRIBUTES should succeed for - readonly files. - -Wine-Staging: server-File_Permissions ---- - dlls/ntdll/tests/file.c | 2 +- - server/fd.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -# diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -# index 04beeca4c2d..4b0d8f9fd37 100644 -# --- a/dlls/ntdll/tests/file.c -# +++ b/dlls/ntdll/tests/file.c -# @@ -4779,7 +4779,7 @@ static void test_readonly(void) - -# status = pNtOpenFile(&handle, FILE_WRITE_ATTRIBUTES, &attr, &io, -# FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT); -# - todo_wine ok(status == STATUS_SUCCESS, "got %#x\n", status); -# + ok(status == STATUS_SUCCESS, "got %#x\n", status); -# CloseHandle(handle); - -# status = pNtOpenFile(&handle, DELETE, &attr, &io, -diff --git a/server/fd.c b/server/fd.c -index 07f44b94cff..d1ac7506a5f 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -1982,7 +1982,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam - else if (errno == EACCES) - { - /* try to change permissions temporarily to open a file descriptor */ -- if (!(access & (FILE_UNIX_WRITE_ACCESS | FILE_UNIX_READ_ACCESS | DELETE)) && -+ if (!(access & ((FILE_UNIX_WRITE_ACCESS | FILE_UNIX_READ_ACCESS | DELETE) & ~FILE_WRITE_ATTRIBUTES)) && - !stat( name, &st ) && st.st_uid == getuid() && - !chmod( name, st.st_mode | S_IRUSR )) - { --- -2.45.2 - diff --git a/0013-server-optimization/0001-misc/0705-ntdll-Handle-NULL-object-name-buffer-in-nt_to_unix_f.patch b/0013-server-optimization/0001-misc/0705-ntdll-Handle-NULL-object-name-buffer-in-nt_to_unix_f.patch deleted file mode 100644 index 9a982b9..0000000 --- a/0013-server-optimization/0001-misc/0705-ntdll-Handle-NULL-object-name-buffer-in-nt_to_unix_f.patch +++ /dev/null @@ -1,80 +0,0 @@ -From ae659100f551f1e0d8b02781d51b3a4266595fec Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Mon, 13 Jul 2020 10:21:49 -0500 -Subject: [PATCH 0705/1562] ntdll: Handle NULL object name buffer in - nt_to_unix_file_name_attr(). - -CW-Bug-Id: #17864 ---- - dlls/ntdll/tests/file.c | 22 +++++++++++++++++++++- - dlls/ntdll/unix/file.c | 5 ++++- - 2 files changed, 25 insertions(+), 2 deletions(-) - -# diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -# index 4b0d8f9fd37..78087114d06 100644 -# --- a/dlls/ntdll/tests/file.c -# +++ b/dlls/ntdll/tests/file.c -# @@ -145,16 +145,36 @@ static void create_file_test(void) -# static const WCHAR pathInvalidDosW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0}; -# static const char testdata[] = "Hello World"; -# FILE_NETWORK_OPEN_INFORMATION info; -# + UNICODE_STRING nameW, null_string; -# NTSTATUS status; -# HANDLE dir, file; -# WCHAR path[MAX_PATH]; -# OBJECT_ATTRIBUTES attr; -# IO_STATUS_BLOCK io; -# - UNICODE_STRING nameW; -# LARGE_INTEGER offset; -# char buf[32]; -# DWORD ret; - -# + attr.Length = sizeof(attr); -# + attr.RootDirectory = NULL; -# + attr.ObjectName = &null_string; -# + attr.Attributes = 0; -# + attr.SecurityDescriptor = NULL; -# + attr.SecurityQualityOfService = NULL; -# + -# + null_string.Buffer = NULL; -# + null_string.Length = 256; -# + -# + /* try various open modes and options on directories */ -# + status = pNtCreateFile( &dir, GENERIC_READ|GENERIC_WRITE, &attr, &io, NULL, 0, -# + FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 ); -# + ok( status == STATUS_ACCESS_VIOLATION, "Got unexpected status %#x.\n", status ); -# + -# + null_string.Length = 0; -# + status = pNtCreateFile( &dir, GENERIC_READ|GENERIC_WRITE, &attr, &io, NULL, 0, -# + FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 ); -# + ok( status == STATUS_OBJECT_PATH_SYNTAX_BAD, "Got unexpected status %#x.\n", status ); -# + -# GetCurrentDirectoryW( MAX_PATH, path ); -# pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL ); -# attr.Length = sizeof(attr); -diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index ddea0e994cc..367cc6763cd 100644 ---- a/dlls/ntdll/unix/file.c -+++ b/dlls/ntdll/unix/file.c -@@ -3499,7 +3499,7 @@ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char - name = nameW->Buffer; - name_len = nameW->Length / sizeof(WCHAR); - -- if (!name_len || name[0] != '\\') return STATUS_OBJECT_PATH_SYNTAX_BAD; -+ if (!name || !name_len || name[0] != '\\') return STATUS_OBJECT_PATH_SYNTAX_BAD; - - if (!(pos = get_dos_prefix_len( nameW ))) - return STATUS_BAD_DEVICE_TYPE; /* no DOS prefix, assume NT native name */ -@@ -3610,6 +3610,9 @@ NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, U - int name_len, unix_len; - NTSTATUS status; - -+ if (!attr->ObjectName->Buffer && attr->ObjectName->Length) -+ return STATUS_ACCESS_VIOLATION; -+ - fileobj.FileName = *attr->ObjectName; - reparse: - if (reparse_count++ == 31) --- -2.45.2 - diff --git a/0013-server-optimization/0001-misc/0706-Avoid-undefined-result-in-ntdll_wcstoumbs-in-case-of.patch b/0013-server-optimization/0001-misc/0706-Avoid-undefined-result-in-ntdll_wcstoumbs-in-case-of.patch deleted file mode 100644 index 7fa40f8..0000000 --- a/0013-server-optimization/0001-misc/0706-Avoid-undefined-result-in-ntdll_wcstoumbs-in-case-of.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 83e30e835c2099d9b9ab2e4e704ad64efd2f6cb7 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Fri, 26 Jun 2020 15:26:53 +0300 -Subject: [PATCH 0706/1562] Avoid undefined result in ntdll_wcstoumbs() in case - of error. - -CW-Bug-Id: #17864 - -Undefined result is due to RtlUnicodeToUTF8N() not setting output -length on error which is a correct behaviour according to -existing tests. - -'Planet Zoo' is affected which passes NULL object name buffer to -NtCreateFile(). - -Signed-off-by: Paul Gofman ---- - dlls/ntdll/unix/env.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c -index 9b7c4ea2cd9..ff3f28d93e1 100644 ---- a/dlls/ntdll/unix/env.c -+++ b/dlls/ntdll/unix/env.c -@@ -399,7 +399,7 @@ DWORD ntdll_umbstowcs( const char *src, DWORD srclen, WCHAR *dst, DWORD dstlen ) - */ - int ntdll_wcstoumbs( const WCHAR *src, DWORD srclen, char *dst, DWORD dstlen, BOOL strict ) - { -- unsigned int i, reslen; -+ unsigned int i, reslen = 0; - - if (unix_cp.CodePage != CP_UTF8) - { --- -2.45.2 - diff --git a/0013-server-optimization/0001-misc/0707-server-Update-system-regs-from-set_thread_context-ha.patch b/0013-server-optimization/0001-misc/0707-server-Update-system-regs-from-set_thread_context-ha.patch deleted file mode 100644 index e44a5e1..0000000 --- a/0013-server-optimization/0001-misc/0707-server-Update-system-regs-from-set_thread_context-ha.patch +++ /dev/null @@ -1,37 +0,0 @@ -From da536399f4b3815fde57dbca72cfc23ba5d1a9d3 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Sat, 22 May 2021 01:23:33 +0300 -Subject: [PATCH 0707/1562] server: Update system regs from set_thread_context - handler only. - -CW-Bug-Id: #18957 ---- - server/thread.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/server/thread.c b/server/thread.c -index 6745b257a7a..8e0d9816996 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -1923,9 +1923,7 @@ DECL_HANDLER(select) - { - union apc_call *data; - data_size_t size = sizeof(*data) + (ctx->regs[CTX_WOW].flags ? 2 : 1) * sizeof(struct context_data); -- unsigned int flags = system_flags & ctx->regs[CTX_NATIVE].flags; - -- if (flags) set_thread_context( current, &ctx->regs[CTX_NATIVE], flags ); - size = min( size, get_reply_max_size() ); - if ((data = set_reply_data_size( size ))) - { -@@ -2171,7 +2169,7 @@ DECL_HANDLER(set_thread_context) - unsigned int flags = system_flags & contexts[CTX_NATIVE].flags; - - if (thread != current) stop_thread( thread ); -- else if (flags) set_thread_context( thread, &contexts[CTX_NATIVE], flags ); -+ if (flags) set_thread_context( thread, &contexts[CTX_NATIVE], flags ); - - if (thread->context && !get_error()) - { --- -2.45.2 - diff --git a/0013-server-optimization/0001-misc/0718-kernel32-Align-stack-pointer-for-lstrcpyA-on-x64.patch b/0013-server-optimization/0001-misc/0718-kernel32-Align-stack-pointer-for-lstrcpyA-on-x64.patch deleted file mode 100644 index 0729e0f..0000000 --- a/0013-server-optimization/0001-misc/0718-kernel32-Align-stack-pointer-for-lstrcpyA-on-x64.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 26b0f8c2bbbc4e6c84deaf92e442d82c22644856 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Mon, 26 Jul 2021 17:36:04 +0300 -Subject: [PATCH 0718/1562] kernel32: Align stack pointer for lstrcpyA() on - x64. - -For Blood of Steel crash on launch. - -CW-Bug-Id: #19148 ---- - dlls/kernel32/virtual.c | 40 +++++++++++++++++++++++++++++++++++++++- - 1 file changed, 39 insertions(+), 1 deletion(-) - -diff --git a/dlls/kernel32/virtual.c b/dlls/kernel32/virtual.c -index 0314b362e86..c4b4fc225a4 100644 ---- a/dlls/kernel32/virtual.c -+++ b/dlls/kernel32/virtual.c -@@ -35,6 +35,7 @@ - #include "psapi.h" - #include "wine/exception.h" - #include "wine/debug.h" -+#include "wine/asm.h" - - #include "kernel_private.h" - -@@ -293,7 +294,8 @@ LPWSTR WINAPI lstrcatW( LPWSTR dst, LPCWSTR src ) - * lstrcpyA (KERNEL32.@) - * lstrcpy (KERNEL32.@) - */ --LPSTR WINAPI lstrcpyA( LPSTR dst, LPCSTR src ) -+#ifdef __x86_64__ -+LPSTR WINAPI lstrcpyA_impl( LPSTR dst, LPCSTR src ) - { - __TRY - { -@@ -309,6 +311,42 @@ LPSTR WINAPI lstrcpyA( LPSTR dst, LPCSTR src ) - return dst; - } - -+__ASM_GLOBAL_FUNC( lstrcpyA, -+ ".byte 0x48, 0x8d, 0xa4, 0x24, 0x00, 0x00, 0x00, 0x00\n\t" -+ "pushq %rbp\n\t" -+ __ASM_SEH(".seh_pushreg %rbp\n\t") -+ __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t") -+ __ASM_CFI(".cfi_rel_offset %rbp,0\n\t") -+ "movq %rsp,%rbp\n\t" -+ __ASM_SEH(".seh_setframe %rbp,0\n\t") -+ __ASM_CFI(".cfi_def_cfa_register %rbp\n\t") -+ __ASM_SEH(".seh_endprologue\n\t") -+ "subq $0x20,%rsp\n\t" -+ "andq $~15,%rsp\n\t" -+ "call " __ASM_NAME("lstrcpyA_impl") "\n\t" -+ "leaq 0(%rbp),%rsp\n\t" -+ __ASM_CFI(".cfi_def_cfa_register %rsp\n\t") -+ "popq %rbp\n\t" -+ __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t") -+ __ASM_CFI(".cfi_same_value %rbp\n\t") -+ "ret" ) -+#else /* __x86_64__ */ -+LPSTR WINAPI lstrcpyA( LPSTR dst, LPCSTR src ) -+{ -+ __TRY -+ { -+ /* this is how Windows does it */ -+ memmove( dst, src, strlen(src)+1 ); -+ } -+ __EXCEPT( badptr_handler ) -+ { -+ SetLastError( ERROR_INVALID_PARAMETER ); -+ return NULL; -+ } -+ __ENDTRY -+ return dst; -+} -+#endif - - /*********************************************************************** - * lstrcpyW (KERNEL32.@) --- -2.45.2 - diff --git a/0013-server-optimization/0001-misc/0741-msvcrt-HACK-Introduce-asm-wrapper-for-_isatty-on-x64.patch b/0013-server-optimization/0001-misc/0741-msvcrt-HACK-Introduce-asm-wrapper-for-_isatty-on-x64.patch index c8d04b5..fb58dd0 100644 --- a/0013-server-optimization/0001-misc/0741-msvcrt-HACK-Introduce-asm-wrapper-for-_isatty-on-x64.patch +++ b/0013-server-optimization/0001-misc/0741-msvcrt-HACK-Introduce-asm-wrapper-for-_isatty-on-x64.patch @@ -1,7 +1,7 @@ From cf08808609a9010a489309ef0a00a92d4c54a400 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Fri, 1 Apr 2022 17:39:50 +0300 -Subject: [PATCH 0741/2307] msvcrt: HACK: Introduce asm wrapper for _isatty on +Subject: [PATCH 0741/2346] msvcrt: HACK: Introduce asm wrapper for _isatty on x64. CW-Bug-Id: #20419 @@ -51,5 +51,5 @@ index 3c1d9572585..3de12d1087f 100644 /* INTERNAL: Allocate stdio file buffer */ static BOOL msvcrt_alloc_buffer(FILE* file) -- -2.46.2 +2.47.0 diff --git a/0013-server-optimization/0001-misc/0748-ntdll-Do-not-open-directory-file-when-setting-the-sa.patch b/0013-server-optimization/0001-misc/0748-ntdll-Do-not-open-directory-file-when-setting-the-sa.patch deleted file mode 100644 index 10bc323..0000000 --- a/0013-server-optimization/0001-misc/0748-ntdll-Do-not-open-directory-file-when-setting-the-sa.patch +++ /dev/null @@ -1,67 +0,0 @@ -From f5309046b435b6cd2783377b03afa55f2119f553 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Wed, 15 Jun 2022 17:21:55 -0500 -Subject: [PATCH 0748/1793] ntdll: Do not open directory file when setting the - same directory path. - -CW-Bug-Id: #20815 ---- - dlls/ntdll/path.c | 22 +++++++++++++++++----- - 1 file changed, 17 insertions(+), 5 deletions(-) - -diff --git a/dlls/ntdll/path.c b/dlls/ntdll/path.c -index 6aa4bb3fdff..dda6ba4ee53 100644 ---- a/dlls/ntdll/path.c -+++ b/dlls/ntdll/path.c -@@ -914,13 +914,13 @@ ULONG WINAPI RtlGetCurrentDirectory_U(ULONG buflen, LPWSTR buf) - NTSTATUS WINAPI RtlSetCurrentDirectory_U(const UNICODE_STRING* dir) - { - FILE_FS_DEVICE_INFORMATION device_info; -+ ULONG size, compare_size; - OBJECT_ATTRIBUTES attr; - UNICODE_STRING newdir; - IO_STATUS_BLOCK io; - CURDIR *curdir; - HANDLE handle; - NTSTATUS nts; -- ULONG size; - PWSTR ptr; - - newdir.Buffer = NULL; -@@ -938,6 +938,22 @@ NTSTATUS WINAPI RtlSetCurrentDirectory_U(const UNICODE_STRING* dir) - goto out; - } - -+ size = newdir.Length / sizeof(WCHAR); -+ ptr = newdir.Buffer; -+ ptr += 4; /* skip \??\ prefix */ -+ size -= 4; -+ -+ if (size && ptr[size - 1] == '\\') compare_size = size - 1; -+ else compare_size = size; -+ -+ if (curdir->DosPath.Length == (compare_size + 1) * sizeof(WCHAR) -+ && !memcmp( curdir->DosPath.Buffer, ptr, compare_size * sizeof(WCHAR) )) -+ { -+ TRACE( "dir %s is the same as current.\n", debugstr_us(dir) ); -+ nts = STATUS_SUCCESS; -+ goto out; -+ } -+ - attr.Length = sizeof(attr); - attr.RootDirectory = 0; - attr.Attributes = OBJ_CASE_INSENSITIVE; -@@ -962,10 +978,6 @@ NTSTATUS WINAPI RtlSetCurrentDirectory_U(const UNICODE_STRING* dir) - curdir->Handle = handle; - - /* append trailing \ if missing */ -- size = newdir.Length / sizeof(WCHAR); -- ptr = newdir.Buffer; -- ptr += 4; /* skip \??\ prefix */ -- size -= 4; - if (size && ptr[size - 1] != '\\') ptr[size++] = '\\'; - - /* convert \??\UNC\ path to \\ prefix */ --- -2.46.0 - diff --git a/0013-server-optimization/0001-misc/0760-ntdll-Resolve-drive-symlinks-when-querying-section-n.patch b/0013-server-optimization/0001-misc/0760-ntdll-Resolve-drive-symlinks-when-querying-section-n.patch deleted file mode 100644 index d78e50e..0000000 --- a/0013-server-optimization/0001-misc/0760-ntdll-Resolve-drive-symlinks-when-querying-section-n.patch +++ /dev/null @@ -1,119 +0,0 @@ -From b037f69d587a57ce72d4579ec50a4f5c171cef1c Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Mon, 11 Oct 2021 11:13:39 +0200 -Subject: [PATCH 0760/1562] ntdll: Resolve drive symlinks when querying section - names. - -Based on a patch by Sebastian Lackner. - -For BeamNG.drive. - -CW-Bug-Id: 18793 ---- - dlls/ntdll/unix/virtual.c | 83 ++++++++++++++++++++++++++++++++++++++- - 1 file changed, 82 insertions(+), 1 deletion(-) - -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 9a2a40c44ea..ed850f4772b 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -5360,6 +5360,86 @@ static NTSTATUS get_working_set_ex( HANDLE process, LPCVOID addr, - return STATUS_SUCCESS; - } - -+static NTSTATUS read_nt_symlink( UNICODE_STRING *name, WCHAR *target, DWORD size ) -+{ -+ NTSTATUS status; -+ OBJECT_ATTRIBUTES attr; -+ HANDLE handle; -+ -+ attr.Length = sizeof(attr); -+ attr.RootDirectory = 0; -+ attr.Attributes = OBJ_CASE_INSENSITIVE; -+ attr.ObjectName = name; -+ attr.SecurityDescriptor = NULL; -+ attr.SecurityQualityOfService = NULL; -+ -+ if (!(status = NtOpenSymbolicLinkObject( &handle, SYMBOLIC_LINK_QUERY, &attr ))) -+ { -+ UNICODE_STRING targetW; -+ targetW.Buffer = target; -+ targetW.MaximumLength = (size - 1) * sizeof(WCHAR); -+ status = NtQuerySymbolicLinkObject( handle, &targetW, NULL ); -+ if (!status) target[targetW.Length / sizeof(WCHAR)] = 0; -+ NtClose( handle ); -+ } -+ return status; -+} -+ -+static NTSTATUS resolve_drive_symlink( UNICODE_STRING *name, SIZE_T max_name_len, SIZE_T *ret_len, NTSTATUS status ) -+{ -+ static int enabled = -1; -+ -+ static const WCHAR dosprefixW[] = {'\\','?','?','\\'}; -+ UNICODE_STRING device_name; -+ SIZE_T required_length, symlink_len; -+ WCHAR symlink[256]; -+ size_t offset = 0; -+ -+ if (enabled == -1) -+ { -+ const char *sgi = getenv("SteamGameId"); -+ -+ enabled = sgi && !strcmp(sgi, "284160"); -+ } -+ if (!enabled) return status; -+ if (status == STATUS_INFO_LENGTH_MISMATCH) -+ { -+ /* FIXME */ -+ *ret_len += 64; -+ return status; -+ } -+ if (status) return status; -+ -+ if (name->Length < sizeof(dosprefixW) || -+ memcmp( name->Buffer, dosprefixW, sizeof(dosprefixW) )) -+ return STATUS_SUCCESS; -+ -+ offset = ARRAY_SIZE(dosprefixW); -+ while (offset * sizeof(WCHAR) < name->Length && name->Buffer[ offset ] != '\\') offset++; -+ -+ device_name = *name; -+ device_name.Length = offset * sizeof(WCHAR); -+ if ((status = read_nt_symlink( &device_name, symlink, ARRAY_SIZE( symlink )))) -+ { -+ ERR("read_nt_symlink failed, status %#x.\n", (int)status); -+ return status; -+ } -+ symlink_len = wcslen( symlink ); -+ required_length = symlink_len * sizeof(WCHAR) + -+ name->Length - offset * sizeof(WCHAR) + sizeof(WCHAR); -+ if (ret_len) -+ *ret_len = sizeof(MEMORY_SECTION_NAME) + required_length; -+ if (required_length > max_name_len) -+ return STATUS_INFO_LENGTH_MISMATCH; -+ -+ memmove( name->Buffer + symlink_len, name->Buffer + offset, name->Length - offset * sizeof(WCHAR) ); -+ memcpy( name->Buffer, symlink, symlink_len * sizeof(WCHAR) ); -+ name->MaximumLength = required_length; -+ name->Length = required_length - sizeof(WCHAR); -+ name->Buffer[name->Length / sizeof(WCHAR)] = 0; -+ return STATUS_SUCCESS; -+} -+ - static unsigned int get_memory_section_name( HANDLE process, LPCVOID addr, - MEMORY_SECTION_NAME *info, SIZE_T len, SIZE_T *ret_len ) - { -@@ -5388,7 +5468,8 @@ static unsigned int get_memory_section_name( HANDLE process, LPCVOID addr, - } - } - SERVER_END_REQ; -- return status; -+ -+ return resolve_drive_symlink( &info->SectionFileName, len - sizeof(*info), ret_len, status ); - } - - static unsigned int get_memory_image_info( HANDLE process, LPCVOID addr, MEMORY_IMAGE_INFORMATION *info, --- -2.45.2 - diff --git a/0013-server-optimization/0001-misc/0764-ntdll-Guard-against-syscall-stack-overrun.patch b/0013-server-optimization/0001-misc/0764-ntdll-Guard-against-syscall-stack-overrun.patch deleted file mode 100644 index 94d2f4f..0000000 --- a/0013-server-optimization/0001-misc/0764-ntdll-Guard-against-syscall-stack-overrun.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 72c83690354adb0d3f81e171f5fba938a4ac2755 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 10 Feb 2022 16:17:41 +0300 -Subject: [PATCH 0764/1562] ntdll: Guard against syscall stack overrun. - ---- - dlls/ntdll/unix/signal_arm.c | 4 ++++ - dlls/ntdll/unix/signal_arm64.c | 4 ++++ - dlls/ntdll/unix/signal_i386.c | 4 ++++ - dlls/ntdll/unix/signal_x86_64.c | 4 ++++ - dlls/ntdll/unix/unix_private.h | 10 +++++++++- - dlls/ntdll/unix/virtual.c | 6 ++++++ - 6 files changed, 31 insertions(+), 1 deletion(-) - -diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c -index 5115fa7ec3a..afa3e71c5e2 100644 ---- a/dlls/ntdll/unix/signal_arm.c -+++ b/dlls/ntdll/unix/signal_arm.c -@@ -1304,6 +1304,10 @@ static BOOL handle_syscall_fault( ucontext_t *context, EXCEPTION_RECORD *rec ) - (DWORD)IP_sig(context), (DWORD)SP_sig(context), (DWORD)LR_sig(context), - (DWORD)PC_sig(context), (DWORD)CPSR_sig(context) ); - -+ if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION -+ && is_inside_syscall_stack_guard( (char *)rec->ExceptionInformation[1] )) -+ ERR_(seh)( "Syscall stack overrun.\n "); -+ - if (ntdll_get_thread_data()->jmp_buf) - { - TRACE( "returning to handler\n" ); -diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c -index f96ec330796..389f16f89d9 100644 ---- a/dlls/ntdll/unix/signal_arm64.c -+++ b/dlls/ntdll/unix/signal_arm64.c -@@ -1271,6 +1271,10 @@ static BOOL handle_syscall_fault( ucontext_t *context, EXCEPTION_RECORD *rec ) - (DWORD64)REGn_sig(28, context), (DWORD64)FP_sig(context), - (DWORD64)LR_sig(context), (DWORD64)SP_sig(context) ); - -+ if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION -+ && is_inside_syscall_stack_guard( (char *)rec->ExceptionInformation[1] )) -+ ERR_(seh)( "Syscall stack overrun.\n "); -+ - if (ntdll_get_thread_data()->jmp_buf) - { - TRACE( "returning to handler\n" ); -diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c -index c372b5bf3a0..d39117b64fc 100644 ---- a/dlls/ntdll/unix/signal_i386.c -+++ b/dlls/ntdll/unix/signal_i386.c -@@ -1846,6 +1846,10 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr, - context->Ebp, context->Esp, context->SegCs, context->SegDs, - context->SegEs, context->SegFs, context->SegGs, context->EFlags ); - -+ if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION -+ && is_inside_syscall_stack_guard( (char *)rec->ExceptionInformation[1] )) -+ ERR_(seh)( "Syscall stack overrun.\n "); -+ - if (ntdll_get_thread_data()->jmp_buf) - { - TRACE( "returning to handler\n" ); -diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c -index d8d5678ec80..de8aaecf94c 100644 ---- a/dlls/ntdll/unix/signal_x86_64.c -+++ b/dlls/ntdll/unix/signal_x86_64.c -@@ -2128,6 +2128,10 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, EXCEPTION_RECORD *rec, - TRACE_(seh)( " r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n", - context->R12, context->R13, context->R14, context->R15 ); - -+ if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION -+ && is_inside_syscall_stack_guard( (char *)rec->ExceptionInformation[1] )) -+ ERR_(seh)( "Syscall stack overrun.\n "); -+ - if (ntdll_get_thread_data()->jmp_buf) - { - TRACE_(seh)( "returning to handler\n" ); -diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index 904a35f471b..55d3a0fb53c 100644 ---- a/dlls/ntdll/unix/unix_private.h -+++ b/dlls/ntdll/unix/unix_private.h -@@ -127,7 +127,8 @@ static const SIZE_T teb_size = 0x3800; /* TEB64 + TEB32 + debug info */ - static const SIZE_T signal_stack_mask = 0xffff; - static const SIZE_T signal_stack_size = 0x10000 - 0x3800; - static const SIZE_T kernel_stack_size = 0x100000; --static const SIZE_T min_kernel_stack = 0x2000; -+static const SIZE_T kernel_stack_guard_size = 0x1000; -+static const SIZE_T min_kernel_stack = 0x3000; - static const LONG teb_offset = 0x2000; - - #define FILE_WRITE_TO_END_OF_FILE ((LONGLONG)-1) -@@ -388,6 +389,13 @@ static inline BOOL is_inside_signal_stack( void *ptr ) - (char *)ptr < (char *)get_signal_stack() + signal_stack_size); - } - -+static inline BOOL is_inside_syscall_stack_guard( const char *stack_ptr ) -+{ -+ const char *kernel_stack = ntdll_get_thread_data()->kernel_stack; -+ -+ return (stack_ptr >= kernel_stack && stack_ptr < kernel_stack + kernel_stack_guard_size); -+} -+ - static inline void mutex_lock( pthread_mutex_t *mutex ) - { - if (!process_exiting) pthread_mutex_lock( mutex ); -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index ed850f4772b..d6dbd917ce5 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -3929,6 +3929,12 @@ NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR limit_low, UL - VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_GUARD ); - mprotect_range( view->base, 2 * page_size , 0, 0 ); - } -+ else -+ { -+ /* setup kernel stack no access guard page */ -+ set_page_vprot( view->base, kernel_stack_guard_size, VPROT_COMMITTED | VPROT_READ ); -+ mprotect_range( view->base, kernel_stack_guard_size, 0, 0 ); -+ } - VIRTUAL_DEBUG_DUMP_VIEW( view ); - - /* note: limit is lower than base since the stack grows down */ --- -2.45.2 - diff --git a/0013-server-optimization/0001-misc/0765-ntdll-Fix-holes-in-ELF-mappings.-v2.patch b/0013-server-optimization/0001-misc/0765-ntdll-Fix-holes-in-ELF-mappings.-v2.patch deleted file mode 100644 index 661da84..0000000 --- a/0013-server-optimization/0001-misc/0765-ntdll-Fix-holes-in-ELF-mappings.-v2.patch +++ /dev/null @@ -1,99 +0,0 @@ -From fffa15b9be8c18c818771bf4118e8a852b685f98 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Thu, 1 Jun 2017 06:04:53 +0200 -Subject: [PATCH 0765/1562] ntdll: Fix holes in ELF mappings. (v2) - -Based on a patch by Andrew Wesie. - -Included to fix crash on startup of WRC8. - -Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=44650 -Link: https://github.com/wine-staging/wine-staging/tree/v6.3/patches/ntdll-Builtin_Prot -Link: https://github.com/ValveSoftware/wine/pull/121 -CW-Bug-Id: #19337 ---- - dlls/ntdll/unix/virtual.c | 25 +++++++++++++++++++++++++ - dlls/psapi/tests/psapi_main.c | 14 +++++++++++++- - 2 files changed, 38 insertions(+), 1 deletion(-) - -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index d6dbd917ce5..a1a97ac1f4a 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -4043,6 +4043,16 @@ static NTSTATUS grow_thread_stack( char *page, struct thread_stack_info *stack_i - } - - -+/*********************************************************************** -+ * is_system_range -+ */ -+static inline BOOL is_system_range( const void *addr, size_t size ) -+{ -+ struct file_view *view = find_view( addr, size ); -+ return view && (view->protect & VPROT_SYSTEM); -+} -+ -+ - /*********************************************************************** - * virtual_handle_fault - */ -@@ -4089,6 +4099,21 @@ NTSTATUS virtual_handle_fault( void *addr, DWORD err, void *stack ) - ret = STATUS_SUCCESS; - } - } -+ else if (!err && (get_unix_prot( vprot ) & PROT_READ) && is_system_range( page, page_size )) -+ { -+ int unix_prot = get_unix_prot( vprot ); -+ unsigned char vec; -+ -+ TRACE("yolo\n"); -+ -+ mprotect_range( page, page_size, 0, 0 ); -+ if (!mincore( page, page_size, &vec ) && (vec & 1)) -+ ret = STATUS_SUCCESS; -+ else if (anon_mmap_fixed( page, page_size, unix_prot, 0 ) == page) -+ ret = STATUS_SUCCESS; -+ else -+ set_page_vprot_bits( page, page_size, 0, VPROT_READ | VPROT_EXEC ); -+ } - mutex_unlock( &virtual_mutex ); - return ret; - } -diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c -index e7e5e5f04e6..17df780ba0c 100644 ---- a/dlls/psapi/tests/psapi_main.c -+++ b/dlls/psapi/tests/psapi_main.c -@@ -581,6 +581,7 @@ static void test_EnumProcessModulesEx(void) - static void test_GetModuleInformation(void) - { - HMODULE hMod = GetModuleHandleA(NULL); -+ DWORD *tmp, counter = 0; - MODULEINFO info; - DWORD ret; - -@@ -600,10 +601,21 @@ static void test_GetModuleInformation(void) - GetModuleInformation(hpQV, hMod, &info, sizeof(info)-1); - ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %ld\n", GetLastError()); - -- SetLastError(0xdeadbeef); - ret = GetModuleInformation(hpQV, hMod, &info, sizeof(info)); - ok(ret == 1, "failed with %ld\n", GetLastError()); - ok(info.lpBaseOfDll == hMod, "lpBaseOfDll=%p hMod=%p\n", info.lpBaseOfDll, hMod); -+ -+ hMod = LoadLibraryA("shell32.dll"); -+ ok(hMod != NULL, "Failed to load shell32.dll, error: %u\n", GetLastError()); -+ -+ ret = GetModuleInformation(hpQV, hMod, &info, sizeof(info)); -+ ok(ret == 1, "failed with %d\n", GetLastError()); -+ info.SizeOfImage /= sizeof(DWORD); -+ for (tmp = (DWORD *)hMod; info.SizeOfImage; info.SizeOfImage--) -+ counter ^= *tmp++; -+ trace("xor of shell32: %08x\n", counter); -+ -+ FreeLibrary(hMod); - } - - static BOOL check_with_margin(SIZE_T perf, SIZE_T sysperf, int margin) --- -2.45.2 - diff --git a/0013-server-optimization/0001-misc/0770-ntdll-Factor-out-prepend_system_dir-function.patch b/0013-server-optimization/0001-misc/0770-ntdll-Factor-out-prepend_system_dir-function.patch deleted file mode 100644 index e43d70d..0000000 --- a/0013-server-optimization/0001-misc/0770-ntdll-Factor-out-prepend_system_dir-function.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 560856ba66e6e8ddd1211fdd76529e65b2723629 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 2 Feb 2023 14:48:37 -0600 -Subject: [PATCH 0770/1793] ntdll: Factor out prepend_system_dir() function. - -CW-Bug-Id: #21866 ---- - dlls/ntdll/loader.c | 26 ++++++++++++++++++-------- - 1 file changed, 18 insertions(+), 8 deletions(-) - -diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c -index 866641dcb15..142fd939ed5 100644 ---- a/dlls/ntdll/loader.c -+++ b/dlls/ntdll/loader.c -@@ -3004,6 +3004,23 @@ done: - } - - -+/****************************************************************************** -+ * prepend_system_dir -+ */ -+static NTSTATUS prepend_system_dir( const WCHAR *name, ULONG name_length, WCHAR **fullname ) -+{ -+ ULONG len; -+ -+ len = wcslen( system_dir ) + name_length; -+ if (!(*fullname = RtlAllocateHeap( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) -+ return STATUS_NO_MEMORY; -+ wcscpy( *fullname, system_dir ); -+ memcpy( *fullname + wcslen( system_dir ), name, name_length * sizeof(WCHAR) ); -+ (*fullname)[len] = 0; -+ -+ return STATUS_SUCCESS; -+} -+ - - /****************************************************************************** - * find_apiset_dll -@@ -3013,18 +3030,11 @@ static NTSTATUS find_apiset_dll( const WCHAR *name, WCHAR **fullname ) - const API_SET_NAMESPACE *map = NtCurrentTeb()->Peb->ApiSetMap; - const API_SET_NAMESPACE_ENTRY *entry; - UNICODE_STRING str; -- ULONG len; - - if (get_apiset_entry( map, name, wcslen(name), &entry )) return STATUS_APISET_NOT_PRESENT; - if (get_apiset_target( map, entry, NULL, &str )) return STATUS_DLL_NOT_FOUND; - -- len = wcslen( system_dir ) + str.Length / sizeof(WCHAR); -- if (!(*fullname = RtlAllocateHeap( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) -- return STATUS_NO_MEMORY; -- wcscpy( *fullname, system_dir ); -- memcpy( *fullname + wcslen( system_dir ), str.Buffer, str.Length ); -- (*fullname)[len] = 0; -- return STATUS_SUCCESS; -+ return prepend_system_dir( str.Buffer, str.Length / sizeof(WCHAR), fullname ); - } - - --- -2.46.0 - diff --git a/0013-server-optimization/0001-misc/0772-ntdll-Load-known-dlls-from-system-directory.patch b/0013-server-optimization/0001-misc/0772-ntdll-Load-known-dlls-from-system-directory.patch deleted file mode 100644 index 720f3f2..0000000 --- a/0013-server-optimization/0001-misc/0772-ntdll-Load-known-dlls-from-system-directory.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 38caaef57f3fb88777c935874bd9428091b50299 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 2 Feb 2023 17:14:54 -0600 -Subject: [PATCH 0772/1793] ntdll: Load known dlls from system directory. - -CW-Bug-Id: #21866 ---- - dlls/kernel32/tests/module.c | 9 ++++-- - dlls/ntdll/loader.c | 54 +++++++++++++++++++++++++++++++++++- - 2 files changed, 59 insertions(+), 4 deletions(-) - -# diff --git a/dlls/kernel32/tests/module.c b/dlls/kernel32/tests/module.c -# index 0e38ce80f54..7dd1125a0a6 100644 -# --- a/dlls/kernel32/tests/module.c -# +++ b/dlls/kernel32/tests/module.c -# @@ -1675,13 +1675,15 @@ static void test_known_dlls_load(void) -# h = LoadLibraryA( dll ); -# ret = pSetDefaultDllDirectories( LOAD_LIBRARY_SEARCH_DEFAULT_DIRS ); -# ok( ret, "SetDefaultDllDirectories failed err %lu\n", GetLastError() ); -# - todo_wine ok( !!h, "Got NULL.\n" ); -# + ok( !!h, "Got NULL.\n" ); -# + check_dll_path( h, system_path ); -# hapiset = GetModuleHandleA( apiset_dll ); -# ok( hapiset == h, "Got %p, %p.\n", hapiset, h ); -# FreeLibrary( h ); - -# h = LoadLibraryExA( dll, 0, LOAD_LIBRARY_SEARCH_APPLICATION_DIR ); -# - todo_wine ok( !!h, "Got NULL.\n" ); -# + ok( !!h, "Got NULL.\n" ); -# + check_dll_path( h, system_path ); -# hapiset = GetModuleHandleA( apiset_dll ); -# ok( hapiset == h, "Got %p, %p.\n", hapiset, h ); -# FreeLibrary( h ); -# @@ -1691,8 +1693,9 @@ static void test_known_dlls_load(void) - -# h = LoadLibraryExA( dll, 0, LOAD_LIBRARY_SEARCH_APPLICATION_DIR ); -# ok( !!h, "Got NULL.\n" ); -# + check_dll_path( h, system_path ); -# hapiset = GetModuleHandleA( apiset_dll ); -# - todo_wine ok( hapiset == h, "Got %p, %p.\n", hapiset, h ); -# + ok( hapiset == h, "Got %p, %p.\n", hapiset, h ); -# FreeLibrary( h ); - -# /* Local version can still be loaded if dll name contains path. */ -diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c -index 142fd939ed5..7084d874d92 100644 ---- a/dlls/ntdll/loader.c -+++ b/dlls/ntdll/loader.c -@@ -34,6 +34,7 @@ - #include "wine/exception.h" - #include "wine/debug.h" - #include "wine/list.h" -+#include "wine/rbtree.h" - #include "ntdll_misc.h" - #include "ddk/ntddk.h" - #include "ddk/wdm.h" -@@ -193,6 +194,13 @@ static WINE_MODREF *last_failed_modref; - - static LDR_DDAG_NODE *node_ntdll, *node_kernel32; - -+struct known_dll -+{ -+ struct rb_entry entry; -+ WCHAR name[1]; -+}; -+static struct rb_tree known_dlls; -+ - static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, DWORD flags, WINE_MODREF** pwm, BOOL system ); - static NTSTATUS process_attach( LDR_DDAG_NODE *node, LPVOID lpReserved ); - static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, -@@ -3332,6 +3340,7 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, UNI - WINE_MODREF **pwm, HANDLE *mapping, SECTION_IMAGE_INFORMATION *image_info, - struct file_id *id ) - { -+ const WCHAR *known_dll_name = NULL; - WCHAR *fullname = NULL; - NTSTATUS status; - ULONG wow64_old_value = 0; -@@ -3364,6 +3373,12 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, UNI - goto done; - } - } -+ if (!fullname && rb_get( &known_dlls, libname )) -+ { -+ prepend_system_dir( libname, wcslen(libname), &fullname ); -+ known_dll_name = libname; -+ libname = fullname; -+ } - } - - if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH) -@@ -3373,7 +3388,11 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, UNI - status = find_builtin_without_file( libname, nt_name, pwm, mapping, image_info, id ); - } - else if (!(status = RtlDosPathNameToNtPathName_U_WithStatus( libname, nt_name, NULL, NULL ))) -+ { - status = open_dll_file( nt_name, pwm, mapping, image_info, id ); -+ if (status == STATUS_DLL_NOT_FOUND && known_dll_name) -+ status = find_builtin_without_file( known_dll_name, nt_name, pwm, mapping, image_info, id ); -+ } - - if (status == STATUS_NOT_SUPPORTED) status = STATUS_INVALID_IMAGE_FORMAT; - -@@ -4232,16 +4251,31 @@ PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule) - return ret; - } - -+/************************************************************************* -+ * compare_known_dlls -+ */ -+static int compare_known_dlls( const void *name, const struct wine_rb_entry *entry ) -+{ -+ struct known_dll *known_dll = WINE_RB_ENTRY_VALUE( entry, struct known_dll, entry ); -+ -+ return wcsicmp( name, known_dll->name ); -+} -+ - /*********************************************************************** - * load_global_options - */ - static void load_global_options(void) - { -+ char buffer[256]; -+ KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; - OBJECT_ATTRIBUTES attr; - UNICODE_STRING bootstrap_mode_str = RTL_CONSTANT_STRING( L"WINEBOOTSTRAPMODE" ); - UNICODE_STRING session_manager_str = - RTL_CONSTANT_STRING( L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager" ); -- UNICODE_STRING val_str; -+ UNICODE_STRING val_str, name_str; -+ struct known_dll *known_dll; -+ ULONG idx = 0, size; -+ NTSTATUS status; - HANDLE hkey; - - val_str.MaximumLength = 0; -@@ -4261,6 +4295,25 @@ static void load_global_options(void) - query_dword_option( hkey, L"SafeDllSearchMode", &dll_safe_mode ); - NtClose( hkey ); - } -+ -+ rb_init( &known_dlls, compare_known_dlls ); -+ -+ RtlInitUnicodeString( &name_str, -+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\KnownDLLs" ); -+ if (NtOpenKey( &hkey, KEY_QUERY_VALUE, &attr )) return; -+ while (1) -+ { -+ status = NtEnumerateValueKey( hkey, idx++, KeyValuePartialInformation, buffer, sizeof(buffer), &size ); -+ if (status == STATUS_BUFFER_OVERFLOW) continue; -+ if (status) break; -+ if (info->Type != REG_SZ) continue; -+ -+ known_dll = RtlAllocateHeap( GetProcessHeap(), 0, offsetof(struct known_dll, name[0]) + info->DataLength ); -+ if (!known_dll) break; -+ memcpy( known_dll->name, info->Data, info->DataLength ); -+ rb_put( &known_dlls, known_dll->name, &known_dll->entry ); -+ } -+ NtClose( hkey ); - } - - static BOOL needs_elevation(void) --- -2.46.0 - diff --git a/0013-server-optimization/0001-misc/0799-ntdll-Do-not-inherit-Unix-std-handles-for-files-with.patch b/0013-server-optimization/0001-misc/0799-ntdll-Do-not-inherit-Unix-std-handles-for-files-with.patch deleted file mode 100644 index c31487b..0000000 --- a/0013-server-optimization/0001-misc/0799-ntdll-Do-not-inherit-Unix-std-handles-for-files-with.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 20d7c6d6e0c2ad95b3dcec9b054893e888023c5d Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Wed, 3 May 2023 17:23:40 -0600 -Subject: [PATCH 0799/1793] ntdll: Do not inherit Unix std handles for files - without a name. - -CW-Bug-Id: #22237 ---- - dlls/ntdll/unix/env.c | 27 ++++++++++++++++++++++++--- - 1 file changed, 24 insertions(+), 3 deletions(-) - -diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c -index ff3f28d93e1..29f5aa2b17f 100644 ---- a/dlls/ntdll/unix/env.c -+++ b/dlls/ntdll/unix/env.c -@@ -1394,6 +1394,27 @@ static void add_registry_environment( WCHAR **env, SIZE_T *pos, SIZE_T *size ) - } - } - -+static void get_std_handle( int fd, unsigned int access, unsigned int attributes, HANDLE *handle ) -+{ -+ IO_STATUS_BLOCK io; -+ FILE_POSITION_INFORMATION pos_info; -+ FILE_NAME_INFORMATION name_info; -+ NTSTATUS status; -+ -+ wine_server_fd_to_handle( fd, access, attributes, handle ); -+ if (!*handle) return; -+ -+ /* Python checks if a file is seekable and if so expects the file name to be gettable from handle. */ -+ if (NtQueryInformationFile( *handle, &io, &pos_info, sizeof(pos_info), FilePositionInformation )) -+ return; -+ -+ TRACE("handle for fd %d is seekable.\n", fd); -+ if (!(status = NtQueryInformationFile( *handle, &io, &name_info, sizeof(name_info), FileNameInformation )) -+ || status == STATUS_BUFFER_OVERFLOW) return; -+ TRACE("closing handle for fd %d.\n", fd); -+ NtClose( *handle ); -+ *handle = NULL; -+} - - /************************************************************************* - * get_initial_console -@@ -1404,9 +1425,9 @@ static void get_initial_console( RTL_USER_PROCESS_PARAMETERS *params ) - { - int output_fd = -1; - -- wine_server_fd_to_handle( 0, GENERIC_READ|SYNCHRONIZE, OBJ_INHERIT, ¶ms->hStdInput ); -- wine_server_fd_to_handle( 1, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, ¶ms->hStdOutput ); -- wine_server_fd_to_handle( 2, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, ¶ms->hStdError ); -+ get_std_handle( 0, GENERIC_READ|SYNCHRONIZE, OBJ_INHERIT, ¶ms->hStdInput ); -+ get_std_handle( 1, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, ¶ms->hStdOutput ); -+ get_std_handle( 2, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, ¶ms->hStdError ); - - if (main_image_info.SubSystemType != IMAGE_SUBSYSTEM_WINDOWS_CUI) - return; --- -2.46.0 - diff --git a/0013-server-optimization/0001-misc/0868-HACK-server-Disable-hooks-that-time-out.patch b/0013-server-optimization/0001-misc/0868-HACK-server-Disable-hooks-that-time-out.patch new file mode 100644 index 0000000..c55bd51 --- /dev/null +++ b/0013-server-optimization/0001-misc/0868-HACK-server-Disable-hooks-that-time-out.patch @@ -0,0 +1,152 @@ +From 74e8b85db92a4f5643115d6c7f434795d5b535e3 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Mon, 24 Apr 2023 19:58:11 -0600 +Subject: [PATCH 0868/2346] HACK: server: Disable hooks that time out. + +An addition to "HACK: user32: Remove hooks that time out." + +CW-Bug-Id: #22178 +--- + server/hook.c | 25 ++++++++++++++++++++++++- + server/queue.c | 22 ++++++++++++++++++---- + server/user.h | 3 ++- + 3 files changed, 44 insertions(+), 6 deletions(-) + +diff --git a/server/hook.c b/server/hook.c +index 3a89a883c3c..24eb27434db 100644 +--- a/server/hook.c ++++ b/server/hook.c +@@ -405,16 +405,39 @@ void remove_thread_hooks( struct thread *thread ) + } + + /* return the thread that owns the first global hook */ +-struct thread *get_first_global_hook( struct desktop *desktop, int id ) ++struct thread *get_first_global_hook( struct desktop *desktop, int id, thread_id_t *thread_id, client_ptr_t *proc ) + { + struct hook *hook; + struct hook_table *global_hooks = desktop->global_hooks; + + if (!global_hooks) return NULL; + if (!(hook = get_first_valid_hook( global_hooks, id - WH_MINHOOK, EVENT_MIN, 0, 0, 0 ))) return NULL; ++ *thread_id = hook->owner->id; ++ *proc = hook->proc; + return hook->owner; + } + ++void disable_hung_hook( struct desktop *desktop, int id, thread_id_t thread_id, client_ptr_t proc ) ++{ ++ struct hook_table *global_hooks = desktop->global_hooks; ++ int index = id - WH_MINHOOK; ++ struct hook *hook; ++ ++ if (!global_hooks || !proc) return; ++ ++ hook = get_first_hook( global_hooks, index ); ++ ++ while (hook) ++ { ++ if (hook->proc == proc && hook->owner->id == thread_id) ++ { ++ hook->proc = 0; ++ return; ++ } ++ hook = HOOK_ENTRY( list_next( &global_hooks->hooks[index], &hook->chain ) ); ++ } ++} ++ + /* set a window hook */ + DECL_HANDLER(set_hook) + { +diff --git a/server/queue.c b/server/queue.c +index fb6fe2d9478..12592241c92 100644 +--- a/server/queue.c ++++ b/server/queue.c +@@ -72,6 +72,8 @@ struct message_result + void *data; /* message reply data */ + unsigned int data_size; /* size of message reply data */ + struct timeout_user *timeout; /* result timeout */ ++ thread_id_t hook_thread_id;/* Hook owner thread id. */ ++ client_ptr_t hook_proc; /* Hook proc address. */ + }; + + struct message +@@ -1016,6 +1018,13 @@ static void result_timeout( void *private ) + { + struct message *msg = result->msg; + ++ if (result->sender && result->hook_thread_id && result->hook_proc) ++ { ++ if (debug_level > 1) ++ fprintf( stderr, "disabling hung hook: tid %04x, proc %#lx\n", ++ result->hook_thread_id, (unsigned long)result->hook_proc ); ++ disable_hung_hook( result->sender->input->desktop, msg->msg, result->hook_thread_id, result->hook_proc ); ++ } + result->msg = NULL; + msg->result = NULL; + remove_queue_message( result->receiver, msg, SEND_MESSAGE ); +@@ -1027,7 +1036,8 @@ static void result_timeout( void *private ) + /* allocate and fill a message result structure */ + static struct message_result *alloc_message_result( struct msg_queue *send_queue, + struct msg_queue *recv_queue, +- struct message *msg, timeout_t timeout ) ++ struct message *msg, timeout_t timeout, ++ thread_id_t hook_thread_id, client_ptr_t hook_proc) + { + struct message_result *result = mem_alloc( sizeof(*result) ); + if (result) +@@ -1042,6 +1052,8 @@ static struct message_result *alloc_message_result( struct msg_queue *send_queue + result->hardware_msg = NULL; + result->desktop = NULL; + result->callback_msg = NULL; ++ result->hook_thread_id = hook_thread_id; ++ result->hook_proc = hook_proc; + + if (msg->type == MSG_CALLBACK) + { +@@ -2027,8 +2039,10 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa + struct msg_queue *queue; + struct message *msg; + timeout_t timeout = 2000 * -10000; /* FIXME: load from registry */ ++ thread_id_t hook_thread_id; ++ client_ptr_t hook_proc; + +- if (!(hook_thread = get_first_global_hook( desktop, id ))) return 0; ++ if (!(hook_thread = get_first_global_hook( desktop, id, &hook_thread_id, &hook_proc ))) return 0; + if (!(queue = hook_thread->queue)) return 0; + if (is_queue_hung( queue )) return 0; + +@@ -2046,7 +2060,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa + msg->result = NULL; + + if (!(msg->data = memdup( hardware_msg->data, hardware_msg->data_size )) || +- !(msg->result = alloc_message_result( sender, queue, msg, timeout ))) ++ !(msg->result = alloc_message_result( sender, queue, msg, timeout, hook_thread_id, hook_proc ))) + { + free_message( msg ); + return 0; +@@ -3272,7 +3286,7 @@ DECL_HANDLER(send_message) + case MSG_ASCII: + case MSG_UNICODE: + case MSG_CALLBACK: +- if (!(msg->result = alloc_message_result( send_queue, recv_queue, msg, req->timeout ))) ++ if (!(msg->result = alloc_message_result( send_queue, recv_queue, msg, req->timeout, 0, 0 ))) + { + free_message( msg ); + break; +diff --git a/server/user.h b/server/user.h +index 26d22a00240..a6ef5fc1f83 100644 +--- a/server/user.h ++++ b/server/user.h +@@ -115,7 +115,8 @@ extern void cleanup_clipboard_thread( struct thread *thread ); + + extern void remove_thread_hooks( struct thread *thread ); + extern unsigned int get_active_hooks(void); +-extern struct thread *get_first_global_hook( struct desktop *desktop, int id ); ++extern struct thread *get_first_global_hook( struct desktop *desktop, int id, thread_id_t *thread_id, client_ptr_t *proc ); ++extern void disable_hung_hook( struct desktop *desktop, int id, thread_id_t thread_id, client_ptr_t proc ); + extern void add_desktop_hook_count( struct desktop *desktop, struct thread *thread, int count ); + + /* queue functions */ +-- +2.47.0 + diff --git a/0013-server-optimization/0001-misc/1031-webservices-Prefer-native.patch b/0013-server-optimization/0001-misc/1031-webservices-Prefer-native.patch deleted file mode 100644 index 2434360..0000000 --- a/0013-server-optimization/0001-misc/1031-webservices-Prefer-native.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 124b98506fd7f289b71fbad79d10df24d953e09d Mon Sep 17 00:00:00 2001 -From: Jacek Caban -Date: Mon, 8 Mar 2021 16:41:19 +0100 -Subject: [PATCH 1031/1793] webservices: Prefer native. - -CW-Bug-Id: #18637 ---- - dlls/webservices/Makefile.in | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/dlls/webservices/Makefile.in b/dlls/webservices/Makefile.in -index 78b7e06af4b..8a613eb6414 100644 ---- a/dlls/webservices/Makefile.in -+++ b/dlls/webservices/Makefile.in -@@ -2,6 +2,8 @@ MODULE = webservices.dll - IMPORTLIB = webservices - IMPORTS = winhttp rpcrt4 user32 ws2_32 - -+EXTRADLLFLAGS = -Wb,--prefer-native -+ - SOURCES = \ - channel.c \ - error.c \ --- -2.46.0 - diff --git a/0013-server-optimization/0001-misc/1032-kernelbase-Ignore-LOAD_LIBRARY_SEARCH_SYSTEM32-flags.patch b/0013-server-optimization/0001-misc/1032-kernelbase-Ignore-LOAD_LIBRARY_SEARCH_SYSTEM32-flags.patch deleted file mode 100644 index 66076ca..0000000 --- a/0013-server-optimization/0001-misc/1032-kernelbase-Ignore-LOAD_LIBRARY_SEARCH_SYSTEM32-flags.patch +++ /dev/null @@ -1,33 +0,0 @@ -From f94a13a11c7595c99988279caf250580fb77f8a7 Mon Sep 17 00:00:00 2001 -From: Jacek Caban -Date: Wed, 8 Dec 2021 23:36:27 +0100 -Subject: [PATCH 1032/1793] kernelbase: Ignore LOAD_LIBRARY_SEARCH_SYSTEM32 - flags for webservices.dll in LoadLibraryExW. - -CW-Bug-Id: #18637 ---- - dlls/kernelbase/loader.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c -index f9aad8e1207..cbb6e49dab2 100644 ---- a/dlls/kernelbase/loader.c -+++ b/dlls/kernelbase/loader.c -@@ -536,6 +536,14 @@ HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW( LPCWSTR name, HANDLE file, DWOR - SetLastError( ERROR_INVALID_PARAMETER ); - return 0; - } -+ -+ /* HACK: allow webservices.dll to be shipped together with remote debugger tools. */ -+ if (flags == LOAD_LIBRARY_SEARCH_SYSTEM32 && !file && !wcscmp( name, L"webservices.dll" )) -+ { -+ FIXME( "HACK: ignoring LOAD_LIBRARY_SEARCH_SYSTEM32 for webservices.dll\n" ); -+ flags = 0; -+ } -+ - RtlInitUnicodeString( &str, name ); - if (str.Buffer[str.Length/sizeof(WCHAR) - 1] != ' ') return load_library( &str, flags ); - --- -2.46.0 - diff --git a/9000-misc-additions/optimize-server-read-big-buffer.patch b/0013-server-optimization/0001-misc/5555-optimize-server-read-big-buffer.patch similarity index 100% rename from 9000-misc-additions/optimize-server-read-big-buffer.patch rename to 0013-server-optimization/0001-misc/5555-optimize-server-read-big-buffer.patch diff --git a/0013-server-optimization/0001-misc/ps0001-ntdll-Try-mmap-again-without-exec-if-it-fails-with.patch b/0013-server-optimization/0001-misc/ps0001-ntdll-Try-mmap-again-without-exec-if-it-fails-with.patch deleted file mode 100644 index c160264..0000000 --- a/0013-server-optimization/0001-misc/ps0001-ntdll-Try-mmap-again-without-exec-if-it-fails-with.patch +++ /dev/null @@ -1,43 +0,0 @@ -From: Chip Davis -Subject: [PATCH] ntdll: Try mmap again without exec if it fails with it. -Message-Id: <20190924004449.16473-1-cdavis@codeweavers.com> -Date: Mon, 23 Sep 2019 19:44:49 -0500 - -On some systems, mmap(2) with PROT_WRITE | PROT_EXEC can legitimately -fail. If we added PROT_EXEC implicitly, try again without it. - -Signed-off-by: Chip Davis ---- - dlls/ntdll/unix/virtual.c | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 11111111111..11111111111 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -2134,6 +2134,7 @@ static NTSTATUS map_file_into_view( struct file_view *view, int fd, size_t start - /* only try mmap if media is not removable (or if we require write access) */ - if (!removable || (flags & MAP_SHARED)) - { -+try_again: - if (mmap( (char *)view->base + start, size, prot, flags, fd, offset ) != MAP_FAILED) - goto done; - -@@ -2154,7 +2155,16 @@ static NTSTATUS map_file_into_view( struct file_view *view, int fd, size_t start - case EPERM: /* noexec filesystem, fall back to read() */ - if (flags & MAP_SHARED) - { -- if (prot & PROT_EXEC) ERR( "failed to set PROT_EXEC on file map, noexec filesystem?\n" ); -+ if (prot & PROT_EXEC) -+ { -+ if (force_exec_prot && (vprot & (VPROT_WRITE|VPROT_EXEC)) == VPROT_WRITE) -+ { -+ /* exec + write may legitimately fail, in that case fall back to write only */ -+ prot &= ~PROT_EXEC; -+ goto try_again; -+ } -+ ERR( "failed to set PROT_EXEC on file map, noexec filesystem?\n" ); -+ } - return STATUS_ACCESS_DENIED; - } - if (prot & PROT_EXEC) WARN( "failed to set PROT_EXEC on file map, noexec filesystem?\n" ); diff --git a/0013-server-optimization/0001-misc/ps0050-oleaut32-CoMsgWaitForMultipleHandles-message-pump.patch b/0013-server-optimization/0001-misc/ps0050-oleaut32-CoMsgWaitForMultipleHandles-message-pump.patch deleted file mode 100644 index 13b89e4..0000000 --- a/0013-server-optimization/0001-misc/ps0050-oleaut32-CoMsgWaitForMultipleHandles-message-pump.patch +++ /dev/null @@ -1,509 +0,0 @@ -From: Kevin Puetz -Subject: [PATCH] oleaut32: CoMsgWaitForMultipleHandles message pump. -Message-Id: <20201124231833.11578-1-PuetzKevinA@JohnDeere.com> -Date: Tue, 24 Nov 2020 17:18:32 -0600 - -Check for completion (handles/APC) before pumping any messages, and -again after each message is dispatched, returning as soon as the wait -condition is satisfied. This matches windows behavior and obsoletes -the previous "100 message" workaround for WM_PAINT. - -Only report timeout before/during sleep, not while actively working. -The previous code had a narrow race (particularly for timeout=0): -if GetTickCount incremented between start_time and the loop body -it could WAIT_TIMEOUT even if the handles were already signaled. -No test; I couldn't think of a way to provoke this consistently. - -NOTE: this means CoWaitForMultipleHandles does not time out while -there are still queued messages, and will livelock (and never time out) -if dispatching of messages continuously posts additional messages. -It will exit (successfully) if the handles eventually become signaled. -The latter is the only case tested, since I don't know how to write -a successful test for "this will livelock and hang the process". -But windows does do the same. - -Notify IMessageFilter::MessagePending only for messages that wake -CoWait from MsgWait (sleeping on an empty queue), but not for -messages already posted before it sleeps. - -Add tests for IMessageFilter::MessagePending -> PENDINGMSG_CANCELCALL -One of these is todo_wine, as was the existing MessageFilter test. -The bug is the same: windows does not call MessagePending for DDE/RPC -messages, but wine (still) does. I'm not sure what the right structure -is to fix this, but it's a separate (and preexisting) issue. ---- - dlls/combase/combase.c | 173 +++++++++++++++++++------------------ - dlls/ole32/tests/compobj.c | 164 +++++++++++++++++++++++++++++++++++ - 2 files changed, 253 insertions(+), 84 deletions(-) - -diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c -index 11111111111..11111111111 100644 ---- a/dlls/combase/combase.c -+++ b/dlls/combase/combase.c -@@ -2050,12 +2050,13 @@ static BOOL com_peek_message(struct apartment *apt, MSG *msg) - HRESULT WINAPI CoWaitForMultipleHandles(DWORD flags, DWORD timeout, ULONG handle_count, HANDLE *handles, - DWORD *index) - { -- BOOL check_apc = !!(flags & COWAIT_ALERTABLE), message_loop; -+ BOOL message_loop; - struct { BOOL post; UINT code; } quit = { .post = FALSE }; - DWORD start_time, wait_flags = 0; - struct tlsdata *tlsdata; - struct apartment *apt; - HRESULT hr; -+ DWORD res; - - TRACE("%#lx, %#lx, %lu, %p, %p\n", flags, timeout, handle_count, handles, index); - -@@ -2084,113 +2085,117 @@ HRESULT WINAPI CoWaitForMultipleHandles(DWORD flags, DWORD timeout, ULONG handle - - start_time = GetTickCount(); - -- while (TRUE) -+ if (message_loop) - { -- DWORD now = GetTickCount(), res; -- -- if (now - start_time > timeout) -+ while (TRUE) - { -- hr = RPC_S_CALLPENDING; -- break; -- } -+ MSG msg; - -- if (message_loop) -- { - TRACE("waiting for rpc completion or window message\n"); - -- res = WAIT_TIMEOUT; -+ res = WaitForMultipleObjectsEx(handle_count, handles, -+ !!(flags & COWAIT_WAITALL), 0, !!(flags & COWAIT_ALERTABLE)); - -- if (check_apc) -+ if (res != WAIT_TIMEOUT) - { -- res = WaitForMultipleObjectsEx(handle_count, handles, !!(flags & COWAIT_WAITALL), 0, TRUE); -- check_apc = FALSE; -+ break; - } - -- if (res == WAIT_TIMEOUT) -- res = MsgWaitForMultipleObjectsEx(handle_count, handles, -- timeout == INFINITE ? INFINITE : start_time + timeout - now, -- QS_SENDMESSAGE | QS_ALLPOSTMESSAGE | QS_PAINT, wait_flags); -- -- if (res == WAIT_OBJECT_0 + handle_count) /* messages available */ -+ if (!apt->win) - { -- int msg_count = 0; -- MSG msg; -- -- /* call message filter */ -+ /* If window is NULL on apartment, peek at messages so that it will not trigger -+ * MsgWaitForMultipleObjects next time. */ -+ PeekMessageW(NULL, NULL, 0, 0, PM_QS_POSTMESSAGE | PM_NOREMOVE | PM_NOYIELD); -+ } - -- if (apt->filter) -+ if (com_peek_message(apt, &msg)) -+ { -+ if (msg.message == WM_QUIT) - { -- PENDINGTYPE pendingtype = tlsdata->pending_call_count_server ? PENDINGTYPE_NESTED : PENDINGTYPE_TOPLEVEL; -- DWORD be_handled = IMessageFilter_MessagePending(apt->filter, 0 /* FIXME */, now - start_time, pendingtype); -- -- TRACE("IMessageFilter_MessagePending returned %ld\n", be_handled); -- -- switch (be_handled) -- { -- case PENDINGMSG_CANCELCALL: -- WARN("call canceled\n"); -- hr = RPC_E_CALL_CANCELED; -- break; -- case PENDINGMSG_WAITNOPROCESS: -- case PENDINGMSG_WAITDEFPROCESS: -- default: -- /* FIXME: MSDN is very vague about the difference -- * between WAITNOPROCESS and WAITDEFPROCESS - there -- * appears to be none, so it is possibly a left-over -- * from the 16-bit world. */ -- break; -- } -+ TRACE("Received WM_QUIT message\n"); -+ quit.post = TRUE; -+ quit.code = msg.wParam; - } -- -- if (!apt->win) -+ else - { -- /* If window is NULL on apartment, peek at messages so that it will not trigger -- * MsgWaitForMultipleObjects next time. */ -- PeekMessageW(NULL, NULL, 0, 0, PM_QS_POSTMESSAGE | PM_NOREMOVE | PM_NOYIELD); -+ TRACE("Received message whilst waiting for RPC: 0x%04x\n", msg.message); -+ TranslateMessage(&msg); -+ DispatchMessageW(&msg); -+ } -+ } -+ else -+ { -+ DWORD now = GetTickCount(); -+ if (now - start_time > timeout) -+ { -+ /* res really is WAIT_TIMEOUT (not just from the dwMilliseconds=0 polling of handles) */ -+ break; - } - -- /* Some apps (e.g. Visio 2010) don't handle WM_PAINT properly and loop forever, -- * so after processing 100 messages we go back to checking the wait handles */ -- while (msg_count++ < 100 && com_peek_message(apt, &msg)) -+ /* not done, no messages pending, sleep for the remaining time (or until something happens) */ -+ res = MsgWaitForMultipleObjectsEx(handle_count, handles, -+ timeout == INFINITE ? INFINITE : start_time + timeout - now, -+ QS_SENDMESSAGE | QS_ALLPOSTMESSAGE | QS_PAINT, wait_flags); -+ -+ if (res == WAIT_OBJECT_0 + handle_count) /* messages available */ - { -- if (msg.message == WM_QUIT) -- { -- TRACE("Received WM_QUIT message\n"); -- quit.post = TRUE; -- quit.code = msg.wParam; -- } -- else -+ /* call message filter */ -+ -+ if (apt->filter) - { -- TRACE("Received message whilst waiting for RPC: 0x%04x\n", msg.message); -- TranslateMessage(&msg); -- DispatchMessageW(&msg); -+ PENDINGTYPE pendingtype = tlsdata->pending_call_count_server ? PENDINGTYPE_NESTED : PENDINGTYPE_TOPLEVEL; -+ DWORD be_handled = IMessageFilter_MessagePending(apt->filter, 0 /* FIXME */, now - start_time, pendingtype); -+ -+ TRACE("IMessageFilter_MessagePending returned %d\n", be_handled); -+ -+ switch (be_handled) -+ { -+ case PENDINGMSG_CANCELCALL: -+ WARN("call canceled\n"); -+ hr = RPC_E_CALL_CANCELED; -+ goto done; -+ break; -+ case PENDINGMSG_WAITNOPROCESS: -+ case PENDINGMSG_WAITDEFPROCESS: -+ default: -+ /* FIXME: MSDN is very vague about the difference -+ * between WAITNOPROCESS and WAITDEFPROCESS - there -+ * appears to be none, so it is possibly a left-over -+ * from the 16-bit world. */ -+ break; -+ } - } - } -- continue; -+ else -+ { -+ break; -+ } - } - } -- else -- { -- TRACE("Waiting for rpc completion\n"); -+ } -+ else -+ { -+ TRACE("Waiting for rpc completion\n"); - -- res = WaitForMultipleObjectsEx(handle_count, handles, !!(flags & COWAIT_WAITALL), -- (timeout == INFINITE) ? INFINITE : start_time + timeout - now, !!(flags & COWAIT_ALERTABLE)); -- } -+ res = WaitForMultipleObjectsEx(handle_count, handles, !!(flags & COWAIT_WAITALL), -+ timeout, !!(flags & COWAIT_ALERTABLE)); -+ } - -- switch (res) -- { -- case WAIT_TIMEOUT: -- hr = RPC_S_CALLPENDING; -- break; -- case WAIT_FAILED: -- hr = HRESULT_FROM_WIN32(GetLastError()); -- break; -- default: -- *index = res; -- break; -- } -+ switch (res) -+ { -+ case WAIT_TIMEOUT: -+ hr = RPC_S_CALLPENDING; -+ break; -+ case WAIT_FAILED: -+ hr = HRESULT_FROM_WIN32(GetLastError()); -+ break; -+ default: -+ hr = S_OK; -+ *index = res; - break; - } -+ -+done: - if (quit.post) PostQuitMessage(quit.code); - - TRACE("-- %#lx\n", hr); -diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c -index 11111111111..11111111111 100644 ---- a/dlls/ole32/tests/compobj.c -+++ b/dlls/ole32/tests/compobj.c -@@ -975,6 +975,16 @@ static DWORD WINAPI MessageFilter_MessagePending( - return PENDINGMSG_WAITNOPROCESS; - } - -+static DWORD WINAPI MessageFilter_MessagePending_cancel( -+ IMessageFilter *iface, -+ HTASK threadIDCallee, -+ DWORD dwTickCount, -+ DWORD dwPendingType) -+{ -+ trace("MessagePending(cancel)\n"); -+ return PENDINGMSG_CANCELCALL; -+} -+ - static const IMessageFilterVtbl MessageFilter_Vtbl = - { - MessageFilter_QueryInterface, -@@ -987,6 +997,18 @@ static const IMessageFilterVtbl MessageFilter_Vtbl = - - static IMessageFilter MessageFilter = { &MessageFilter_Vtbl }; - -+static const IMessageFilterVtbl MessageFilter_Vtbl_cancel = -+{ -+ MessageFilter_QueryInterface, -+ MessageFilter_AddRef, -+ MessageFilter_Release, -+ MessageFilter_HandleInComingCall, -+ MessageFilter_RetryRejectedCall, -+ MessageFilter_MessagePending_cancel -+}; -+ -+static IMessageFilter MessageFilter_cancel = { &MessageFilter_Vtbl_cancel }; -+ - static void test_CoRegisterMessageFilter(void) - { - HRESULT hr; -@@ -2611,6 +2633,22 @@ static DWORD CALLBACK post_message_thread(LPVOID arg) - return 0; - } - -+static DWORD CALLBACK post_input_later_thread(LPVOID arg) -+{ -+ HWND hWnd = arg; -+ Sleep(50); -+ PostMessageA(hWnd, WM_CHAR, VK_ESCAPE, 0); -+ return 0; -+} -+ -+static DWORD CALLBACK post_dde_later_thread(LPVOID arg) -+{ -+ HWND hWnd = arg; -+ Sleep(50); -+ PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); -+ return 0; -+} -+ - static const char cls_name[] = "cowait_test_class"; - - static UINT cowait_msgs[100], cowait_msgs_first, cowait_msgs_last; -@@ -2668,6 +2706,18 @@ static LRESULT CALLBACK cowait_window_proc(HWND hwnd, UINT msg, WPARAM wparam, L - cowait_msgs[cowait_msgs_last++] = msg; - if(msg == WM_DDE_FIRST) - return 6; -+ if(msg == WM_DDE_EXECUTE && lparam) -+ { -+ const char* command = (const char *)GlobalLock((HGLOBAL)lparam); -+ if(strcmp(command,"[apc]") == 0) -+ QueueUserAPC(apc_test_proc, GetCurrentThread(), 0); -+ else if(strcmp(command,"[postmessage]") == 0) -+ PostMessageA(hwnd,msg,wparam,lparam); /* post the same message again (trigges livelock) */ -+ else if(strcmp(command,"[semaphore]") == 0) -+ ReleaseSemaphore(GetPropA(hwnd,"semaphore"), 1, NULL); -+ GlobalUnlock((HGLOBAL)lparam); -+ return 0; -+ } - return DefWindowProcA(hwnd, msg, wparam, lparam); - } - -@@ -2749,6 +2799,27 @@ static DWORD CALLBACK test_CoWaitForMultipleHandles_thread(LPVOID arg) - success = PeekMessageA(&msg, NULL, uMSG, uMSG, PM_REMOVE); - ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); - -+ hr = CoRegisterMessageFilter(&MessageFilter_cancel, NULL); -+ ok(hr == S_OK, "CoRegisterMessageFilter failed: %08x\n", hr); -+ -+ /* a message which arrives during the wait calls IMessageFilter::PendingMessage, -+ * which can cancel the wait (without pumping the message) */ -+ thread = CreateThread(NULL, 0, post_input_later_thread, hWnd, 0, &tid); -+ hr = CoWaitForMultipleHandles(0, 200, 2, handles, &index); -+ ok(hr == RPC_E_CALL_CANCELED, "expected RPC_E_CALL_CANCELED, got 0x%08x\n", hr); -+ success = PeekMessageA(&msg, hWnd, WM_CHAR, WM_CHAR, PM_REMOVE); -+ ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); -+ CloseHandle(thread); -+ -+ /* DDE/RPC messages shouldn't go to IMessageFilter::PendingMessage */ -+ thread = CreateThread(NULL, 0, post_dde_later_thread, hWnd, 0, &tid); -+ hr = CoWaitForMultipleHandles(0, 200, 2, handles, &index); -+ todo_wine ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); -+ CloseHandle(thread); -+ -+ hr = CoRegisterMessageFilter(NULL, NULL); -+ ok(hr == S_OK, "CoRegisterMessageFilter failed: %08x\n", hr); -+ - DestroyWindow(hWnd); - CoUninitialize(); - -@@ -2788,6 +2859,15 @@ static DWORD CALLBACK test_CoWaitForMultipleHandles_thread(LPVOID arg) - return 0; - } - -+static HGLOBAL globalalloc_string(const char *s) { -+ UINT len = strlen(s); -+ HGLOBAL ret = GlobalAlloc(GMEM_FIXED,len+1); -+ void *ptr = GlobalLock(ret); -+ strcpy(ptr,s); -+ GlobalUnlock(ret); -+ return ret; -+} -+ - static void test_CoWaitForMultipleHandles(void) - { - HANDLE handles[2], thread; -@@ -2797,6 +2877,10 @@ static void test_CoWaitForMultipleHandles(void) - HRESULT hr; - HWND hWnd; - MSG msg; -+ HGLOBAL execute_apc = globalalloc_string("[apc]"); -+ HGLOBAL execute_postmessage = globalalloc_string("[postmessage]"); -+ HGLOBAL execute_semaphore = globalalloc_string("[semaphore]"); -+ DWORD start_time; - - hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - ok(hr == S_OK, "CoInitializeEx failed with error 0x%08lx\n", hr); -@@ -2819,6 +2903,8 @@ static void test_CoWaitForMultipleHandles(void) - handles[1] = CreateSemaphoreA(NULL, 1, 1, NULL); - ok(handles[1] != 0, "CreateSemaphoreA failed %lu\n", GetLastError()); - -+ SetPropA(hWnd,"semaphore",handles[0]); -+ - /* test without flags */ - - PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); -@@ -2867,6 +2953,31 @@ static void test_CoWaitForMultipleHandles(void) - success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); - ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n"); - -+ /* test CoWaitForMultipleHandles stops pumping messages as soon as its handles are signaled */ -+ index = 0xdeadbeef; -+ PostMessageA(hWnd, WM_DDE_EXECUTE, 0, (LPARAM)execute_semaphore); -+ PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); -+ hr = CoWaitForMultipleHandles(0, 50, 1, handles, &index); -+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); -+ ok(index == 0, "expected index 0, got %u\n", index); -+ cowait_msgs_expect_queued(hWnd,WM_DDE_FIRST); /* WM_DDE_EXECUTE already pumped*/ -+ success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE); -+ ok(!success, "CoWaitForMultipleHandles didn't pump enough messages\n"); -+ -+ /* test CoWaitForMultipleHandles will keep pumping even beyond timeout if the queue -+ * still has messages (e.g. pumping messages just posts more mesages), -+ * but will still exit if the handles handles become signaled */ -+ index = 0xdeadbeef; -+ PostMessageA(hWnd, WM_DDE_EXECUTE, 0, (LPARAM)execute_postmessage); -+ start_time = GetTickCount(); -+ thread = CreateThread(NULL, 0, release_semaphore_thread, handles[0], 0, &tid); -+ hr = CoWaitForMultipleHandles(0, 50, 1, handles, &index); -+ ok(GetTickCount() - start_time >= 200, "CoWaitForMultipleHandles exited too soon\n"); -+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); -+ cowait_msgs_expect_queued(hWnd,WM_DDE_EXECUTE); /* each pumped execute_postmessage added one more back */ -+ success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE); -+ ok(!success, "CoWaitForMultipleHandles didn't pump enough messages\n"); -+ - /* test PostMessageA/SendMessageA from a different thread */ - - index = 0xdeadbeef; -@@ -2914,6 +3025,45 @@ static void test_CoWaitForMultipleHandles(void) - success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); - ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n"); - -+ ReleaseSemaphore(handles[0], 1, NULL); -+ -+ /* COWAIT_ALL will get time out even if the handles became signaled while it waits -+ * in MsgWaitForMultipleObjects(...,MWIO_WAITALL), as it demands a posted message too */ -+ index = 0xdeadbeef; -+ thread = CreateThread(NULL, 0, release_semaphore_thread, handles[1], 0, &tid); -+ hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 500, 2, handles, &index); -+ ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr); -+ /* but will succeed (without any further wait time) if the handles are avilable right away -+ * i.e. that it checks the handles first before calling MsgWaitForMultipleObjects */ -+ hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 0, 2, handles, &index); -+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); -+ ok(index == 0, "expected index 0, got %u\n", index); -+ -+ ReleaseSemaphore(handles[1], 1, NULL); -+ -+ /* COWAIT_ALL will pump message which are already in the queue, -+ * (but no longer QS_ALLPOSTMESSAGE), before blocking in MsgWaitForMultipleObjectsEx */ -+ index = 0xdeadbeef; -+ PostMessageA(hWnd, WM_DDE_EXECUTE, 0, (LPARAM)execute_semaphore); -+ PeekMessageA(&msg, hWnd, 0, 0, PM_NOREMOVE); // clear QS_ALLPOSTMESSAGE -+ hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 50, 1, handles, &index); -+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); -+ ok(index == 0, "expected index 0, got %u\n", index); -+ success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); -+ ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n"); -+ -+ ReleaseSemaphore(handles[1], 1, NULL); -+ -+ /* test early completion (rather than blocking in MsgWaitForMultipleObjectsEx again) -+ * if pumping a message results in all handles becoming signaled) */ -+ index = 0xdeadbeef; -+ PostMessageA(hWnd, WM_DDE_EXECUTE, 0, (LPARAM)execute_semaphore); -+ hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 50, 2, handles, &index); -+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); -+ ok(index == 0, "expected index 0, got %u\n", index); -+ success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); -+ ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n"); -+ - ReleaseSemaphore(handles[0], 1, NULL); - ReleaseSemaphore(handles[1], 1, NULL); - -@@ -2953,6 +3103,16 @@ static void test_CoWaitForMultipleHandles(void) - success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); - ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n"); - -+ index = 0xdeadbeef; -+ PostMessageA(hWnd, WM_DDE_EXECUTE, 0, (LPARAM)execute_apc); -+ PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); -+ hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 1, handles, &index); -+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); -+ ok(index == WAIT_IO_COMPLETION, "expected index WAIT_IO_COMPLETION, got %u\n", index); -+ cowait_msgs_expect_queued(hWnd,WM_DDE_FIRST); /* WM_DDE_EXECUTE already pumped*/ -+ success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE); -+ ok(!success, "CoWaitForMultipleHandles didn't pump enough messages\n"); -+ - /* test with COWAIT_INPUTAVAILABLE (semaphores are still locked) */ - - index = 0xdeadbeef; -@@ -3165,6 +3325,10 @@ static void test_CoWaitForMultipleHandles(void) - - CoUninitialize(); - -+ RemovePropA(hWnd,"semaphore"); -+ GlobalFree(execute_apc); -+ GlobalFree(execute_postmessage); -+ GlobalFree(execute_semaphore); - CloseHandle(handles[0]); - CloseHandle(handles[1]); - DestroyWindow(hWnd); - diff --git a/0013-server-optimization/0001-misc/ps0052-mountmgr-Add-SCSI-addresses-of-udisks2-devices-to-.patch b/0013-server-optimization/0001-misc/ps0052-mountmgr-Add-SCSI-addresses-of-udisks2-devices-to-.patch deleted file mode 100644 index 1db6ca0..0000000 --- a/0013-server-optimization/0001-misc/ps0052-mountmgr-Add-SCSI-addresses-of-udisks2-devices-to-.patch +++ /dev/null @@ -1,123 +0,0 @@ -From: Esme Povirk -Subject: [PATCH] mountmgr: Add SCSI addresses of udisks2 devices to the registry. -Message-Id: <20201107171450.2377-1-esme@codeweavers.com> -Date: Sat, 7 Nov 2020 11:14:50 -0600 - -Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49788 -Signed-off-by: Esme Povirk ---- - dlls/mountmgr.sys/dbus.c | 63 +++++++++++++++++++++++++++++++++++++--- - 1 file changed, 59 insertions(+), 4 deletions(-) - -diff --git a/dlls/mountmgr.sys/dbus.c b/dlls/mountmgr.sys/dbus.c -index 11111111111..11111111111 100644 ---- a/dlls/mountmgr.sys/dbus.c -+++ b/dlls/mountmgr.sys/dbus.c -@@ -336,7 +336,8 @@ static const char *udisks2_string_from_array( DBusMessageIter *iter ) - - /* find the drive entry in the dictionary and get its parameters */ - static void udisks2_get_drive_info( const char *drive_name, DBusMessageIter *dict, -- enum device_type *drive_type, int *removable, const char **serial ) -+ enum device_type *drive_type, int *removable, const char **serial, -+ int *optical, const char **model ) - { - DBusMessageIter iter, drive, variant; - const char *name; -@@ -356,11 +357,59 @@ static void udisks2_get_drive_info( const char *drive_name, DBusMessageIter *dic - *drive_type = udisks_parse_media_compatibility( &variant ); - else if (!strcmp( name, "Id" )) - p_dbus_message_iter_get_basic( &variant, serial ); -+ else if (!strcmp( name, "Optical" )) -+ p_dbus_message_iter_get_basic( &variant, optical ); -+ else if (!strcmp( name, "Model" )) -+ p_dbus_message_iter_get_basic( &variant, model ); - } - } - } - } - -+static void udisks2_get_scsi_info( const char *unix_device, int optical, -+ const char *model, struct scsi_info *scsi_info ) -+{ -+ WCHAR name[MAX_PATH] = {'\\','?','?','\\','u','n','i','x',0}; -+ UNICODE_STRING string; -+ OBJECT_ATTRIBUTES attr = {sizeof(attr)}; -+ IO_STATUS_BLOCK iosb; -+ NTSTATUS status; -+ HANDLE handle; -+ DWORD len; -+ -+ if (!unix_device) -+ return; -+ -+ len = ntdll_umbstowcs( unix_device, strlen( unix_device ) + 1, &name[8], ARRAY_SIZE(name) - 8 ); -+ if (len >= ARRAY_SIZE(name) - 8) -+ { -+ ERR("Failed to convert %s to NT, path too long\n", debugstr_a(unix_device)); -+ return; -+ } -+ -+ string.Buffer = name; -+ string.Length = len + 8; -+ string.MaximumLength = string.Length; -+ attr.ObjectName = &string; -+ status = NtCreateFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, -+ FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0 ); -+ if (!NT_SUCCESS(status)) -+ { -+ WARN("Failed to open %s, status %u\n", debugstr_a(unix_device), status); -+ return; -+ } -+ -+ if (NtDeviceIoControlFile( handle, 0, NULL, NULL, &iosb, IOCTL_SCSI_GET_ADDRESS, NULL, 0, &scsi_info->addr, sizeof(scsi_info->addr) )) -+ { -+ scsi_info->type = optical ? SCSI_CDROM_PERIPHERAL : SCSI_DISK_PERIPHERAL; -+ scsi_info->init_id = 255; /* FIXME */ -+ strcpy( scsi_info->driver, optical ? "atapi" : "WINE SCSI" ); /* FIXME */ -+ lstrcpynA( scsi_info->model, model, sizeof(scsi_info->model) ); -+ } -+ -+ NtClose( handle ); -+} -+ - static void udisks2_add_device( const char *udi, DBusMessageIter *dict, DBusMessageIter *block ) - { - DBusMessageIter iter, variant, paths, string; -@@ -370,9 +419,10 @@ static void udisks2_add_device( const char *udi, DBusMessageIter *dict, DBusMess - const char *drive = NULL; - const char *id = NULL; - const char *label = NULL; -+ const char *model = NULL; - GUID guid, *guid_ptr = NULL; - const char *iface, *name; -- int removable = FALSE; -+ int removable = FALSE, optical = FALSE; - enum device_type drive_type = DEVICE_UNKNOWN; - - while ((iface = udisks_next_dict_entry( block, &iter ))) -@@ -405,7 +455,7 @@ static void udisks2_add_device( const char *udi, DBusMessageIter *dict, DBusMess - else if (!strcmp( name, "Drive" )) - { - p_dbus_message_iter_get_basic( &variant, &drive ); -- udisks2_get_drive_info( drive, dict, &drive_type, &removable, &id ); -+ udisks2_get_drive_info( drive, dict, &drive_type, &removable, &id, &optical, &model ); - } - else if (!strcmp( name, "IdUUID" )) - { -@@ -439,7 +489,12 @@ static void udisks2_add_device( const char *udi, DBusMessageIter *dict, DBusMess - } - if (device) - { -- if (removable) queue_device_op( ADD_DOS_DEVICE, udi, device, mount_point, drive_type, guid_ptr, id, label, NULL ); -+ if (removable) -+ { -+ struct scsi_info scsi_info = {0}; -+ udisks2_get_scsi_info( device, optical, model, &scsi_info ); -+ queue_device_op( ADD_DOS_DEVICE, udi, device, mount_point, drive_type, guid_ptr, id, label, scsi_info.type ? &scsi_info : NULL ); -+ } - else if (guid_ptr) queue_device_op( ADD_VOLUME, udi, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr, id, label, NULL ); - } - } --- -0.0.0 - diff --git a/0013-server-optimization/0001-misc/ps0057-ntdll-Implement-dynamic-spinning.patch b/0013-server-optimization/0001-misc/ps0057-ntdll-Implement-dynamic-spinning.patch new file mode 100644 index 0000000..3580823 --- /dev/null +++ b/0013-server-optimization/0001-misc/ps0057-ntdll-Implement-dynamic-spinning.patch @@ -0,0 +1,121 @@ +From: William Horvath +Date: Sat, 7 Dec 2024 16:59:04 -0800 +Subject: [PATCH v2] ntdll: Implement dynamic spinning. + +Original by Jangwoon Kim: https://list.winehq.org/mailman3/hyperkitty/list/wine-devel@winehq.org/thread/K7KUZUHQQ43AA2M7SZOQWY3W5G45QCCY/#K7KUZUHQQ43AA2M7SZOQWY3W5G45QCCY + +Previously, InitializeCriticalSectionEx with +RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN worked as semi-stub. + +This patch implements dynamic spinning. +Specifically, 32th bit from the right (starting with zero index) +indicates whether it is dynamically spinning critical section. + +v2: Enable dynamic spinning by default on Windows >= 8, which seems to be what Windows does + (https://stackoverflow.com/questions/54765280/windows-critical-section-how-to-disable-spinning-completely) + - Default spincount of 256 if unspecified is just a random guess + - 4096 seems to be used by Windows (https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-initializecriticalsectionandspincount), + so that should be a safe maximum + +Co-authored-by: Jangwoong Kim <6812skiii@gmail.com> +--- + dlls/ntdll/sync.c | 54 ++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 46 insertions(+), 8 deletions(-) + +diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c +index 11111111111..11111111111 100644 +--- a/dlls/ntdll/sync.c ++++ b/dlls/ntdll/sync.c +@@ -42,6 +42,13 @@ + WINE_DEFAULT_DEBUG_CHANNEL(sync); + WINE_DECLARE_DEBUG_CHANNEL(relay); + ++#define IS_DYNAMIC_SPIN crit->SpinCount >> 31 == 1 ? TRUE : FALSE ++#define MAX_ADAPTIVE_SPIN_COUNT 4096 ++#define DEFAULT_ADAPTIVE_SPIN_COUNT 256 ++#ifndef min ++#define min(a,b) (((a) < (b)) ? (a) : (b)) ++#endif ++ + static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) + { + if (!timeout) return "(infinite)"; +@@ -220,7 +227,11 @@ NTSTATUS WINAPI RtlInitializeCriticalSectionAndSpinCount( RTL_CRITICAL_SECTION * + */ + NTSTATUS WINAPI RtlInitializeCriticalSectionEx( RTL_CRITICAL_SECTION *crit, ULONG spincount, ULONG flags ) + { +- if (flags & (RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN|RTL_CRITICAL_SECTION_FLAG_STATIC_INIT)) ++ if (NtCurrentTeb()->Peb->OSMajorVersion > 6 || ++ (NtCurrentTeb()->Peb->OSMajorVersion == 6 && NtCurrentTeb()->Peb->OSMinorVersion >= 2)) ++ flags |= RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN; ++ ++ if (flags & RTL_CRITICAL_SECTION_FLAG_STATIC_INIT) + FIXME("(%p,%lu,0x%08lx) semi-stub\n", crit, spincount, flags); + + /* FIXME: if RTL_CRITICAL_SECTION_FLAG_STATIC_INIT is given, we should use +@@ -250,8 +261,15 @@ NTSTATUS WINAPI RtlInitializeCriticalSectionEx( RTL_CRITICAL_SECTION *crit, ULON + crit->RecursionCount = 0; + crit->OwningThread = 0; + crit->LockSemaphore = 0; ++ spincount = spincount & ~0x80000000; + if (NtCurrentTeb()->Peb->NumberOfProcessors <= 1) spincount = 0; +- crit->SpinCount = spincount & ~0x80000000; ++ else if (flags & RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN) ++ { ++ spincount = min(spincount == 0 ? DEFAULT_ADAPTIVE_SPIN_COUNT : spincount, MAX_ADAPTIVE_SPIN_COUNT); ++ /* 31th bit (from right starting with 0) indicates whether it is dynamically spinning CS */ ++ spincount |= ((ULONG)1 << 31); ++ } ++ crit->SpinCount = spincount; + return STATUS_SUCCESS; + } + +@@ -353,19 +371,39 @@ NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) + */ + NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit ) + { +- if (crit->SpinCount) ++ if (crit->SpinCount & ~0x80000000) + { + ULONG count; + + if (RtlTryEnterCriticalSection( crit )) return STATUS_SUCCESS; +- for (count = crit->SpinCount; count > 0; count--) ++ if (IS_DYNAMIC_SPIN) + { +- if (crit->LockCount > 0) break; /* more than one waiter, don't bother spinning */ +- if (crit->LockCount == -1) /* try again */ ++ ULONG max_count = min(MAX_ADAPTIVE_SPIN_COUNT, (crit->SpinCount & ~0x80000000) * 2); ++ for (count = 0; count <= max_count; count++) + { +- if (InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1) goto done; ++ if (crit->LockCount == -1) ++ { ++ if (InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1) ++ { ++ crit->SpinCount += ((LONG)count - (LONG)(crit->SpinCount & ~0x80000000)) / 10; ++ goto done; ++ } ++ } ++ YieldProcessor(); ++ } ++ crit->SpinCount += ((LONG)count - (LONG)(crit->SpinCount & ~0x80000000)) / 10; ++ } ++ else ++ { ++ for (count = (crit->SpinCount & ~0x80000000); count > 0; count--) ++ { ++ if (crit->LockCount > 0) break; /* more than one waiter, don't bother spinning */ ++ if (crit->LockCount == -1) /* try again */ ++ { ++ if (InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1) goto done; ++ } ++ YieldProcessor(); + } +- YieldProcessor(); + } + } + +-- +0.0.0 + diff --git a/0013-server-optimization/0001-misc/ps0057-p0001-ntdll-Implement-dynamic-spinning.patch b/0013-server-optimization/0001-misc/ps0057-p0001-ntdll-Implement-dynamic-spinning.patch deleted file mode 100644 index 5b5e45a..0000000 --- a/0013-server-optimization/0001-misc/ps0057-p0001-ntdll-Implement-dynamic-spinning.patch +++ /dev/null @@ -1,112 +0,0 @@ -From: Jangwoong Kim <6812skiii@gmail.com> -Subject: [PATCH] ntdll: Implement dynamic spinning -Message-Id: <20210101134108.5112-1-6812skiii@gmail.com> -Date: Fri, 1 Jan 2021 22:41:08 +0900 - -Previously, InitialzeCriticalSectionEx with -RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN worked as semi-stub. - -This patch implements dynamic spinning. -Specifically, 32th bit from the right (starting with zero index) -indicates whether it is dynamically spinning critical section. - -Signed-off-by: Jangwoong Kim <6812skiii@gmail.com> ---- - dlls/ntdll/sync.c | 52 ++++++++++++++++++++++++++++++++++++++++------- - 1 file changed, 45 insertions(+), 7 deletions(-) - -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 11111111111..11111111111 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -45,6 +45,9 @@ static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) - return wine_dbgstr_longlong( timeout->QuadPart ); - } - -+#define MAX_ADAPTIVE_SPIN_COUNT 4000 -+#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -+ - /****************************************************************** - * RtlRunOnceInitialize (NTDLL.@) - */ -@@ -223,7 +226,7 @@ NTSTATUS WINAPI RtlInitializeCriticalSectionAndSpinCount( RTL_CRITICAL_SECTION * - */ - NTSTATUS WINAPI RtlInitializeCriticalSectionEx( RTL_CRITICAL_SECTION *crit, ULONG spincount, ULONG flags ) - { -- if (flags & (RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN|RTL_CRITICAL_SECTION_FLAG_STATIC_INIT)) -+ if (flags & RTL_CRITICAL_SECTION_FLAG_STATIC_INIT) - FIXME("(%p,%lu,0x%08lx) semi-stub\n", crit, spincount, flags); - - /* FIXME: if RTL_CRITICAL_SECTION_FLAG_STATIC_INIT is given, we should use -@@ -253,8 +256,15 @@ NTSTATUS WINAPI RtlInitializeCriticalSectionEx( RTL_CRITICAL_SECTION *crit, ULON - crit->RecursionCount = 0; - crit->OwningThread = 0; - crit->LockSemaphore = 0; -+ spincount = spincount & ~RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN; -+ if (flags & RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN) -+ { -+ spincount = MIN(spincount, MAX_ADAPTIVE_SPIN_COUNT); -+ /* RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN indicates whether it is a dynamically spinning CS */ -+ spincount |= RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN; -+ } - if (NtCurrentTeb()->Peb->NumberOfProcessors <= 1) spincount = 0; -- crit->SpinCount = spincount & ~0x80000000; -+ crit->SpinCount = spincount; - return STATUS_SUCCESS; - } - -@@ -357,17 +367,45 @@ NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit ) - { - if (crit->SpinCount) - { -+ ULONG spincount = *(volatile ULONG*)&crit->SpinCount; - ULONG count; - - if (RtlTryEnterCriticalSection( crit )) return STATUS_SUCCESS; -- for (count = crit->SpinCount; count > 0; count--) -+ if (spincount & RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN) - { -- if (crit->LockCount > 0) break; /* more than one waiter, don't bother spinning */ -- if (crit->LockCount == -1) /* try again */ -+ ULONG max_count; -+ LONG adjustment; -+ -+ spincount &= ~RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN; -+ max_count = MIN(spincount * 2, MAX_ADAPTIVE_SPIN_COUNT); -+ for (count = 0; count < max_count; count++) - { -- if (InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1) goto done; -+ if (crit->LockCount == -1 && InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1) -+ { -+ adjustment = (LONG)(count - spincount) / 10; -+ spincount = *(volatile ULONG*)&crit->SpinCount & ~RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN; -+ spincount += adjustment; -+ crit->SpinCount = (LONG)spincount < 0 ? 0 : MIN(spincount, MAX_ADAPTIVE_SPIN_COUNT); -+ goto done; -+ } -+ YieldProcessor(); -+ } -+ adjustment = (LONG)(count - spincount) / 10; -+ spincount = *(volatile ULONG*)&crit->SpinCount & ~RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN; -+ spincount += adjustment; -+ crit->SpinCount = (LONG)spincount < 0 ? 0 : MIN(spincount, MAX_ADAPTIVE_SPIN_COUNT); -+ } -+ else -+ { -+ for (count = spincount; count > 0; count--) -+ { -+ if (crit->LockCount > 0) break; /* more than one waiter, don't bother spinning */ -+ if (crit->LockCount == -1) /* try again */ -+ { -+ if (InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1) goto done; -+ } -+ YieldProcessor(); - } -- YieldProcessor(); - } - } - - --- -0.0.0 - diff --git a/0013-server-optimization/0001-misc/ps0057-p0002-enable-dynamic-spinning.patch b/0013-server-optimization/0001-misc/ps0057-p0002-enable-dynamic-spinning.patch deleted file mode 100644 index c29f9b0..0000000 --- a/0013-server-optimization/0001-misc/ps0057-p0002-enable-dynamic-spinning.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Torge Matthies -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 11111111111..11111111111 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -46,6 +46,7 @@ static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) - } - - #define MAX_ADAPTIVE_SPIN_COUNT 4000 -+#define DEFAULT_ADAPTIVE_SPIN_COUNT 2000 - #define MIN(a, b) (((a) < (b)) ? (a) : (b)) - - /****************************************************************** -@@ -229,6 +230,12 @@ NTSTATUS WINAPI RtlInitializeCriticalSectionEx( RTL_CRITICAL_SECTION *crit, ULON - if (flags & RTL_CRITICAL_SECTION_FLAG_STATIC_INIT) - FIXME("(%p,%lu,0x%08lx) semi-stub\n", crit, spincount, flags); - -+ if (!spincount) -+ { -+ flags |= RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN; -+ spincount = DEFAULT_ADAPTIVE_SPIN_COUNT; -+ } -+ - /* FIXME: if RTL_CRITICAL_SECTION_FLAG_STATIC_INIT is given, we should use - * memory from a static pool to hold the debug info. Then heap.c could pass - * this flag rather than initialising the process heap CS by hand. If this diff --git a/0013-server-optimization/0001-misc/ps0086-p0003-mountmgr.sys-Add-an-ioctl-to-directly-make-v.patch b/0013-server-optimization/0001-misc/ps0086-p0003-mountmgr.sys-Add-an-ioctl-to-directly-make-v.patch deleted file mode 100644 index 7539b65..0000000 --- a/0013-server-optimization/0001-misc/ps0086-p0003-mountmgr.sys-Add-an-ioctl-to-directly-make-v.patch +++ /dev/null @@ -1,281 +0,0 @@ -From: "Erich E. Hoover" -Subject: [PATCH 3/5] mountmgr.sys: Add an ioctl to directly make volume queries. -Message-Id: -Date: Thu, 18 Mar 2021 10:53:43 -0600 - -This patch adds a new ioctl similar to -IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE, but this version directly returns the -FILE_FS_*_INFORMATION from the mountmgr implementation instead of -returning properties of the mount point and relying on the caller to -interpret those properties correctly. - -Best, -Erich - -From 5354dedc85423ae46a582bb4af3661fc50d8e0fb Mon Sep 17 00:00:00 2001 -From: "Erich E. Hoover" -Date: Sun, 28 Feb 2021 11:21:06 -0700 -#Subject: mountmgr.sys: Add an ioctl to directly make volume queries. - -Signed-off-by: Erich E. Hoover ---- - dlls/mountmgr.sys/device.c | 102 +++++++++++++++++++++++------------ - dlls/mountmgr.sys/mountmgr.c | 11 ++++ - dlls/mountmgr.sys/mountmgr.h | 1 + - include/ddk/mountmgr.h | 10 ++++ - 4 files changed, 90 insertions(+), 34 deletions(-) - -diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c -index 11111111111..11111111111 100644 ---- a/dlls/mountmgr.sys/device.c -+++ b/dlls/mountmgr.sys/device.c -@@ -1630,32 +1630,18 @@ static NTSTATUS query_property( struct disk_device *device, IRP *irp ) - return status; - } - --static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp ) -+static NTSTATUS WINAPI fill_volume_info( FS_INFORMATION_CLASS info_class, enum fs_type fs_type, -+ DWORD serial, WCHAR *label, char *unix_mount, void *buff, -+ ULONG length, ULONG_PTR *size ) - { -- IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); -- int info_class = irpsp->Parameters.QueryVolume.FsInformationClass; -- ULONG length = irpsp->Parameters.QueryVolume.Length; -- struct disk_device *dev = device->DeviceExtension; -- PIO_STATUS_BLOCK io = &irp->IoStatus; -- struct volume *volume; - NTSTATUS status; - -- TRACE( "volume query %x length %lu\n", info_class, length ); -- -- EnterCriticalSection( &device_section ); -- volume = dev->volume; -- if (!volume) -- { -- status = STATUS_BAD_DEVICE_TYPE; -- goto done; -- } -- - switch(info_class) - { - case FileFsVolumeInformation: - { - -- FILE_FS_VOLUME_INFORMATION *info = irp->AssociatedIrp.SystemBuffer; -+ FILE_FS_VOLUME_INFORMATION *info = buff; - - if (length < sizeof(FILE_FS_VOLUME_INFORMATION)) - { -@@ -1664,21 +1650,21 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp ) - } - - info->VolumeCreationTime.QuadPart = 0; /* FIXME */ -- info->VolumeSerialNumber = volume->serial; -- info->VolumeLabelLength = min( lstrlenW(volume->label) * sizeof(WCHAR), -+ info->VolumeSerialNumber = serial; -+ info->VolumeLabelLength = min( lstrlenW(label) * sizeof(WCHAR), - length - offsetof( FILE_FS_VOLUME_INFORMATION, VolumeLabel ) ); -- info->SupportsObjects = (get_mountmgr_fs_type(volume->fs_type) == MOUNTMGR_FS_TYPE_NTFS); -- memcpy( info->VolumeLabel, volume->label, info->VolumeLabelLength ); -+ info->SupportsObjects = (get_mountmgr_fs_type(fs_type) == MOUNTMGR_FS_TYPE_NTFS); -+ memcpy( info->VolumeLabel, label, info->VolumeLabelLength ); - -- io->Information = offsetof( FILE_FS_VOLUME_INFORMATION, VolumeLabel ) + info->VolumeLabelLength; -+ *size = offsetof( FILE_FS_VOLUME_INFORMATION, VolumeLabel ) + info->VolumeLabelLength; - status = STATUS_SUCCESS; - break; - } - case FileFsSizeInformation: - { -- FILE_FS_SIZE_INFORMATION *info = irp->AssociatedIrp.SystemBuffer; -+ FILE_FS_SIZE_INFORMATION *info = buff; - struct size_info size_info = { 0, 0, 0, 0, 0 }; -- struct get_volume_size_info_params params = { dev->unix_mount, &size_info }; -+ struct get_volume_size_info_params params = { unix_mount, &size_info }; - - if (length < sizeof(FILE_FS_SIZE_INFORMATION)) - { -@@ -1692,7 +1678,7 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp ) - info->AvailableAllocationUnits.QuadPart = size_info.caller_available_allocation_units; - info->SectorsPerAllocationUnit = size_info.sectors_per_allocation_unit; - info->BytesPerSector = size_info.bytes_per_sector; -- io->Information = sizeof(*info); -+ *size = sizeof(*info); - status = STATUS_SUCCESS; - } - -@@ -1700,8 +1686,8 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp ) - } - case FileFsAttributeInformation: - { -- FILE_FS_ATTRIBUTE_INFORMATION *info = irp->AssociatedIrp.SystemBuffer; -- enum mountmgr_fs_type fs_type = get_mountmgr_fs_type(volume->fs_type); -+ FILE_FS_ATTRIBUTE_INFORMATION *info = buff; -+ enum mountmgr_fs_type fs_type = get_mountmgr_fs_type(fs_type); - const WCHAR *fsname; - - if (length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) -@@ -1741,15 +1727,15 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp ) - } - info->FileSystemNameLength = min( wcslen(fsname) * sizeof(WCHAR), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) ); - memcpy(info->FileSystemName, fsname, info->FileSystemNameLength); -- io->Information = offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) + info->FileSystemNameLength; -+ *size = offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) + info->FileSystemNameLength; - status = STATUS_SUCCESS; - break; - } - case FileFsFullSizeInformation: - { -- FILE_FS_FULL_SIZE_INFORMATION *info = irp->AssociatedIrp.SystemBuffer; -+ FILE_FS_FULL_SIZE_INFORMATION *info = buff; - struct size_info size_info = { 0, 0, 0, 0, 0 }; -- struct get_volume_size_info_params params = { dev->unix_mount, &size_info }; -+ struct get_volume_size_info_params params = { unix_mount, &size_info }; - - if (length < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) - { -@@ -1764,7 +1750,7 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp ) - info->ActualAvailableAllocationUnits.QuadPart = size_info.actual_available_allocation_units; - info->SectorsPerAllocationUnit = size_info.sectors_per_allocation_unit; - info->BytesPerSector = size_info.bytes_per_sector; -- io->Information = sizeof(*info); -+ *size = sizeof(*info); - status = STATUS_SUCCESS; - } - -@@ -1772,12 +1758,60 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp ) - } - - default: -- FIXME("Unsupported volume query %x\n", irpsp->Parameters.QueryVolume.FsInformationClass); -+ FIXME("Unsupported volume query %x\n", info_class); - status = STATUS_NOT_SUPPORTED; - break; - } -+ return status; -+} -+ -+/* implementation of IOCTL_MOUNTMGR_QUERY_VOLUME */ -+NTSTATUS query_volume( void *buff, SIZE_T insize, SIZE_T outsize, IO_STATUS_BLOCK *iosb ) -+{ -+ const struct mountmgr_volume *input = buff; -+ FS_INFORMATION_CLASS info_class = input->info_class; -+ NTSTATUS status = STATUS_NO_SUCH_DEVICE; -+ int letter = towlower( input->letter ); -+ struct volume *volume; -+ -+ if (letter && (letter < 'a' || letter > 'z')) return STATUS_INVALID_PARAMETER; -+ -+ EnterCriticalSection( &device_section ); -+ if (letter) -+ volume = find_volume_by_letter( letter - 'a' ); -+ else -+ volume = find_volume_by_unixdev( input->unix_dev ); -+ if (volume) -+ { -+ char *unix_mount = volume->device ? volume->device->unix_mount : NULL; -+ status = fill_volume_info( info_class, volume->fs_type, volume->serial, volume->label, -+ unix_mount, buff, outsize, &iosb->Information ); -+ release_volume( volume ); -+ } -+ LeaveCriticalSection( &device_section ); -+ -+ return status; -+} -+ -+static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp ) -+{ -+ IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); -+ int info_class = irpsp->Parameters.QueryVolume.FsInformationClass; -+ ULONG length = irpsp->Parameters.QueryVolume.Length; -+ struct disk_device *dev = device->DeviceExtension; -+ void *buff = irp->AssociatedIrp.SystemBuffer; -+ NTSTATUS status = STATUS_BAD_DEVICE_TYPE; -+ PIO_STATUS_BLOCK io = &irp->IoStatus; -+ struct volume *volume; -+ -+ TRACE( "volume query %x length %u\n", info_class, length ); -+ -+ EnterCriticalSection( &device_section ); -+ volume = dev->volume; -+ if (volume) -+ status = fill_volume_info( info_class, volume->fs_type, volume->serial, volume->label, -+ dev->unix_mount, buff, length, &io->Information ); - --done: - io->Status = status; - LeaveCriticalSection( &device_section ); - IoCompleteRequest( irp, IO_NO_INCREMENT ); -diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c -index 11111111111..11111111111 100644 ---- a/dlls/mountmgr.sys/mountmgr.c -+++ b/dlls/mountmgr.sys/mountmgr.c -@@ -525,6 +525,17 @@ static NTSTATUS WINAPI mountmgr_ioctl( DEVICE_OBJECT *device, IRP *irp ) - irpsp->Parameters.DeviceIoControl.OutputBufferLength, - &irp->IoStatus ); - break; -+ case IOCTL_MOUNTMGR_QUERY_VOLUME: -+ if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(struct mountmgr_volume)) -+ { -+ status = STATUS_INVALID_PARAMETER; -+ break; -+ } -+ status = query_volume( irp->AssociatedIrp.SystemBuffer, -+ irpsp->Parameters.DeviceIoControl.InputBufferLength, -+ irpsp->Parameters.DeviceIoControl.OutputBufferLength, -+ &irp->IoStatus ); -+ break; - case IOCTL_MOUNTMGR_QUERY_DHCP_REQUEST_PARAMS: - if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(struct mountmgr_dhcp_request_params)) - { -diff --git a/dlls/mountmgr.sys/mountmgr.h b/dlls/mountmgr.sys/mountmgr.h -index 11111111111..11111111111 100644 ---- a/dlls/mountmgr.sys/mountmgr.h -+++ b/dlls/mountmgr.sys/mountmgr.h -@@ -50,6 +50,7 @@ enum device_type - DEVICE_RAMDISK - }; - -+extern NTSTATUS query_volume( void *buff, SIZE_T insize, SIZE_T outsize, IO_STATUS_BLOCK *iosb ); - extern NTSTATUS WINAPI harddisk_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ); - extern NTSTATUS WINAPI serial_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ); - extern NTSTATUS WINAPI parallel_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ); -diff --git a/include/ddk/mountmgr.h b/include/ddk/mountmgr.h -index 11111111111..11111111111 100644 ---- a/include/ddk/mountmgr.h -+++ b/include/ddk/mountmgr.h -@@ -23,6 +23,8 @@ - - #include "ifdef.h" - -+#include "winternl.h" -+ - #define MOUNTMGRCONTROLTYPE ((ULONG)'m') - #define MOUNTDEVCONTROLTYPE ((ULONG)'M') - -@@ -55,6 +57,7 @@ static const WCHAR MOUNTMGR_DOS_DEVICE_NAME[] = {'\\','\\','.','\\','M','o','u', - #define IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE CTL_CODE(MOUNTMGRCONTROLTYPE, 33, METHOD_BUFFERED, FILE_READ_ACCESS) - #define IOCTL_MOUNTMGR_DEFINE_SHELL_FOLDER CTL_CODE(MOUNTMGRCONTROLTYPE, 34, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) - #define IOCTL_MOUNTMGR_QUERY_SHELL_FOLDER CTL_CODE(MOUNTMGRCONTROLTYPE, 35, METHOD_BUFFERED, FILE_READ_ACCESS) -+#define IOCTL_MOUNTMGR_QUERY_VOLUME CTL_CODE(MOUNTMGRCONTROLTYPE, 34, METHOD_BUFFERED, FILE_READ_ACCESS) - - enum mountmgr_fs_type - { -@@ -86,6 +89,13 @@ struct mountmgr_shell_folder - ULONG symlink_offset; - }; - -+struct mountmgr_volume -+{ -+ FS_INFORMATION_CLASS info_class; -+ ULONGLONG unix_dev; -+ WCHAR letter; -+}; -+ - #define IOCTL_MOUNTMGR_READ_CREDENTIAL CTL_CODE(MOUNTMGRCONTROLTYPE, 48, METHOD_BUFFERED, FILE_READ_ACCESS) - #define IOCTL_MOUNTMGR_WRITE_CREDENTIAL CTL_CODE(MOUNTMGRCONTROLTYPE, 49, METHOD_BUFFERED, FILE_WRITE_ACCESS) - #define IOCTL_MOUNTMGR_DELETE_CREDENTIAL CTL_CODE(MOUNTMGRCONTROLTYPE, 50, METHOD_BUFFERED, FILE_WRITE_ACCESS) - --- -0.0.0 - diff --git a/0013-server-optimization/0001-misc/ps0086-p0004-mountmgr.sys-Add-the-ability-to-query-filesy.patch b/0013-server-optimization/0001-misc/ps0086-p0004-mountmgr.sys-Add-the-ability-to-query-filesy.patch deleted file mode 100644 index 7bc421c..0000000 --- a/0013-server-optimization/0001-misc/ps0086-p0004-mountmgr.sys-Add-the-ability-to-query-filesy.patch +++ /dev/null @@ -1,213 +0,0 @@ -From: "Erich E. Hoover" -Subject: [PATCH 4/5] mountmgr.sys: Add the ability to query filesystem attributes on a file handle. -Message-Id: -Date: Thu, 18 Mar 2021 10:54:04 -0600 - -This patch adds capability to the new IOCTL_MOUNTMGR_QUERY_VOLUME -ioctl to be able to return volume information on a file handle. This -code represents the "fallback" case when standard volume information -is unavailable (for more details see the code removed from -dlls/ntdll/unix/file.c in patch 5 in the case where -get_mountmgr_fs_info() fails). - -Best, -Erich - -From 05fdc0539f5a5ecc5f8b690ef332c96c1ea64bb7 Mon Sep 17 00:00:00 2001 -From: "Erich E. Hoover" -Date: Sun, 28 Feb 2021 11:44:43 -0700 -#Subject: mountmgr.sys: Add the ability to query filesystem attributes on a - file handle. - -Signed-off-by: Erich E. Hoover ---- - dlls/mountmgr.sys/device.c | 31 ++++++++++++++++-------- - dlls/mountmgr.sys/mountmgr.h | 10 ++++++++ - dlls/mountmgr.sys/unixlib.c | 46 ++++++++++++++++++++++++++++++++++++ - dlls/mountmgr.sys/unixlib.h | 7 ++++++ - include/ddk/mountmgr.h | 2 ++ - 5 files changed, 86 insertions(+), 10 deletions(-) - -diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c -index 11111111111..11111111111 100644 ---- a/dlls/mountmgr.sys/device.c -+++ b/dlls/mountmgr.sys/device.c -@@ -51,16 +51,6 @@ static const WCHAR drive_types[][8] = - L"ramdisk" /* DEVICE_RAMDISK */ - }; - --enum fs_type --{ -- FS_ERROR, /* error accessing the device */ -- FS_UNKNOWN, /* unknown file system */ -- FS_FAT1216, -- FS_FAT32, -- FS_ISO9660, -- FS_UDF /* For reference [E] = Ecma-167.pdf, [U] = udf260.pdf */ --}; -- - struct disk_device - { - enum device_type type; /* drive type */ -@@ -1790,6 +1780,27 @@ NTSTATUS query_volume( void *buff, SIZE_T insize, SIZE_T outsize, IO_STATUS_BLOC - } - LeaveCriticalSection( &device_section ); - -+ if (!volume && input->info_class == FileFsAttributeInformation) -+ { -+ enum fs_type fs_type = FS_UNKNOWN; -+ HANDLE hProcess, handle; -+ BOOL ret; -+ struct get_handle_fs_type_params params = { 0, &fs_type }; -+ -+ if (!(hProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, input->process ))) -+ return status; -+ ret = DuplicateHandle( hProcess, input->handle, GetCurrentProcess(), &handle, 0, FALSE, -+ DUPLICATE_SAME_ACCESS ); -+ CloseHandle( hProcess ); -+ if (!ret) return status; -+ params.handle = handle; -+ status = MOUNTMGR_CALL( get_handle_fs_type, ¶ms ); -+ CloseHandle( handle ); -+ if (status) return status; -+ status = fill_volume_info( info_class, fs_type, 0, NULL, NULL, buff, outsize, -+ &iosb->Information ); -+ } -+ - return status; - } - -diff --git a/dlls/mountmgr.sys/mountmgr.h b/dlls/mountmgr.sys/mountmgr.h -index 11111111111..11111111111 100644 ---- a/dlls/mountmgr.sys/mountmgr.h -+++ b/dlls/mountmgr.sys/mountmgr.h -@@ -36,6 +36,16 @@ - #define WINE_MOUNTMGR_EXTENSIONS - #include "ddk/mountmgr.h" - -+enum fs_type -+{ -+ FS_ERROR, /* error accessing the device */ -+ FS_UNKNOWN, /* unknown file system */ -+ FS_FAT1216, -+ FS_FAT32, -+ FS_ISO9660, -+ FS_UDF /* For reference [E] = Ecma-167.pdf, [U] = udf260.pdf */ -+}; -+ - /* device functions */ - - enum device_type -diff --git a/dlls/mountmgr.sys/unixlib.c b/dlls/mountmgr.sys/unixlib.c -index 11111111111..11111111111 100644 ---- a/dlls/mountmgr.sys/unixlib.c -+++ b/dlls/mountmgr.sys/unixlib.c -@@ -56,6 +56,7 @@ - - #include "unixlib.h" - #include "wine/debug.h" -+#include "wine/server.h" - - WINE_DEFAULT_DEBUG_CHANNEL(mountmgr); - -@@ -681,6 +682,50 @@ static NTSTATUS get_shell_folder( void *args ) - return STATUS_SUCCESS; - } - -+static NTSTATUS get_handle_fs_type( void *args ) -+{ -+ const struct get_handle_fs_type_params *params = args; -+ int fd; -+ NTSTATUS status; -+ enum fs_type fs_type = FS_UNKNOWN; -+ struct statfs stfs; -+ -+ status = wine_server_handle_to_fd( params->handle, 0, &fd, NULL ); -+ if (status) return status; -+ -+ if (!fstatfs( fd, &stfs )) -+ { -+#if defined(linux) && defined(HAVE_FSTATFS) -+ switch (stfs.f_type) -+ { -+ case 0x9660: -+ fs_type = FS_ISO9660; -+ break; -+ case 0x15013346: -+ fs_type = FS_UDF; -+ break; -+ case 0x4d44: -+ fs_type = FS_FAT32; -+ break; -+ } -+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__) -+ if (!strcmp( stfs.f_fstypename, "cd9660" )) -+ fs_type = FS_ISO9660; -+ else if (!strcmp( stfs.f_fstypename, "udf" )) -+ fs_type = FS_UDF; -+ else if (!strcmp( stfs.f_fstypename, "msdos" )) /* FreeBSD < 5, Apple */ -+ fs_type = FS_FAT32; -+ else if (!strcmp( stfs.f_fstypename, "msdosfs" )) /* FreeBSD >= 5 */ -+ fs_type = FS_FAT32; -+#endif -+ } -+ -+ close( fd ); -+ -+ *params->fs_type = fs_type; -+ return status; -+} -+ - const unixlib_entry_t __wine_unix_call_funcs[] = - { - run_loop, -@@ -704,6 +749,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = - delete_credential, - enumerate_credentials, - get_volume_filesystem, -+ get_handle_fs_type, - }; - - C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count ); -diff --git a/dlls/mountmgr.sys/unixlib.h b/dlls/mountmgr.sys/unixlib.h -index 11111111111..11111111111 100644 ---- a/dlls/mountmgr.sys/unixlib.h -+++ b/dlls/mountmgr.sys/unixlib.h -@@ -158,6 +158,12 @@ struct ioctl_params - ULONG *info; - }; - -+struct get_handle_fs_type_params -+{ -+ HANDLE handle; -+ enum fs_type *fs_type; -+}; -+ - enum mountmgr_funcs - { - unix_run_loop, -@@ -181,6 +187,7 @@ enum mountmgr_funcs - unix_delete_credential, - unix_enumerate_credentials, - unix_get_volume_filesystem, -+ unix_get_handle_fs_type, - unix_funcs_count - }; - -diff --git a/include/ddk/mountmgr.h b/include/ddk/mountmgr.h -index 11111111111..11111111111 100644 ---- a/include/ddk/mountmgr.h -+++ b/include/ddk/mountmgr.h -@@ -94,6 +94,8 @@ struct mountmgr_volume - FS_INFORMATION_CLASS info_class; - ULONGLONG unix_dev; - WCHAR letter; -+ DWORD process; -+ HANDLE handle; - }; - - - #define IOCTL_MOUNTMGR_READ_CREDENTIAL CTL_CODE(MOUNTMGRCONTROLTYPE, 48, METHOD_BUFFERED, FILE_READ_ACCESS) --- -0.0.0 - diff --git a/0013-server-optimization/0001-misc/ps0086-p0005-ntdll-Obtain-volume-information-directly-fro.patch b/0013-server-optimization/0001-misc/ps0086-p0005-ntdll-Obtain-volume-information-directly-fro.patch deleted file mode 100644 index d4c8413..0000000 --- a/0013-server-optimization/0001-misc/ps0086-p0005-ntdll-Obtain-volume-information-directly-fro.patch +++ /dev/null @@ -1,235 +0,0 @@ -From: "Erich E. Hoover" -Subject: [PATCH 5/5] ntdll: Obtain volume information directly from the mountmgr. -Message-Id: -Date: Thu, 18 Mar 2021 10:54:28 -0600 - -This patch replaces the IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE query in -dlls/ntdll/unix/file.c with the new IOCTL_MOUNTMGR_QUERY_VOLUME. With -this patch all FileFsAttributeInformation and FileFsVolumeInformation -queries run through the mountmgr for both code paths instead of being -duplicated in ntdll. - -Best, -Erich - -From d2864aff1860b635e73f66d9ed1b222749a42cb5 Mon Sep 17 00:00:00 2001 -From: "Erich E. Hoover" -Date: Sat, 20 Feb 2021 17:45:18 -0700 -#Subject: ntdll: Obtain volume information directly from the mountmgr. - -Signed-off-by: Erich E. Hoover ---- - dlls/ntdll/unix/file.c | 145 ++++++----------------------------------- - 1 file changed, 19 insertions(+), 126 deletions(-) - -diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 11111111111..11111111111 100644 ---- a/dlls/ntdll/unix/file.c -+++ b/dlls/ntdll/unix/file.c -@@ -2480,8 +2480,11 @@ static int find_dos_device( const char *path ) - return -1; - } - --static NTSTATUS get_mountmgr_fs_info( HANDLE handle, int fd, struct mountmgr_unix_drive *drive, ULONG size ) -+ -+static NTSTATUS get_mountmgr_vol_info( HANDLE handle, int fd, FS_INFORMATION_CLASS info_class, -+ void *ptr, ULONG size, ULONG_PTR *outsize ) - { -+ struct mountmgr_volume volume; - OBJECT_ATTRIBUTES attr; - UNICODE_STRING string; - char *unix_name; -@@ -2493,16 +2496,19 @@ static NTSTATUS get_mountmgr_fs_info( HANDLE handle, int fd, struct mountmgr_uni - letter = find_dos_device( unix_name ); - free( unix_name ); - -- memset( drive, 0, sizeof(*drive) ); -+ memset( &volume, 0, sizeof(volume) ); - if (letter == -1) - { - struct stat st; - - fstat( fd, &st ); -- drive->unix_dev = st.st_rdev ? st.st_rdev : st.st_dev; -+ volume.unix_dev = st.st_rdev ? st.st_rdev : st.st_dev; - } - else -- drive->letter = 'a' + letter; -+ volume.letter = 'a' + letter; -+ volume.info_class = info_class; -+ volume.process = GetCurrentProcessId(); -+ volume.handle = handle; - - init_unicode_string( &string, MOUNTMGR_DEVICE_NAME ); - InitializeObjectAttributes( &attr, &string, 0, NULL, NULL ); -@@ -2510,10 +2516,12 @@ static NTSTATUS get_mountmgr_fs_info( HANDLE handle, int fd, struct mountmgr_uni - FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT ); - if (status) return status; - -- status = sync_ioctl( mountmgr, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE, drive, sizeof(*drive), drive, size ); -+ status = NtDeviceIoControlFile( mountmgr, NULL, NULL, NULL, &io, IOCTL_MOUNTMGR_QUERY_VOLUME, -+ &volume, sizeof(volume), ptr, size ); - NtClose( mountmgr ); - if (status == STATUS_BUFFER_OVERFLOW) status = STATUS_SUCCESS; - else if (status) WARN("failed to retrieve filesystem type from mountmgr, status %#x\n", status); -+ if (outsize && !status) *outsize = io.Information; - return status; - } - -@@ -5688,12 +5696,14 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, - if (fd_get_file_info( fd, options, &st, &attr ) == -1) status = errno_to_status( errno ); - else - { -- struct mountmgr_unix_drive drive; -+ BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)]; -+ FILE_FS_VOLUME_INFORMATION *ffvi = (FILE_FS_VOLUME_INFORMATION *)buf; -+ FS_INFORMATION_CLASS info_class = FileFsVolumeInformation; - FILE_ID_INFORMATION *info = ptr; - - info->VolumeSerialNumber = 0; -- if (!get_mountmgr_fs_info( handle, fd, &drive, sizeof(drive) )) -- info->VolumeSerialNumber = drive.serial; -+ if (!get_mountmgr_vol_info( handle, fd, info_class, buf, sizeof(buf), NULL )) -+ info->VolumeSerialNumber = ffvi->VolumeSerialNumber; - memset( &info->FileId, 0, sizeof(info->FileId) ); - *(ULONGLONG *)&info->FileId = st.st_ino; - } -@@ -8344,125 +8354,9 @@ NTSTATUS WINAPI NtQueryVolumeInformationFile( HANDLE handle, IO_STATUS_BLOCK *io - break; - - case FileFsAttributeInformation: -- { -- static const WCHAR fatW[] = {'F','A','T'}; -- static const WCHAR fat32W[] = {'F','A','T','3','2'}; -- static const WCHAR ntfsW[] = {'N','T','F','S'}; -- static const WCHAR cdfsW[] = {'C','D','F','S'}; -- static const WCHAR udfW[] = {'U','D','F'}; -- -- FILE_FS_ATTRIBUTE_INFORMATION *info = buffer; -- struct mountmgr_unix_drive drive; -- enum mountmgr_fs_type fs_type = MOUNTMGR_FS_TYPE_NTFS; -- -- if (length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) -- { -- status = STATUS_INFO_LENGTH_MISMATCH; -- break; -- } -- -- if (!get_mountmgr_fs_info( handle, fd, &drive, sizeof(drive) )) fs_type = drive.fs_type; -- else -- { -- struct statfs stfs; -- -- if (!fstatfs( fd, &stfs )) -- { --#if defined(linux) && defined(HAVE_FSTATFS) -- switch (stfs.f_type) -- { -- case 0x9660: -- fs_type = MOUNTMGR_FS_TYPE_ISO9660; -- break; -- case 0x15013346: -- fs_type = MOUNTMGR_FS_TYPE_UDF; -- break; -- case 0x4d44: -- fs_type = MOUNTMGR_FS_TYPE_FAT32; -- break; -- } --#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__) -- if (!strcmp( stfs.f_fstypename, "cd9660" )) -- fs_type = MOUNTMGR_FS_TYPE_ISO9660; -- else if (!strcmp( stfs.f_fstypename, "udf" )) -- fs_type = MOUNTMGR_FS_TYPE_UDF; -- else if (!strcmp( stfs.f_fstypename, "msdos" )) /* FreeBSD < 5, Apple */ -- fs_type = MOUNTMGR_FS_TYPE_FAT32; -- else if (!strcmp( stfs.f_fstypename, "msdosfs" )) /* FreeBSD >= 5 */ -- fs_type = MOUNTMGR_FS_TYPE_FAT32; --#endif -- } -- } -- -- switch (fs_type) -- { -- case MOUNTMGR_FS_TYPE_ISO9660: -- info->FileSystemAttributes = FILE_READ_ONLY_VOLUME; -- info->MaximumComponentNameLength = 221; -- info->FileSystemNameLength = min( sizeof(cdfsW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) ); -- memcpy(info->FileSystemName, cdfsW, info->FileSystemNameLength); -- break; -- case MOUNTMGR_FS_TYPE_UDF: -- info->FileSystemAttributes = FILE_READ_ONLY_VOLUME | FILE_UNICODE_ON_DISK | FILE_CASE_SENSITIVE_SEARCH; -- info->MaximumComponentNameLength = 255; -- info->FileSystemNameLength = min( sizeof(udfW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) ); -- memcpy(info->FileSystemName, udfW, info->FileSystemNameLength); -- break; -- case MOUNTMGR_FS_TYPE_FAT: -- info->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES; /* FIXME */ -- info->MaximumComponentNameLength = 255; -- info->FileSystemNameLength = min( sizeof(fatW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) ); -- memcpy(info->FileSystemName, fatW, info->FileSystemNameLength); -- break; -- case MOUNTMGR_FS_TYPE_FAT32: -- info->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES; /* FIXME */ -- info->MaximumComponentNameLength = 255; -- info->FileSystemNameLength = min( sizeof(fat32W), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) ); -- memcpy(info->FileSystemName, fat32W, info->FileSystemNameLength); -- break; -- default: -- info->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_PERSISTENT_ACLS; -- info->MaximumComponentNameLength = 255; -- info->FileSystemNameLength = min( sizeof(ntfsW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) ); -- memcpy(info->FileSystemName, ntfsW, info->FileSystemNameLength); -- break; -- } -- -- io->Information = offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) + info->FileSystemNameLength; -- status = STATUS_SUCCESS; -- break; -- } -- - case FileFsVolumeInformation: -- { -- FILE_FS_VOLUME_INFORMATION *info = buffer; -- ULONGLONG data[64]; -- struct mountmgr_unix_drive *drive = (struct mountmgr_unix_drive *)data; -- const WCHAR *label; -- -- if (length < sizeof(FILE_FS_VOLUME_INFORMATION)) -- { -- status = STATUS_INFO_LENGTH_MISMATCH; -- break; -- } -- -- if (get_mountmgr_fs_info( handle, fd, drive, sizeof(data) )) -- { -- status = STATUS_NOT_IMPLEMENTED; -- break; -- } -- -- label = (WCHAR *)((char *)drive + drive->label_offset); -- info->VolumeCreationTime.QuadPart = 0; /* FIXME */ -- info->VolumeSerialNumber = drive->serial; -- info->VolumeLabelLength = min( wcslen( label ) * sizeof(WCHAR), -- length - offsetof( FILE_FS_VOLUME_INFORMATION, VolumeLabel ) ); -- info->SupportsObjects = (drive->fs_type == MOUNTMGR_FS_TYPE_NTFS); -- memcpy( info->VolumeLabel, label, info->VolumeLabelLength ); -- io->Information = offsetof( FILE_FS_VOLUME_INFORMATION, VolumeLabel ) + info->VolumeLabelLength; -- status = STATUS_SUCCESS; -+ status = get_mountmgr_vol_info( handle, fd, info_class, buffer, length, &io->Information ); - break; -- } - - case FileFsControlInformation: - FIXME( "%p: control info not supported\n", handle ); -diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index eb89fed2478..9431d174aa4 100644 ---- a/dlls/ntdll/unix/file.c -+++ b/dlls/ntdll/unix/file.c -@@ -2487,6 +2487,7 @@ static NTSTATUS get_mountmgr_vol_info( HANDLE handle, int fd, FS_INFORMATION_CLA - struct mountmgr_volume volume; - OBJECT_ATTRIBUTES attr; - UNICODE_STRING string; -+ IO_STATUS_BLOCK io = {{0}}; - char *unix_name; - HANDLE mountmgr; - unsigned int status; diff --git a/0013-server-optimization/0001-misc/ps0086-p0006-mountmgr-fixup.patch b/0013-server-optimization/0001-misc/ps0086-p0006-mountmgr-fixup.patch deleted file mode 100644 index 711bebb..0000000 --- a/0013-server-optimization/0001-misc/ps0086-p0006-mountmgr-fixup.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c -index 11111111111..11111111111 100644 ---- a/dlls/mountmgr.sys/device.c -+++ b/dlls/mountmgr.sys/device.c -@@ -1639,7 +1639,7 @@ static NTSTATUS query_property( struct disk_device *device, IRP *irp ) - - static NTSTATUS WINAPI fill_volume_info( FS_INFORMATION_CLASS info_class, enum fs_type fs_type, - DWORD serial, WCHAR *label, char *unix_mount, void *buff, -- ULONG length, ULONG_PTR *size ) -+ ULONG length, ULONG_PTR *size, struct volume *volume ) - { - NTSTATUS status; - -@@ -1792,7 +1792,7 @@ NTSTATUS query_volume( void *buff, SIZE_T insize, SIZE_T outsize, IO_STATUS_BLOC - { - char *unix_mount = volume->device ? volume->device->unix_mount : NULL; - status = fill_volume_info( info_class, volume->fs_type, volume->serial, volume->label, -- unix_mount, buff, outsize, &iosb->Information ); -+ unix_mount, buff, outsize, &iosb->Information, volume ); - release_volume( volume ); - } - LeaveCriticalSection( &device_section ); -@@ -1815,7 +1815,7 @@ NTSTATUS query_volume( void *buff, SIZE_T insize, SIZE_T outsize, IO_STATUS_BLOC - CloseHandle( handle ); - if (status) return status; - status = fill_volume_info( info_class, fs_type, 0, NULL, NULL, buff, outsize, -- &iosb->Information ); -+ &iosb->Information, volume ); - } - - return status; -@@ -1838,7 +1838,7 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp ) - volume = dev->volume; - if (volume) - status = fill_volume_info( info_class, volume->fs_type, volume->serial, volume->label, -- dev->unix_mount, buff, length, &io->Information ); -+ dev->unix_mount, buff, length, &io->Information, volume ); - - io->Status = status; - LeaveCriticalSection( &device_section ); diff --git a/0013-server-optimization/0001-misc/ps0136-kernelbase-Implement-TzSpecificLocalTimeToSystemTi.patch b/0013-server-optimization/0001-misc/ps0136-kernelbase-Implement-TzSpecificLocalTimeToSystemTi.patch deleted file mode 100644 index bb79a4f..0000000 --- a/0013-server-optimization/0001-misc/ps0136-kernelbase-Implement-TzSpecificLocalTimeToSystemTi.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 2b262571b5ece30501b6548ab7d2a40cdeac4028 Mon Sep 17 00:00:00 2001 -From: Richard Yao -Date: Sun, 2 Aug 2020 15:35:53 -0400 -Subject: [PATCH] kernelbase: Implement TzSpecificLocalTimeToSystemTimeEx() - -We also reimplement TzSpecificLocalTimeToSystemTime using -TzSpecificLocalTimeToSystemTimeEx. - -Signed-off-by: Richard Yao ---- - dlls/kernelbase/kernelbase.spec | 2 +- - dlls/kernelbase/locale.c | 64 ++++++++++++++++++++++----------- - 2 files changed, 44 insertions(+), 22 deletions(-) - -diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec -index 11111111111..11111111111 100644 ---- a/dlls/kernelbase/kernelbase.spec -+++ b/dlls/kernelbase/kernelbase.spec -@@ -1653,7 +1653,7 @@ - @ stdcall TryEnterCriticalSection(ptr) ntdll.RtlTryEnterCriticalSection - @ stdcall TrySubmitThreadpoolCallback(ptr ptr ptr) - @ stdcall TzSpecificLocalTimeToSystemTime(ptr ptr ptr) --@ stub TzSpecificLocalTimeToSystemTimeEx -+@ stdcall TzSpecificLocalTimeToSystemTimeEx(ptr ptr ptr) - @ stdcall UnhandledExceptionFilter(ptr) - @ stdcall UnlockFile(long long long long long) - @ stdcall UnlockFileEx(long long long long ptr) -diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c -index 11111111111..11111111111 100644 ---- a/dlls/kernelbase/locale.c -+++ b/dlls/kernelbase/locale.c -@@ -7084,6 +7084,42 @@ BOOL WINAPI DECLSPEC_HOTPATCH SystemTimeToTzSpecificLocalTime( const TIME_ZONE_I - } - - -+/*********************************************************************** -+ * TzSpecificLocalTimeToSystemTimeEx (kernelbase.@) -+ */ -+BOOL WINAPI DECLSPEC_HOTPATCH TzSpecificLocalTimeToSystemTimeEx( const DYNAMIC_TIME_ZONE_INFORMATION *info, -+ const SYSTEMTIME *local, -+ SYSTEMTIME *system ) -+{ -+ DYNAMIC_TIME_ZONE_INFORMATION tzinfo; -+ LARGE_INTEGER ft; -+ LONG bias = 0; -+ -+ if (!info) -+ { -+ RtlQueryDynamicTimeZoneInformation( (RTL_TIME_ZONE_INFORMATION *)&tzinfo ); -+ info = &tzinfo; -+ } -+ -+ if (!SystemTimeToFileTime( local, (FILETIME *)&ft )) return FALSE; -+ switch (get_timezone_id( (const TIME_ZONE_INFORMATION *) info, ft, TRUE )) -+ { -+ case TIME_ZONE_ID_UNKNOWN: -+ break; -+ case TIME_ZONE_ID_DAYLIGHT: -+ bias = info->DaylightBias; -+ if (FALSE == info->DynamicDaylightTimeDisabled) -+ break; -+ case TIME_ZONE_ID_STANDARD: -+ bias = info->StandardBias; -+ break; -+ default: -+ return FALSE; -+ } -+ ft.QuadPart += (info->Bias + bias) * (LONGLONG)600000000; -+ return FileTimeToSystemTime( (FILETIME *)&ft, system ); -+} -+ - /*********************************************************************** - * TzSpecificLocalTimeToSystemTime (kernelbase.@) - */ -@@ -7091,31 +7127,17 @@ BOOL WINAPI DECLSPEC_HOTPATCH TzSpecificLocalTimeToSystemTime( const TIME_ZONE_I - const SYSTEMTIME *local, - SYSTEMTIME *system ) - { -- TIME_ZONE_INFORMATION tzinfo; -- LARGE_INTEGER ft; -+ DYNAMIC_TIME_ZONE_INFORMATION tzinfo; - -- if (!info) -+ if (info) - { -- RtlQueryTimeZoneInformation( (RTL_TIME_ZONE_INFORMATION *)&tzinfo ); -- info = &tzinfo; -+ memset(&tzinfo, 0, sizeof(tzinfo)); -+ *((TIME_ZONE_INFORMATION*)&tzinfo) = *info; -+ } else { -+ RtlQueryDynamicTimeZoneInformation( &tzinfo ); - } - -- if (!SystemTimeToFileTime( local, (FILETIME *)&ft )) return FALSE; -- switch (get_timezone_id( info, ft, TRUE )) -- { -- case TIME_ZONE_ID_UNKNOWN: -- ft.QuadPart += info->Bias * (LONGLONG)600000000; -- break; -- case TIME_ZONE_ID_STANDARD: -- ft.QuadPart += (info->Bias + info->StandardBias) * (LONGLONG)600000000; -- break; -- case TIME_ZONE_ID_DAYLIGHT: -- ft.QuadPart += (info->Bias + info->DaylightBias) * (LONGLONG)600000000; -- break; -- default: -- return FALSE; -- } -- return FileTimeToSystemTime( (FILETIME *)&ft, system ); -+ return TzSpecificLocalTimeToSystemTimeEx( &tzinfo, local, system ); - } - - diff --git a/0013-server-optimization/0001-misc/ps0174-p0003-ddraw-Declare-the-same-number-of-planes-as-c.patch b/0013-server-optimization/0001-misc/ps0174-p0003-ddraw-Declare-the-same-number-of-planes-as-c.patch deleted file mode 100644 index fd6247d..0000000 --- a/0013-server-optimization/0001-misc/ps0174-p0003-ddraw-Declare-the-same-number-of-planes-as-c.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: "Rémi Bernon" -Subject: [PATCH 3/5] ddraw: Declare the same number of planes as compute_sphere_visibility takes (GCC 11). -Message-Id: <20210927085833.544992-3-rbernon@codeweavers.com> -Date: Mon, 27 Sep 2021 10:58:31 +0200 -In-Reply-To: <20210927085833.544992-1-rbernon@codeweavers.com> -References: <20210927085833.544992-1-rbernon@codeweavers.com> - -Signed-off-by: Rémi Bernon ---- - dlls/ddraw/device.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c -index 11111111111..11111111111 100644 ---- a/dlls/ddraw/device.c -+++ b/dlls/ddraw/device.c -@@ -4540,7 +4540,7 @@ static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *ifac - D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values) - { - static const DWORD enabled_planes = 0x3f; -- struct wined3d_vec4 plane[6]; -+ struct wined3d_vec4 plane[12]; - unsigned int i, j; - - - TRACE("iface %p, centers %p, radii %p, sphere_count %lu, flags %#lx, return_values %p.\n", --- -0.0.0 - diff --git a/0013-server-optimization/0001-misc/ps0174-p0005-ntoskrnl.exe-Make-user-shared-data-pointers-.patch b/0013-server-optimization/0001-misc/ps0174-p0005-ntoskrnl.exe-Make-user-shared-data-pointers-.patch deleted file mode 100644 index 2ecfa82..0000000 --- a/0013-server-optimization/0001-misc/ps0174-p0005-ntoskrnl.exe-Make-user-shared-data-pointers-.patch +++ /dev/null @@ -1,33 +0,0 @@ -From: "Rémi Bernon" -Subject: [PATCH 5/5] ntoskrnl.exe: Make user shared data pointers volatile (GCC 11). -Message-Id: <20210927085833.544992-5-rbernon@codeweavers.com> -Date: Mon, 27 Sep 2021 10:58:33 +0200 -In-Reply-To: <20210927085833.544992-1-rbernon@codeweavers.com> -References: <20210927085833.544992-1-rbernon@codeweavers.com> - -So that GCC 11 stops warning about reading from a 0-size memory region. - -Signed-off-by: Rémi Bernon ---- - dlls/ntoskrnl.exe/instr.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/dlls/ntoskrnl.exe/instr.c b/dlls/ntoskrnl.exe/instr.c -index 11111111111..11111111111 100644 ---- a/dlls/ntoskrnl.exe/instr.c -+++ b/dlls/ntoskrnl.exe/instr.c -@@ -496,8 +496,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(int); - #define SIB_BASE( sib, rex ) (((sib) & 7) | (((rex) & REX_B) ? 8 : 0)) - - /* keep in sync with dlls/ntdll/thread.c:thread_init */ --static const BYTE *wine_user_shared_data = (BYTE *)0x7ffe0000; --static const BYTE *user_shared_data = (BYTE *)0xfffff78000000000; -+static const BYTE *const volatile wine_user_shared_data = (BYTE *)0x7ffe0000; -+static const BYTE *const volatile user_shared_data = (BYTE *)0xfffff78000000000; - - static inline DWORD64 *get_int_reg( CONTEXT *context, int index ) - { - --- -0.0.0 - diff --git a/0013-server-optimization/0001-misc/ps0175-p0002-win32u-ensure-init_region-sets-pReg-fields-o.patch b/0013-server-optimization/0001-misc/ps0175-p0002-win32u-ensure-init_region-sets-pReg-fields-o.patch deleted file mode 100644 index efe65c6..0000000 --- a/0013-server-optimization/0001-misc/ps0175-p0002-win32u-ensure-init_region-sets-pReg-fields-o.patch +++ /dev/null @@ -1,33 +0,0 @@ -From: Eric Pouech -Subject: [PATCH 2/4] win32u: ensure init_region() sets pReg fields on all code path (GCC11) -Message-Id: <163317638516.285529.4737602410547049339.stgit@euterpe> -Date: Sat, 2 Oct 2021 14:06:25 +0200 -In-Reply-To: <163317637739.285529.489808632054114548.stgit@euterpe> -References: <163317637739.285529.489808632054114548.stgit@euterpe> - -- otherwise, it generates a warning in destroy_region() - -Signed-off-by: Eric Pouech - ---- - dlls/win32u/region.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/dlls/win32u/region.c b/dlls/win32u/region.c -index 11111111111..11111111111 100644 ---- a/dlls/win32u/region.c -+++ b/dlls/win32u/region.c -@@ -407,7 +407,11 @@ static BOOL init_region( WINEREGION *pReg, INT n ) - - if (n > RGN_DEFAULT_RECTS) - { -- if (n > INT_MAX / sizeof(RECT)) return FALSE; -+ if (n > INT_MAX / sizeof(RECT)) -+ { -+ pReg->rects = NULL; -+ return FALSE; -+ } - if (!(pReg->rects = malloc( n * sizeof( RECT ) ))) - return FALSE; - } - diff --git a/0013-server-optimization/0001-misc/ps0268-ntdll-server-Make-robust-to-spurious-short-writes.patch b/0013-server-optimization/0001-misc/ps0268-ntdll-server-Make-robust-to-spurious-short-writes.patch deleted file mode 100644 index 6447556..0000000 --- a/0013-server-optimization/0001-misc/ps0268-ntdll-server-Make-robust-to-spurious-short-writes.patch +++ /dev/null @@ -1,100 +0,0 @@ -From: Keno Fischer -Subject: [PATCH v2] ntdll/server: Make robust to spurious short writes -Message-Id: <20211216020935.GA1741897@juliacomputing.com> -Date: Wed, 15 Dec 2021 21:09:35 -0500 - -It is possible for the write/writev functions in send_request to -return short writes, even in non-error conditions. There are -several situations where this might happen. Examples are: - - SIGSTOP/SIGCONT (either explicitly or via ptrace attach) - - cgroup freezes and similar mechanisms - - system suspends - - External debuggers or profilers - -In general, Linux makes very few guarantees about syscall restarts. -In some cases (in particular when no bytes have been transferred at all), -the linux kernel will automatically restart the system call, but once any -bytes have been transferred, the result will be a short write with -no automatic restart. - -Make wine robust to this corner case by properly restarting a -short write with adjusted buffers. - -Signed-off-by: Keno Fischer ---- - -v2: Fix signoff, fix comment style, stop talking about SIGINT example - in comments and commit message which, as Alexandre Julliard points - out, is not applicable here. - - dlls/ntdll/unix/server.c | 41 +++++++++++++++++++++++++++++++++------- - 1 file changed, 34 insertions(+), 7 deletions(-) - -diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c -index 11111111111..11111111111 100644 ---- a/dlls/ntdll/unix/server.c -+++ b/dlls/ntdll/unix/server.c -@@ -204,13 +204,25 @@ static DECLSPEC_NORETURN void server_protocol_perror( const char *err ) - static unsigned int send_request( const struct __server_request_info *req ) - { - unsigned int i; -- int ret; -+ int ret = 0; - -+ int to_write = sizeof(req->u.req) + req->u.req.request_header.request_size; - if (!req->u.req.request_header.request_size) - { -- if ((ret = write( ntdll_get_thread_data()->request_fd, &req->u.req, -- sizeof(req->u.req) )) == sizeof(req->u.req)) return STATUS_SUCCESS; -- -+ const char *write_ptr = (const char *)&req->u.req; -+ for (;;) { -+ ret = write( ntdll_get_thread_data()->request_fd, (void*)write_ptr, -+ to_write ); -+ if (ret == to_write) return STATUS_SUCCESS; -+ else if (ret < 0) break; -+ /* Short write. Most signals are blocked at this point, but it is -+ still possible to experience a syscall restart due to, e.g. -+ a SIGSTOP, cgroup freeze or external debug/profile tooling. -+ This is not an error. Simply adjust the remaining write length -+ and buffer and start again. */ -+ to_write -= ret; -+ write_ptr += ret; -+ } - } - else - { -@@ -223,11 +235,26 @@ static unsigned int send_request( const struct __server_request_info *req ) - vec[i+1].iov_base = (void *)req->data[i].ptr; - vec[i+1].iov_len = req->data[i].size; - } -- if ((ret = writev( ntdll_get_thread_data()->request_fd, vec, i+1 )) == -- req->u.req.request_header.request_size + sizeof(req->u.req)) return STATUS_SUCCESS; -+ -+ for (;;) { -+ ret = writev( ntdll_get_thread_data()->request_fd, vec, i+1 ); -+ if (ret == to_write) return STATUS_SUCCESS; -+ else if (ret < 0) break; -+ /* Short write as above. Adjust buffer lengths and start again. */ -+ to_write -= ret; -+ for (unsigned int j = 0; j < i+1; j++) { -+ if (ret >= vec[j].iov_len) { -+ ret -= vec[j].iov_len; -+ vec[j].iov_len = 0; -+ } else { -+ vec[j].iov_base = (char *)vec[j].iov_base + ret; -+ vec[j].iov_len -= ret; -+ break; -+ } -+ } -+ } - } - -- if (ret >= 0) server_protocol_error( "partial write %d\n", ret ); - if (errno == EPIPE) abort_thread(0); - if (errno == EFAULT) return STATUS_ACCESS_VIOLATION; - server_protocol_perror( "write" ); - --- -0.0.0 - diff --git a/0013-server-optimization/0001-misc/ps0474-ntdll-Avoid-writing-to-invalid-memory-in-i386-unix.patch b/0013-server-optimization/0001-misc/ps0474-ntdll-Avoid-writing-to-invalid-memory-in-i386-unix.patch deleted file mode 100644 index fb075f0..0000000 --- a/0013-server-optimization/0001-misc/ps0474-ntdll-Avoid-writing-to-invalid-memory-in-i386-unix.patch +++ /dev/null @@ -1,39 +0,0 @@ -From b0515fbb61f7118ed24db134106604d63d618a11 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Sun, 11 Dec 2022 20:09:44 +0100 -Subject: [PATCH 66/68] ntdll: Avoid writing to invalid memory in i386 unix - dispatcher. - - - 100.0% dlls/ntdll/unix/ -diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c -index 751b0081534..d86857be6e3 100644 ---- a/dlls/ntdll/unix/signal_i386.c -+++ b/dlls/ntdll/unix/signal_i386.c -@@ -2779,8 +2779,7 @@ __ASM_GLOBAL_FUNC( __wine_unix_call_dispatcher, - __ASM_CFI_REG_IS_AT1(esi, ecx, 0x30) - "movl %ebp,0x34(%ecx)\n\t" - __ASM_CFI_REG_IS_AT1(ebp, ecx, 0x34) -- "movl 12(%esp),%edx\n\t" /* args */ -- "movl %edx,-16(%ecx)\n\t" -+ "movl 12(%esp),%ebx\n\t" /* args */ - "movl (%esp),%eax\n\t" /* handle */ - "movl 8(%esp),%edx\n\t" /* code */ - /* switch to kernel stack */ -@@ -2792,10 +2791,13 @@ __ASM_GLOBAL_FUNC( __wine_unix_call_dispatcher, - __ASM_CFI(".cfi_offset %ebx,-12\n\t") - __ASM_CFI(".cfi_offset %esi,-16\n\t") - __ASM_CFI(".cfi_offset %edi,-20\n\t") -+ "movl %ebx,(%esp)\n\t" - "call *(%eax,%edx,4)\n\t" - "leal 16(%esp),%esp\n\t" - "testw $0xffff,2(%esp)\n\t" /* frame->restore_flags */ - "jnz " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") "\n\t" -+ "movl 0x20(%esp),%ebx\n\t" -+ __ASM_CFI(".cfi_same_value %ebx\n\t") - "movl 0x08(%esp),%ecx\n\t" /* frame->eip */ - /* switch to user stack */ - "movl 0x0c(%esp),%esp\n\t" /* frame->esp */ --- -2.43.0 - diff --git a/0013-server-optimization/0001-misc/ps0741-ntdll-Implement-NtFlushProcessWriteBuffers.patch b/0013-server-optimization/0001-misc/ps0741-ntdll-Implement-NtFlushProcessWriteBuffers.patch index 65c9770..1952ddc 100644 --- a/0013-server-optimization/0001-misc/ps0741-ntdll-Implement-NtFlushProcessWriteBuffers.patch +++ b/0013-server-optimization/0001-misc/ps0741-ntdll-Implement-NtFlushProcessWriteBuffers.patch @@ -1,69 +1,76 @@ -From c1720fc3ab35df2aa9c02f14a3214a4cc9370fdd Mon Sep 17 00:00:00 2001 +From 7f0f004f441bb5a4098fcf9cc980e9f2dddda616 Mon Sep 17 00:00:00 2001 From: Torge Matthies -Date: Tue, 20 Feb 2024 16:45:49 +0100 -Subject: [PATCH 1/4] ntdll: Add mprotect-based implementation of +Date: Tue, 28 Mar 2023 12:53:25 +0200 +Subject: [PATCH 1/3] ntdll: Add MADV_DONTNEED-based implementation of NtFlushProcessWriteBuffers. +Credits to Avi Kivity (scylladb) and Aliaksei Kandratsenka (gperftools) for this trick, see [1]. + +[1] https://github.com/scylladb/seastar/commit/77a58e4dc020233f66fccb8d9e8f7a8b7f9210c4 --- - dlls/ntdll/unix/virtual.c | 51 +++++++++++++++++++++++++++++++++++++-- - 1 file changed, 49 insertions(+), 2 deletions(-) + dlls/ntdll/unix/virtual.c | 52 +++++++++++++++++++++++++++++++++++++- + tools/winapi/nativeapi.dat | 1 + + 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 2b6ce543531..219a0339933 100644 +index 0faf3e343e3..a6fb19c807a 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c -@@ -219,6 +219,9 @@ struct range_entry +@@ -216,6 +216,9 @@ struct range_entry static struct range_entry *free_ranges; static struct range_entry *free_ranges_end; -+static void *dummy_page; -+static pthread_mutex_t dummy_page_mutex = PTHREAD_MUTEX_INITIALIZER; ++static void *dontneed_page; ++static pthread_mutex_t dontneed_page_mutex = PTHREAD_MUTEX_INITIALIZER; + static inline BOOL is_beyond_limit( const void *addr, size_t size, const void *limit ) { -@@ -6073,14 +6076,58 @@ NTSTATUS WINAPI NtFlushInstructionCache( HANDLE handle, const void *addr, SIZE_T +@@ -5170,13 +5173,60 @@ NTSTATUS WINAPI NtFlushInstructionCache( HANDLE handle, const void *addr, SIZE_T } -+static BOOL try_mprotect( void ) ++static BOOL try_madvise( void ) +{ -+#if !defined(__i386__) && !defined(__x86_64__) ++#ifdef __aarch64__ + static int once = 0; +#endif + BOOL success = FALSE; + char *mem; + -+ pthread_mutex_lock(&dummy_page_mutex); -+ mem = dummy_page; ++ pthread_mutex_lock(&dontneed_page_mutex); ++ /* Credits to Avi Kivity (scylladb) and Aliaksei Kandratsenka (gperftools) for this trick, ++ see https://github.com/scylladb/seastar/commit/77a58e4dc020233f66fccb8d9e8f7a8b7f9210c4 */ ++ mem = dontneed_page; + if (!mem) + { -+ /* Allocate one page of memory that we can call mprotect() on */ ++ int ret; ++ /* Allocate one page of memory that we can call madvise() on */ + mem = anon_mmap_alloc( page_size, PROT_READ | PROT_WRITE ); + if (mem == MAP_FAILED) + goto failed; -+ /* Lock page into memory so that it is not unmapped between the calls to mprotect() below */ -+ if (mlock( mem, page_size )) ++ /* If the memory is locked, e.g. by a call to mlockall(MCL_FUTURE), the madvise() call below ++ will fail with error EINVAL, so unlock it here */ ++ ret = munlock( mem, page_size ); ++ /* munlock() may fail on old kernels if we don't have sufficient permissions, but that is not ++ a problem since in that case we didn't have permission to lock the memory either */ ++ if (ret && errno != EPERM) + goto failed; -+ dummy_page = mem; ++ dontneed_page = mem; + } -+ /* Make dummy page writable */ -+ success = !mprotect( mem, page_size, PROT_READ | PROT_WRITE ); -+ if (!success) -+ goto failed; -+ /* Make the page dirty to prevent the kernel from skipping the global TLB flush */ -+ InterlockedIncrement((volatile LONG*)mem); -+ /* Change the page protection to PROT_NONE to force the kernel to send an IPI to all threads of this process, ++ /* Force the page into memory to make madvise() have real work to do */ ++ *mem = 3; ++ /* Evict the page from memory to force the kernel to send an IPI to all threads of this process, + which has the side effect of executing a memory barrier in those threads */ -+ success = !mprotect( mem, page_size, PROT_NONE ); -+#if !defined(__i386__) && !defined(__x86_64__) ++ success = !madvise( mem, page_size, MADV_DONTNEED ); ++#ifdef __aarch64__ + /* Some ARMv8 processors can broadcast TLB invalidations using the TLBI instruction, -+ the madvise trick does not work on those. Print a fixme on all non-x86 architectures. */ ++ the madvise trick does not work on those */ + if (success && !once++) + FIXME( "memory barrier may not work on this platform\n" ); +#endif +failed: -+ pthread_mutex_unlock(&dummy_page_mutex); ++ pthread_mutex_unlock(&dontneed_page_mutex); + return success; +} + @@ -75,22 +82,32 @@ index 2b6ce543531..219a0339933 100644 { static int once = 0; - if (!once++) FIXME( "stub\n" ); -- return STATUS_SUCCESS; -+ if (try_mprotect()) ++ if (try_madvise()) + return STATUS_SUCCESS; + if (!once++) FIXME( "no implementation available on this platform\n" ); -+ return STATUS_NOT_IMPLEMENTED; + return STATUS_SUCCESS; } - +diff --git a/tools/winapi/nativeapi.dat b/tools/winapi/nativeapi.dat +index ade20b5ee68..5512c4f1833 100644 +--- a/tools/winapi/nativeapi.dat ++++ b/tools/winapi/nativeapi.dat +@@ -134,6 +134,7 @@ log10 + logb + longjmp + lseek ++madvise + malloc + mblen + memccpy -- GitLab -From 5014d210649a65e6e46c1dd3363e65d1a304eb5f Mon Sep 17 00:00:00 2001 +From 014e78a433f147bf81cd5a94f7dcb7bbceecde60 Mon Sep 17 00:00:00 2001 From: Torge Matthies -Date: Tue, 20 Feb 2024 16:45:49 +0100 -Subject: [PATCH 2/4] ntdll: Add sys_membarrier-based implementation of +Date: Tue, 28 Mar 2023 12:53:25 +0200 +Subject: [PATCH 2/3] ntdll: Add sys_membarrier-based implementation of NtFlushProcessWriteBuffers. Uses the MEMBARRIER_CMD_PRIVATE_EXPEDITED membarrier command introduced in Linux 4.14. @@ -99,7 +116,7 @@ Uses the MEMBARRIER_CMD_PRIVATE_EXPEDITED membarrier command introduced in Linux 1 file changed, 47 insertions(+) diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 219a0339933..8c53ce00e9f 100644 +index a6fb19c807a..ee2a12ecd54 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -39,6 +39,9 @@ @@ -112,7 +129,7 @@ index 219a0339933..8c53ce00e9f 100644 #ifdef HAVE_SYS_SYSCTL_H # include #endif -@@ -219,6 +222,11 @@ struct range_entry +@@ -216,6 +219,11 @@ struct range_entry static struct range_entry *free_ranges; static struct range_entry *free_ranges_end; @@ -121,10 +138,10 @@ index 219a0339933..8c53ce00e9f 100644 +static pthread_once_t membarrier_init_once = PTHREAD_ONCE_INIT; +#endif + - static void *dummy_page; - static pthread_mutex_t dummy_page_mutex = PTHREAD_MUTEX_INITIALIZER; + static void *dontneed_page; + static pthread_mutex_t dontneed_page_mutex = PTHREAD_MUTEX_INITIALIZER; -@@ -6076,6 +6084,43 @@ NTSTATUS WINAPI NtFlushInstructionCache( HANDLE handle, const void *addr, SIZE_T +@@ -5173,6 +5181,43 @@ NTSTATUS WINAPI NtFlushInstructionCache( HANDLE handle, const void *addr, SIZE_T } @@ -165,34 +182,34 @@ index 219a0339933..8c53ce00e9f 100644 +#endif /* defined(__linux__) && defined(__NR_membarrier) */ + + - static BOOL try_mprotect( void ) + static BOOL try_madvise( void ) { - #if !defined(__i386__) && !defined(__x86_64__) -@@ -6124,6 +6169,8 @@ failed: + #ifdef __aarch64__ +@@ -5224,6 +5269,8 @@ failed: NTSTATUS WINAPI NtFlushProcessWriteBuffers(void) { static int once = 0; + if (try_exp_membarrier()) + return STATUS_SUCCESS; - if (try_mprotect()) + if (try_madvise()) return STATUS_SUCCESS; if (!once++) FIXME( "no implementation available on this platform\n" ); -- GitLab -From 1dff2a4385d92b9afba435e0a6f2c2116de162a2 Mon Sep 17 00:00:00 2001 +From e9df595359e846e3596c9268f7856b29e4fb628d Mon Sep 17 00:00:00 2001 From: Torge Matthies -Date: Tue, 20 Feb 2024 16:45:49 +0100 -Subject: [PATCH 3/4] ntdll: Add thread_get_register_pointer_values-based +Date: Tue, 28 Mar 2023 12:53:26 +0200 +Subject: [PATCH 3/3] ntdll: Add thread_get_register_pointer_values-based implementation of NtFlushProcessWriteBuffers. --- - dlls/ntdll/unix/virtual.c | 64 +++++++++++++++++++++++++++++++++++++++ - 1 file changed, 64 insertions(+) + dlls/ntdll/unix/virtual.c | 70 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 70 insertions(+) diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 8c53ce00e9f..155367b605f 100644 +index ee2a12ecd54..7a5778a6d8c 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -65,6 +65,9 @@ @@ -205,7 +222,7 @@ index 8c53ce00e9f..155367b605f 100644 #endif #include "ntstatus.h" -@@ -222,6 +225,11 @@ struct range_entry +@@ -219,6 +222,11 @@ struct range_entry static struct range_entry *free_ranges; static struct range_entry *free_ranges_end; @@ -217,7 +234,7 @@ index 8c53ce00e9f..155367b605f 100644 #if defined(__linux__) && defined(__NR_membarrier) static BOOL membarrier_exp_available; static pthread_once_t membarrier_init_once = PTHREAD_ONCE_INIT; -@@ -6084,6 +6092,60 @@ NTSTATUS WINAPI NtFlushInstructionCache( HANDLE handle, const void *addr, SIZE_T +@@ -5181,6 +5189,66 @@ NTSTATUS WINAPI NtFlushInstructionCache( HANDLE handle, const void *addr, SIZE_T } @@ -233,8 +250,8 @@ index 8c53ce00e9f..155367b605f 100644 + /* Taken from https://github.com/dotnet/runtime/blob/7be37908e5a1cbb83b1062768c1649827eeaceaa/src/coreclr/pal/src/thread/process.cpp#L2799 */ + mach_msg_type_number_t count, i = 0; + thread_act_array_t threads; -+ BOOL success = TRUE; + kern_return_t kret; ++ BOOL success = FALSE; + + pthread_once(&tgrpvs_init_once, tgrpvs_init); + if (!p_thread_get_register_pointer_values) @@ -257,12 +274,18 @@ index 8c53ce00e9f..155367b605f 100644 + /* This function always fails when querying Rosetta's exception handling thread, so we only treat + KERN_INSUFFICIENT_BUFFER_SIZE as an error, like .NET core does. */ + if (kret == KERN_INSUFFICIENT_BUFFER_SIZE) -+ success = FALSE; ++ goto fail; + + /* Deallocate thread reference once we're done with it */ -+ mach_port_deallocate( mach_task_self(), threads[i++] ); ++ kret = mach_port_deallocate( mach_task_self(), threads[i++] ); ++ if (kret) ++ goto fail; + } -+ ++ success = TRUE; ++fail: ++ /* Deallocate remaining thread references */ ++ while (i < count) ++ mach_port_deallocate( mach_task_self(), threads[i++] ); + /* Deallocate thread list */ + vm_deallocate( mach_task_self(), (vm_address_t)threads, count * sizeof(threads[0]) ); + return success; @@ -278,7 +301,7 @@ index 8c53ce00e9f..155367b605f 100644 #if defined(__linux__) && defined(__NR_membarrier) #define MEMBARRIER_CMD_QUERY 0x00 -@@ -6169,6 +6231,8 @@ failed: +@@ -5269,6 +5337,8 @@ failed: NTSTATUS WINAPI NtFlushProcessWriteBuffers(void) { static int once = 0; @@ -286,61 +309,7 @@ index 8c53ce00e9f..155367b605f 100644 + return STATUS_SUCCESS; if (try_exp_membarrier()) return STATUS_SUCCESS; - if (try_mprotect()) --- -GitLab - - -From 2249604e53b9f72478d3886f250720db957454cf Mon Sep 17 00:00:00 2001 -From: Torge Matthies -Date: Tue, 20 Feb 2024 16:51:50 +0100 -Subject: [PATCH 4/4] ntdll/tests: Add basic NtFlushProcessWriteBuffers test. - ---- - dlls/ntdll/tests/virtual.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c -index 3628cec89e8..748ce9c4bb8 100644 ---- a/dlls/ntdll/tests/virtual.c -+++ b/dlls/ntdll/tests/virtual.c -@@ -46,6 +46,7 @@ static NTSTATUS (WINAPI *pNtMapViewOfSectionEx)(HANDLE, HANDLE, PVOID *, const L - static NTSTATUS (WINAPI *pNtSetInformationVirtualMemory)(HANDLE, VIRTUAL_MEMORY_INFORMATION_CLASS, - ULONG_PTR, PMEMORY_RANGE_ENTRY, - PVOID, ULONG); -+static NTSTATUS (WINAPI *pNtFlushProcessWriteBuffers)(void); - - static const BOOL is_win64 = sizeof(void*) != sizeof(int); - static BOOL is_wow64; -@@ -2705,6 +2706,14 @@ static void test_query_image_information(void) - NtClose( file ); - } - -+static void test_flush_write_buffers(void) -+{ -+ NTSTATUS status; -+ -+ status = pNtFlushProcessWriteBuffers(); -+ ok( status == STATUS_SUCCESS, "Unexpected status %08lx\n", status ); -+} -+ - START_TEST(virtual) - { - HMODULE mod; -@@ -2737,6 +2746,7 @@ START_TEST(virtual) - pNtAllocateVirtualMemoryEx = (void *)GetProcAddress(mod, "NtAllocateVirtualMemoryEx"); - pNtMapViewOfSectionEx = (void *)GetProcAddress(mod, "NtMapViewOfSectionEx"); - pNtSetInformationVirtualMemory = (void *)GetProcAddress(mod, "NtSetInformationVirtualMemory"); -+ pNtFlushProcessWriteBuffers = (void *)GetProcAddress(mod, "NtFlushProcessWriteBuffers"); - - NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL); - trace("system page size %#lx\n", sbi.PageSize); -@@ -2755,4 +2765,5 @@ START_TEST(virtual) - test_query_region_information(); - test_query_image_information(); - test_exec_memory_writes(); -+ test_flush_write_buffers(); - } + if (try_madvise()) -- GitLab diff --git a/0013-server-optimization/0001-misc/ps6666-win32u-check-for-driver-events-every-0.1ms-instead-o.patch b/0013-server-optimization/0001-misc/ps6666-win32u-check-for-driver-events-every-0.1ms-instead-o.patch new file mode 100644 index 0000000..8171940 --- /dev/null +++ b/0013-server-optimization/0001-misc/ps6666-win32u-check-for-driver-events-every-0.1ms-instead-o.patch @@ -0,0 +1,71 @@ +From: William Horvath +Date: Mon, 9 Dec 2024 03:26:27 -0800 +Subject: [PATCH] win32u: check for driver events every 0.1ms instead of 1ms + +alternative workaround for https://bugs.winehq.org/show_bug.cgi?id=57442 + +v2: use fast USD (it's updating at 0.1ms anyways) instead of yet another clock_gettime call +--- + dlls/win32u/message.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c +index 11111111111..11111111111 100644 +--- a/dlls/win32u/message.c ++++ b/dlls/win32u/message.c +@@ -26,6 +26,8 @@ + + #include + #include "ntstatus.h" ++#include "winternl.h" ++#include "ddk/wdm.h" + #define WIN32_NO_STATUS + #include "win32u_private.h" + #include "ntuser_private.h" +@@ -40,6 +42,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msg); + WINE_DECLARE_DEBUG_CHANNEL(key); + WINE_DECLARE_DEBUG_CHANNEL(relay); + ++static const struct _KUSER_SHARED_DATA *user_shared_data = (struct _KUSER_SHARED_DATA *)0x7ffe0000; ++ + #define MAX_WINPROC_RECURSION 64 + + #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE +@@ -354,6 +358,11 @@ static const unsigned int message_pointer_flags[] = + SET(WM_ASKCBFORMATNAME) + }; + ++static inline DWORD __wine_get_hires_tick_count(void) ++{ ++ return (DWORD)(user_shared_data->InterruptTime.LowPart / 1000); ++} ++ + /* check whether a given message type includes pointers */ + static inline BOOL is_pointer_message( UINT message, WPARAM wparam ) + { +@@ -3064,11 +3073,11 @@ static HANDLE get_server_queue_handle(void) + /* check for driver events if we detect that the app is not properly consuming messages */ + static inline void check_for_driver_events(void) + { +- if (get_user_thread_info()->last_driver_time != NtGetTickCount()) ++ if (get_user_thread_info()->last_driver_time != __wine_get_hires_tick_count()) + { + flush_window_surfaces( FALSE ); + user_driver->pProcessEvents( QS_ALLINPUT ); +- get_user_thread_info()->last_driver_time = NtGetTickCount(); ++ get_user_thread_info()->last_driver_time = __wine_get_hires_tick_count(); + } + } + +@@ -3110,7 +3119,7 @@ static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DW + } + + if (ret == WAIT_TIMEOUT && !count && !timeout) NtYieldExecution(); +- if (ret == count - 1) get_user_thread_info()->last_driver_time = NtGetTickCount(); ++ if (ret == count - 1) get_user_thread_info()->last_driver_time = __wine_get_hires_tick_count(); + + KeUserDispatchCallback( ¶ms.dispatch, sizeof(params), &ret_ptr, &ret_len ); + +-- +0.0.0 + diff --git a/0013-server-optimization/0003-qpc/0009-ntdll-Create-and-use-hypervisor-shared-data-page-for.patch b/0013-server-optimization/0003-qpc/0009-ntdll-Create-and-use-hypervisor-shared-data-page-for.patch index 860ab87..e9f2aac 100644 --- a/0013-server-optimization/0003-qpc/0009-ntdll-Create-and-use-hypervisor-shared-data-page-for.patch +++ b/0013-server-optimization/0003-qpc/0009-ntdll-Create-and-use-hypervisor-shared-data-page-for.patch @@ -153,7 +153,7 @@ index 11111111111..11111111111 100644 + MEM_RESERVE | MEM_COMMIT, PAGE_READONLY ); + if (status) + { -+ ERR( "wine: failed to map the shared user data: %08x\n", status ); ++ ERR( "wine: failed to map the shared hypervisor data: %08x\n", status ); + exit(1); + } + diff --git a/0013-server-optimization/0003-qpc/2001-ntdll-HACK-Work-around-WINELOADERNOEXEC-hypervisor_s.patch b/0013-server-optimization/0003-qpc/2001-ntdll-HACK-Work-around-WINELOADERNOEXEC-hypervisor_s.patch new file mode 100644 index 0000000..2a29c9f --- /dev/null +++ b/0013-server-optimization/0003-qpc/2001-ntdll-HACK-Work-around-WINELOADERNOEXEC-hypervisor_s.patch @@ -0,0 +1,31 @@ +From 9fa4d646def448d77e2d5dfee01f2260bf386a1c Mon Sep 17 00:00:00 2001 +From: William Horvath +Date: Tue, 3 Dec 2024 21:35:41 -0800 +Subject: [PATCH] ntdll: HACK: Work around WINELOADERNOEXEC + hypervisor_shared_data mapping. + +--- + dlls/ntdll/unix/virtual.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index fb5b8e4b16b..96490c131b4 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -932,8 +932,11 @@ static void mmap_init( const struct preload_info *preload_info ) + } + } + } +- else reserve_area( (void *)0x00010000, (void *)0x40000000 ); +- ++ else ++ { ++ user_space_limit = (char *)0x7ffd0000; ++ reserve_area( (void *)0x00010000, (void *)0x40000000 ); ++ } + + #ifndef __APPLE__ + if (stack_ptr >= user_space_limit) +-- +2.47.1 + diff --git a/0013-server-optimization/0003-qpc/9100-display-cache-less-frequent-update.patch b/0013-server-optimization/0003-qpc/9100-display-cache-less-frequent-update.patch deleted file mode 100644 index 2806a43..0000000 --- a/0013-server-optimization/0003-qpc/9100-display-cache-less-frequent-update.patch +++ /dev/null @@ -1,82 +0,0 @@ -diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c -index 11111111111..11111111111 100644 ---- a/dlls/win32u/sysparams.c -+++ b/dlls/win32u/sysparams.c -@@ -26,9 +26,14 @@ - - #include - #include -+#include - - #include "ntstatus.h" - #define WIN32_NO_STATUS -+#include "windef.h" -+#include "winbase.h" -+#include "winternl.h" -+#include "ddk/wdm.h" - #include "ntgdi_private.h" - #include "ntuser_private.h" - #include "devpropdef.h" -@@ -1679,12 +1684,31 @@ static struct monitor *find_monitor_from_path( const char *path ) - return NULL; - } - -+static ULONGLONG last_update = 0; -+ -+#define user_shared_data ((volatile const struct _KUSER_SHARED_DATA *)0x7ffe0000) -+ -+static ULONGLONG get_tick_count(void) -+{ -+ ULONG high, low; -+ -+ do -+ { -+ high = user_shared_data->TickCount.High1Time; -+ low = user_shared_data->TickCount.LowPart; -+ } -+ while (high != user_shared_data->TickCount.High2Time); -+ /* note: we ignore TickCountMultiplier */ -+ return (ULONGLONG)high << 32 | low; -+} -+ - static BOOL update_display_cache_from_registry(void) - { - char path[MAX_PATH]; - DWORD source_id, monitor_id, monitor_count = 0, size; - KEY_BASIC_INFORMATION key; - struct source *source; -+ ULONGLONG tick_count; - struct monitor *monitor; - HANDLE mutex = NULL; - NTSTATUS status; -@@ -1694,12 +1718,18 @@ static BOOL update_display_cache_from_registry(void) - sizeof(devicemap_video_keyW) ))) - return FALSE; - -+ if ((tick_count = get_tick_count()) - last_update < 1000) return TRUE; -+ - status = NtQueryKey( video_key, KeyBasicInformation, &key, - offsetof(KEY_BASIC_INFORMATION, Name), &size ); - if (status && status != STATUS_BUFFER_OVERFLOW) - return FALSE; - -- if (key.LastWriteTime.QuadPart <= last_query_display_time) return TRUE; -+ if (key.LastWriteTime.QuadPart <= last_query_display_time) -+ { -+ last_update = tick_count; -+ return TRUE; -+ } - - mutex = get_display_device_init_mutex(); - pthread_mutex_lock( &display_lock ); -@@ -1746,7 +1776,10 @@ static BOOL update_display_cache_from_registry(void) - } - - if ((ret = !list_empty( &sources ) && !list_empty( &monitors ))) -+ { - last_query_display_time = key.LastWriteTime.QuadPart; -+ last_update = tick_count; -+ } - - set_winstation_monitors(); - pthread_mutex_unlock( &display_lock ); diff --git a/0013-server-optimization/0004-time-wait/0001-use-clock_nanosleep-for-delay.patch b/0013-server-optimization/0004-time-wait/0001-use-clock_nanosleep-for-delay.patch deleted file mode 100644 index 0e4794c..0000000 --- a/0013-server-optimization/0004-time-wait/0001-use-clock_nanosleep-for-delay.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/configure.ac b/configure.ac -index d539ee50bda..7585324602c 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -2170,6 +2170,17 @@ case $host_os in - ;; - esac - -+dnl Check for clock_nanosleep which may be in -lrt -+case $host_os in -+ darwin*|macosx*) ;; -+ *) ac_save_LIBS=$LIBS -+ AC_SEARCH_LIBS(clock_nanosleep, rt, -+ [AC_DEFINE(HAVE_CLOCK_NANOSLEEP, 1, [Define to 1 if you have the `clock_nanosleep' function.]) -+ test "$ac_res" = "none required" || AC_SUBST(RT_LIBS,"$ac_res")]) -+ LIBS=$ac_save_LIBS -+ ;; -+esac -+ - AC_CACHE_CHECK([for sched_setaffinity],wine_cv_have_sched_setaffinity, - AC_LINK_IFELSE([AC_LANG_PROGRAM( - [[#include ]], [[sched_setaffinity(0, 0, 0);]])],[wine_cv_have_sched_setaffinity=yes],[wine_cv_have_sched_setaffinity=no])) -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 11111111111..11111111111 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -2851,10 +2851,39 @@ NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeou - } - else - { -+ LONGLONG ticks = timeout->QuadPart; - LARGE_INTEGER now; -- timeout_t when, diff; -+ timeout_t when = ticks, diff; - -- if ((when = timeout->QuadPart) < 0) -+#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_NANOSLEEP) -+ static BOOL disable_clock_nanosleep = FALSE; -+ if (!disable_clock_nanosleep && ticks != 0) -+ { -+ struct timespec when; -+ int err; -+ -+ if (ticks < 0) -+ { -+ clock_gettime( CLOCK_REALTIME, &when ); -+ when.tv_sec += (time_t)(-ticks / TICKSPERSEC); -+ when.tv_nsec += (long)((-ticks % TICKSPERSEC) * 100); -+ } -+ else -+ { -+ when.tv_sec = (time_t)((ticks / TICKSPERSEC) - SECS_1601_TO_1970); -+ when.tv_nsec = (long)((ticks % TICKSPERSEC) * 100); -+ } -+ -+ -+ while ((err = clock_nanosleep( CLOCK_REALTIME, TIMER_ABSTIME, &when, NULL )) == EINTR); -+ if (!err) -+ return STATUS_SUCCESS; -+ else -+ disable_clock_nanosleep = TRUE; -+ } -+#endif -+ -+ if (when < 0) - { - NtQuerySystemTime( &now ); - when = now.QuadPart - when; diff --git a/0013-server-optimization/0004-time-wait/0007-server-Use-a-dedicated-thread-for-user_shared_data-t.patch b/0013-server-optimization/0004-time-wait/0007-server-Use-a-dedicated-thread-for-user_shared_data-t.patch index b7749cd..f25d2e6 100644 --- a/0013-server-optimization/0004-time-wait/0007-server-Use-a-dedicated-thread-for-user_shared_data-t.patch +++ b/0013-server-optimization/0004-time-wait/0007-server-Use-a-dedicated-thread-for-user_shared_data-t.patch @@ -72,9 +72,9 @@ index 80bf84b5ac0..8538c0e711f 100644 +static void set_user_shared_data_time(timeout_t current_time, timeout_t monotonic_time) { + /* Adding a compensation offset for the USD update interval -+ * to try to workaround consumers reading stale values and being behind real QPC */ -+ current_time += user_shared_data_timeout_ticks; -+ monotonic_time += user_shared_data_timeout_ticks; ++ * to try to workaround consumers reading stale values and being behind real QPC (maybe not) */ ++ // current_time += user_shared_data_timeout_ticks; ++ // monotonic_time += user_shared_data_timeout_ticks; timeout_t tick_count = monotonic_time / 10000; static timeout_t last_timezone_update; timeout_t timezone_bias; diff --git a/0013-server-optimization/0004-time-wait/0011-remove-yield-syscall.patch b/0013-server-optimization/0004-time-wait/0011-remove-yield-syscall.patch new file mode 100644 index 0000000..333dd61 --- /dev/null +++ b/0013-server-optimization/0004-time-wait/0011-remove-yield-syscall.patch @@ -0,0 +1,22 @@ +diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c +index 91bab77489a..8bae3cfe686 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -1848,17 +1848,7 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, + NTSTATUS WINAPI NtYieldExecution(void) + { + #ifdef HAVE_SCHED_YIELD +-#ifdef RUSAGE_THREAD +- struct rusage u1, u2; +- int ret; +- +- ret = getrusage( RUSAGE_THREAD, &u1 ); +-#endif + sched_yield(); +-#ifdef RUSAGE_THREAD +- if (!ret) ret = getrusage( RUSAGE_THREAD, &u2 ); +- if (!ret && u1.ru_nvcsw == u2.ru_nvcsw && u1.ru_nivcsw == u2.ru_nivcsw) return STATUS_NO_YIELD_PERFORMED; +-#endif + return STATUS_SUCCESS; + #else + return STATUS_NO_YIELD_PERFORMED; diff --git a/0013-server-optimization/0008-shm-opts/ps2002-HACK-win32u-Skip-setting-the-cursor-position-if-the-.patch b/0013-server-optimization/0008-shm-opts/ps2002-HACK-win32u-Skip-setting-the-cursor-position-if-the-.patch deleted file mode 100644 index d663611..0000000 --- a/0013-server-optimization/0008-shm-opts/ps2002-HACK-win32u-Skip-setting-the-cursor-position-if-the-.patch +++ /dev/null @@ -1,40 +0,0 @@ -From c3ec84dd82f38df2364e2aa4efd3d6ce85a46616 Mon Sep 17 00:00:00 2001 -From: Torge Matthies -Date: Tue, 29 Mar 2022 02:13:14 +0200 -Subject: [PATCH 2002/7] HACK: win32u: Skip setting the cursor position if the new - position matches the cached one. - ---- - dlls/win32u/input.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c -index 11111111111..11111111111 100644 ---- a/dlls/win32u/input.c -+++ b/dlls/win32u/input.c -@@ -706,10 +706,22 @@ UINT WINAPI NtUserSendInput( UINT count, INPUT *inputs, int size ) - */ - BOOL WINAPI NtUserSetCursorPos( INT x, INT y ) - { -+ struct object_lock lock = OBJECT_LOCK_INIT; -+ const desktop_shm_t *desktop_shm; -+ NTSTATUS status; - RECT rect = {x, y, x, y}; - BOOL ret; - INT prev_x, prev_y, new_x, new_y; - -+ /* HACK: Doesn't generate any window messages but skips the server call. */ -+ while ((status = get_shared_desktop( &lock, &desktop_shm )) == STATUS_PENDING) -+ { -+ ret = desktop_shm->cursor.last_change != 0 && -+ x == desktop_shm->cursor.x && -+ y == desktop_shm->cursor.y; -+ } -+ if (ret) return TRUE; -+ - rect = map_rect_virt_to_raw( rect, get_thread_dpi() ); - SERVER_START_REQ( set_cursor ) - { --- -0.0.0 - diff --git a/9000-misc-additions/8bpp-copy-support.patch b/9000-misc-additions/8bpp-copy-support.patch index 0c67346..52a2bcf 100644 --- a/9000-misc-additions/8bpp-copy-support.patch +++ b/9000-misc-additions/8bpp-copy-support.patch @@ -21,7 +21,7 @@ index 11111111111..11111111111 100644 + srcstride = prc->Width; + srcdatasize = srcstride * prc->Height; + -+ srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); ++ srcdata = malloc(srcdatasize); + if (!srcdata) return E_OUTOFMEMORY; + + res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -45,7 +45,7 @@ index 11111111111..11111111111 100644 + } + } + -+ HeapFree(GetProcessHeap(), 0, srcdata); ++ free(srcdata); + + return res; + } diff --git a/9000-misc-additions/HACK-proton-wineboot-Don-t-show-updating-prefix-wind.patch b/9000-misc-additions/HACK-proton-wineboot-Don-t-show-updating-prefix-wind.patch new file mode 100644 index 0000000..3808c40 --- /dev/null +++ b/9000-misc-additions/HACK-proton-wineboot-Don-t-show-updating-prefix-wind.patch @@ -0,0 +1,71 @@ +From 4e5d2e3aae85eabeee6921e5d889608ae2881ef6 Mon Sep 17 00:00:00 2001 +From: Andrew Eikum +Date: Mon, 22 Jan 2018 14:35:51 -0600 +Subject: [PATCH 0030/2346] HACK: proton: wineboot: Don't show "updating + prefix" window. + +--- + programs/wineboot/wineboot.c | 33 --------------------------------- + 1 file changed, 33 deletions(-) + +diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c +index c16446cf289..2a8f2edb141 100644 +--- a/programs/wineboot/wineboot.c ++++ b/programs/wineboot/wineboot.c +@@ -1425,37 +1425,6 @@ static BOOL start_services_process(void) + return TRUE; + } + +-static INT_PTR CALLBACK wait_dlgproc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) +-{ +- switch (msg) +- { +- case WM_INITDIALOG: +- { +- DWORD len; +- WCHAR *buffer, text[1024]; +- const WCHAR *name = (WCHAR *)lp; +- HICON icon = LoadImageW( 0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 48, 48, LR_SHARED ); +- SendDlgItemMessageW( hwnd, IDC_WAITICON, STM_SETICON, (WPARAM)icon, 0 ); +- SendDlgItemMessageW( hwnd, IDC_WAITTEXT, WM_GETTEXT, 1024, (LPARAM)text ); +- len = lstrlenW(text) + lstrlenW(name) + 1; +- buffer = malloc( len * sizeof(WCHAR) ); +- swprintf( buffer, len, text, name ); +- SendDlgItemMessageW( hwnd, IDC_WAITTEXT, WM_SETTEXT, 0, (LPARAM)buffer ); +- free( buffer ); +- } +- break; +- } +- return 0; +-} +- +-static HWND show_wait_window(void) +-{ +- HWND hwnd = CreateDialogParamW( GetModuleHandleW(0), MAKEINTRESOURCEW(IDD_WAITDLG), 0, +- wait_dlgproc, (LPARAM)prettyprint_configdir() ); +- ShowWindow( hwnd, SW_SHOWNORMAL ); +- return hwnd; +-} +- + static HANDLE start_rundll32( const WCHAR *inf_path, const WCHAR *install, WORD machine ) + { + WCHAR app[MAX_PATH + ARRAY_SIZE(L"\\rundll32.exe" )]; +@@ -1606,7 +1575,6 @@ static void update_wineprefix( BOOL force ) + + if ((process = start_rundll32( inf_path, L"PreInstall", IMAGE_FILE_MACHINE_TARGET_HOST ))) + { +- HWND hwnd = show_wait_window(); + for (;;) + { + if (process) +@@ -1627,7 +1595,6 @@ static void update_wineprefix( BOOL force ) + process = start_rundll32( inf_path, L"Wow64Install", machines[count].Machine ); + count++; + } +- DestroyWindow( hwnd ); + } + install_root_pnp_devices(); + update_user_profile(); +-- +2.47.0 + diff --git a/9000-misc-additions/always-dynamic-spin.patch b/9000-misc-additions/always-dynamic-spin.patch new file mode 100644 index 0000000..0006c1e --- /dev/null +++ b/9000-misc-additions/always-dynamic-spin.patch @@ -0,0 +1,15 @@ +diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c +index 7847d37ffbf..8d97c8593dd 100644 +--- a/dlls/ntdll/sync.c ++++ b/dlls/ntdll/sync.c +@@ -227,9 +227,7 @@ NTSTATUS WINAPI RtlInitializeCriticalSectionAndSpinCount( RTL_CRITICAL_SECTION * + */ + NTSTATUS WINAPI RtlInitializeCriticalSectionEx( RTL_CRITICAL_SECTION *crit, ULONG spincount, ULONG flags ) + { +- if (NtCurrentTeb()->Peb->OSMajorVersion > 6 || +- (NtCurrentTeb()->Peb->OSMajorVersion == 6 && NtCurrentTeb()->Peb->OSMinorVersion >= 2)) +- flags |= RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN; ++ flags |= RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN; + + if (flags & RTL_CRITICAL_SECTION_FLAG_STATIC_INIT) + FIXME("(%p,%lu,0x%08lx) semi-stub\n", crit, spincount, flags); diff --git a/9000-misc-additions/dead-keys.patch b/9000-misc-additions/dead-keys.patch deleted file mode 100644 index 86bacee..0000000 --- a/9000-misc-additions/dead-keys.patch +++ /dev/null @@ -1,46 +0,0 @@ -https://bugs.winehq.org/show_bug.cgi?id=33368 - -diff -ur a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c -diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c -index 11111111111..11111111111 100644 ---- a/dlls/winex11.drv/event.c -+++ b/dlls/winex11.drv/event.c -@@ -435,6 +435,10 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X - count++; - if (XFilterEvent( &event, None )) - { -+ KeySym keysym = 0; -+ XLookupString(&event.xkey, NULL, 0, &keysym, NULL); -+ BOOL is_dead = (keysym >= XK_dead_grave && keysym <=XK_dead_semivoiced_sound); -+ - /* - * SCIM on linux filters key events strangely. It does not filter the - * KeyPress events for these keys however it does filter the -@@ -443,13 +447,12 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X - * - * We need to let those KeyRelease events be processed so that the - * keyboard state is correct. -+ * -+ * Moreover, let dead chars be processed or we will never have -+ * WM_DEADCHAR events - */ -- if (event.type == KeyRelease) -+ if (event.type == KeyRelease || is_dead) - { -- KeySym keysym = 0; -- XKeyEvent *keyevent = &event.xkey; -- -- XLookupString(keyevent, NULL, 0, &keysym, NULL); - if (!(keysym == XK_Shift_L || - keysym == XK_Shift_R || - keysym == XK_Control_L || -@@ -457,7 +460,8 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X - keysym == XK_Alt_R || - keysym == XK_Alt_L || - keysym == XK_Meta_R || -- keysym == XK_Meta_L)) -+ keysym == XK_Meta_L || -+ is_dead)) - continue; /* not a key we care about, ignore it */ - } - else diff --git a/9000-misc-additions/ntdll-Add-SystemLeapSecondInformation-info-class-to-.patch b/9000-misc-additions/ntdll-Add-SystemLeapSecondInformation-info-class-to-.patch new file mode 100644 index 0000000..7138b5f --- /dev/null +++ b/9000-misc-additions/ntdll-Add-SystemLeapSecondInformation-info-class-to-.patch @@ -0,0 +1,71 @@ +From c4fe4dace3bbd7df57440af62957b416096d8d6d Mon Sep 17 00:00:00 2001 +From: William Horvath +Date: Fri, 6 Dec 2024 19:48:25 -0800 +Subject: [PATCH] ntdll: Add SystemLeapSecondInformation info class to + NtQuerySystemInformation(). + +--- + dlls/ntdll/unix/system.c | 17 +++++++++++++++++ + dlls/wow64/system.c | 1 + + include/winternl.h | 5 +++++ + 3 files changed, 23 insertions(+) + +diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c +index 4acdbd95cd2..1ef70f8a969 100644 +--- a/dlls/ntdll/unix/system.c ++++ b/dlls/ntdll/unix/system.c +@@ -3622,6 +3622,23 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class, + case SystemCpuSetInformation: /* 175 */ + return NtQuerySystemInformationEx(class, NULL, 0, info, size, ret_size); + ++ case SystemLeapSecondInformation: /* 206 */ ++ { ++ SYSTEM_LEAP_SECOND_INFORMATION slsi; ++ ++ slsi.Enabled = FALSE; ++ slsi.Flags = 0; ++ ++ len = sizeof(slsi); ++ if (size >= len) ++ { ++ if (!info) ret = STATUS_ACCESS_VIOLATION; ++ else memcpy( info, &slsi, len ); ++ } ++ else ret = STATUS_INFO_LENGTH_MISMATCH; ++ break; ++ } ++ + /* Wine extensions */ + + case SystemWineVersionInformation: /* 1000 */ +diff --git a/dlls/wow64/system.c b/dlls/wow64/system.c +index 2f466d869dd..0172100e51e 100644 +--- a/dlls/wow64/system.c ++++ b/dlls/wow64/system.c +@@ -331,6 +331,7 @@ NTSTATUS WINAPI wow64_NtQuerySystemInformation( UINT *args ) + case SystemCodeIntegrityInformation: /* SYSTEM_CODEINTEGRITY_INFORMATION */ + case SystemKernelDebuggerInformationEx: /* SYSTEM_KERNEL_DEBUGGER_INFORMATION_EX */ + case SystemCpuSetInformation: /* SYSTEM_CPU_SET_INFORMATION */ ++ case SystemLeapSecondInformation: /* SYSTEM_LEAP_SECOND_INFORMATION */ + case SystemProcessorBrandString: /* char[] */ + case SystemProcessorFeaturesInformation: /* SYSTEM_PROCESSOR_FEATURES_INFORMATION */ + case SystemWineVersionInformation: /* char[] */ +diff --git a/include/winternl.h b/include/winternl.h +index 79d1689105a..1ae37134ade 100644 +--- a/include/winternl.h ++++ b/include/winternl.h +@@ -3063,6 +3063,11 @@ typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION_EX { + BOOLEAN DebuggerPresent; + } SYSTEM_KERNEL_DEBUGGER_INFORMATION_EX, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION_EX; + ++typedef struct _SYSTEM_LEAP_SECOND_INFORMATION { ++ BOOLEAN Enabled; ++ ULONG Flags; ++} SYSTEM_LEAP_SECOND_INFORMATION, *PSYSTEM_LEAP_SECOND_INFORMATION; ++ + typedef struct _VM_COUNTERS + { + SIZE_T PeakVirtualSize; +-- +2.47.1 + diff --git a/9000-misc-additions/opengl32-windowscodecs-winepulse-free-on-process-exit.patch b/9000-misc-additions/opengl32-windowscodecs-winepulse-free-on-process-exit.patch new file mode 100644 index 0000000..6bc56ee --- /dev/null +++ b/9000-misc-additions/opengl32-windowscodecs-winepulse-free-on-process-exit.patch @@ -0,0 +1,73 @@ +reverts f03c3a167c2e4abe92b1e1bf2ea5f7c31a07fc3b 6e9728bee52ac7e1f5a3d3bfe3bfaf5d9d1e01c1 505455de69acbc1390d2bf69313f1e76a19100ea +--- b/dlls/ntdll/unix/virtual.c ++++ a/dlls/ntdll/unix/virtual.c +@@ -4397,8 +4397,7 @@ + if (is_wow64()) + user_space_wow_limit = ((main_image_info.ImageCharacteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) ? limit_4g : limit_2g) - 1; + #ifndef __APPLE__ /* don't free the zerofill section on macOS */ +- else if ((main_image_info.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) && +- (main_image_info.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)) ++ else + free_reserved_memory( 0, (char *)0x7ffe0000 ); + #endif + } +--- b/dlls/opengl32/wgl.c ++++ a/dlls/opengl32/wgl.c +@@ -1281,7 +1281,6 @@ + break; + + case DLL_PROCESS_DETACH: +- if (reserved) break; + UNIX_CALL( process_detach, NULL ); + #ifndef _WIN64 + cleanup_wow64_strings(); +--- b/dlls/windowscodecs/main.c ++++ a/dlls/windowscodecs/main.c +@@ -44,7 +44,6 @@ + windowscodecs_module = hinstDLL; + break; + case DLL_PROCESS_DETACH: +- if (lpvReserved) break; + ReleaseComponentInfos(); + break; + } +--- b/dlls/winepulse.drv/mmdevdrv.c ++++ a/dlls/winepulse.drv/mmdevdrv.c +@@ -72,12 +72,10 @@ + + BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved) + { ++ if (reason == DLL_PROCESS_ATTACH) { ++ WCHAR buf[MAX_PATH]; ++ WCHAR *filename; +- WCHAR buf[MAX_PATH]; +- WCHAR *filename; + +- switch (reason) +- { +- case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(dll); + if (__wine_init_unix_call()) + return FALSE; +@@ -89,16 +87,11 @@ + + swprintf(drv_key_devicesW, ARRAY_SIZE(drv_key_devicesW), + L"Software\\Wine\\Drivers\\%s\\devices", filename); ++ } else if (reason == DLL_PROCESS_DETACH) { ++ struct device_cache *device, *device_next; ++ ++ LIST_FOR_EACH_ENTRY_SAFE(device, device_next, &g_devices_cache, struct device_cache, entry) ++ free(device); +- break; +- case DLL_PROCESS_DETACH: +- if (!reserved) +- { +- struct device_cache *device, *device_next; +- +- LIST_FOR_EACH_ENTRY_SAFE(device, device_next, &g_devices_cache, struct device_cache, entry) +- free(device); +- } +- break; + } + return TRUE; + } diff --git a/9000-misc-additions/osu-map-import-crash-fix.patch b/9000-misc-additions/osu-map-import-crash-fix.patch deleted file mode 100644 index 0c16605..0000000 --- a/9000-misc-additions/osu-map-import-crash-fix.patch +++ /dev/null @@ -1,13 +0,0 @@ -## osu! fix: disables assertion causing game to crash when importing maps -diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c -index 9e84ec3cc96..dfa2a2781bc 100644 ---- a/dlls/ntdll/unix/thread.c -+++ b/dlls/ntdll/unix/thread.c -@@ -1783,7 +1783,6 @@ NTSTATUS get_thread_context( HANDLE handle, void *context, BOOL *self, USHORT ma - */ - void ntdll_set_exception_jmp_buf( __wine_jmp_buf *jmp ) - { -- assert( !jmp || !ntdll_get_thread_data()->jmp_buf ); - ntdll_get_thread_data()->jmp_buf = jmp; - } - diff --git a/9000-misc-additions/per-source-cflags.patch b/9000-misc-additions/per-source-cflags.patch deleted file mode 100644 index e11a4ce..0000000 --- a/9000-misc-additions/per-source-cflags.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/tools/makedep.c b/tools/makedep.c -index 11111111111..11111111111 100644 ---- a/tools/makedep.c -+++ b/tools/makedep.c -@@ -3164,6 +3164,7 @@ static void output_source_one_arch( struct makefile *make, struct incl_file *sou - - output_filenames( cpp_flags ); - output_filename( var_cflags ); -+ output_filename( arch_make_variable( strmake( "%s_CFLAGS", basename( obj ) ), arch )); - output( "\n" ); - - if (make->testdll && strendswith( source->name, ".c" ) && diff --git a/9000-misc-additions/static-cpufreq-envvar.patch b/9000-misc-additions/static-cpufreq-envvar.patch new file mode 100644 index 0000000..ecd4b4d --- /dev/null +++ b/9000-misc-additions/static-cpufreq-envvar.patch @@ -0,0 +1,73 @@ +diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c +index 11111111111..11111111111 100644 +--- a/dlls/ntdll/unix/system.c ++++ b/dlls/ntdll/unix/system.c +@@ -4225,24 +4225,32 @@ NTSTATUS WINAPI NtPowerInformation( POWER_INFORMATION_LEVEL level, void *input, + char filename[128]; + FILE* f; + ++ static int fixed_cpufreq = -1; ++ if (fixed_cpufreq == -1) ++ { ++ fixed_cpufreq = !!getenv("WINE_STATIC_CPUFREQ"); ++ } + for(i = 0; i < out_cpus; i++) { +- snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", i); +- f = fopen(filename, "r"); +- if (f && (fscanf(f, "%u", &val) == 1)) { +- cpu_power[i].MaxMhz = val / 1000; +- fclose(f); +- cpu_power[i].CurrentMhz = cpu_power[i].MaxMhz; +- } +- else { +- if(i == 0) { +- cpu_power[0].CurrentMhz = mhz_from_cpuinfo(); +- if(cpu_power[0].CurrentMhz == 0) +- cpu_power[0].CurrentMhz = cannedMHz; ++ if (!fixed_cpufreq) ++ { ++ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", i); ++ f = fopen(filename, "r"); ++ if (f && (fscanf(f, "%u", &val) == 1)) { ++ cpu_power[i].MaxMhz = val / 1000; ++ fclose(f); ++ cpu_power[i].CurrentMhz = cpu_power[i].MaxMhz; ++ } ++ else { ++ if(i == 0) { ++ cpu_power[0].CurrentMhz = mhz_from_cpuinfo(); ++ if(cpu_power[0].CurrentMhz == 0) ++ cpu_power[0].CurrentMhz = cannedMHz; ++ } ++ else ++ cpu_power[i].CurrentMhz = cpu_power[0].CurrentMhz; ++ cpu_power[i].MaxMhz = cpu_power[i].CurrentMhz; ++ if(f) fclose(f); + } +- else +- cpu_power[i].CurrentMhz = cpu_power[0].CurrentMhz; +- cpu_power[i].MaxMhz = cpu_power[i].CurrentMhz; +- if(f) fclose(f); + } + + snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", i); +@@ -4253,10 +4261,15 @@ NTSTATUS WINAPI NtPowerInformation( POWER_INFORMATION_LEVEL level, void *input, + } + else + { +- cpu_power[i].MhzLimit = cpu_power[i].MaxMhz; ++ cpu_power[i].MhzLimit = (cpu_power[i].MaxMhz > 0 ? cpu_power[i].MaxMhz : cannedMHz); + if(f) fclose(f); + } + ++ if (fixed_cpufreq > 0) ++ { ++ cpu_power[i].CurrentMhz = cpu_power[i].MaxMhz = cpu_power[i].MhzLimit; ++ } ++ + cpu_power[i].Number = i; + cpu_power[i].MaxIdleState = 0; /* FIXME */ + cpu_power[i].CurrentIdleState = 0; /* FIXME */ +-- +0.0.0 + diff --git a/9000-misc-additions/wineboot-Skip-root-device-installation-if-WINE_INSTA.patch b/9000-misc-additions/wineboot-Skip-root-device-installation-if-WINE_INSTA.patch new file mode 100644 index 0000000..c698fa4 --- /dev/null +++ b/9000-misc-additions/wineboot-Skip-root-device-installation-if-WINE_INSTA.patch @@ -0,0 +1,36 @@ +From 1b6b6b0ff539fa7ac26c5bcf1bc7789152eeab82 Mon Sep 17 00:00:00 2001 +From: William Horvath +Date: Thu, 5 Dec 2024 18:11:18 -0800 +Subject: [PATCH] wineboot: Skip root device installation if + WINE_INSTALL_ROOT_DEVICES isn't in the environment. + +osu! doesn't need any of them. +--- + programs/wineboot/wineboot.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c +index 0353cd6d801..d4516f5afcd 100644 +--- a/programs/wineboot/wineboot.c ++++ b/programs/wineboot/wineboot.c +@@ -1704,6 +1704,7 @@ static void update_user_profile(void) + static void update_wineprefix( BOOL force ) + { + const WCHAR *config_dir = _wgetenv( L"WINECONFIGDIR" ); ++ const WCHAR *root_install = _wgetenv( L"WINE_INSTALL_ROOT_DEVICES" ); + WCHAR *inf_path = get_wine_inf_path(); + int fd; + struct stat st; +@@ -1754,7 +1755,8 @@ static void update_wineprefix( BOOL force ) + count++; + } + } +- install_root_pnp_devices(); ++ if (root_install) ++ install_root_pnp_devices(); + update_user_profile(); + + TRACE( "wine: configuration in %s has been updated.\n", debugstr_w(prettyprint_configdir()) ); +-- +2.47.1 + diff --git a/9000-misc-additions/winex11-Custom-frame-limiter-for-OpenGL.patch b/9000-misc-additions/winex11-Custom-frame-limiter-for-OpenGL.patch index 05e7e99..3195c7f 100644 --- a/9000-misc-additions/winex11-Custom-frame-limiter-for-OpenGL.patch +++ b/9000-misc-additions/winex11-Custom-frame-limiter-for-OpenGL.patch @@ -9,29 +9,28 @@ Subject: [PATCH] winex11: Custom frame limiter for OpenGL dlls/winex11.drv/x11drv_main.c | 26 +++++++++++++++ 3 files changed, 89 insertions(+) -Added in the use-clock_nanosleep-for-delay patch -# diff --git a/configure.ac b/configure.ac -# index d539ee50bda..7585324602c 100644 -# --- a/configure.ac -# +++ b/configure.ac -# @@ -2170,6 +2170,17 @@ case $host_os in -# ;; -# esac +diff --git a/configure.ac b/configure.ac +index d539ee50bda..7585324602c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2170,6 +2170,17 @@ case $host_os in + ;; + esac -# +dnl Check for clock_nanosleep which may be in -lrt -# +case $host_os in -# + darwin*|macosx*) ;; -# + *) ac_save_LIBS=$LIBS -# + AC_SEARCH_LIBS(clock_nanosleep, rt, -# + [AC_DEFINE(HAVE_CLOCK_NANOSLEEP, 1, [Define to 1 if you have the `clock_nanosleep' function.]) -# + test "$ac_res" = "none required" || AC_SUBST(RT_LIBS,"$ac_res")]) -# + LIBS=$ac_save_LIBS -# + ;; -# +esac -# + -# AC_CACHE_CHECK([for sched_setaffinity],wine_cv_have_sched_setaffinity, -# AC_LINK_IFELSE([AC_LANG_PROGRAM( -# [[#include ]], [[sched_setaffinity(0, 0, 0);]])],[wine_cv_have_sched_setaffinity=yes],[wine_cv_have_sched_setaffinity=no])) ++dnl Check for clock_nanosleep which may be in -lrt ++case $host_os in ++ darwin*|macosx*) ;; ++ *) ac_save_LIBS=$LIBS ++ AC_SEARCH_LIBS(clock_nanosleep, rt, ++ [AC_DEFINE(HAVE_CLOCK_NANOSLEEP, 1, [Define to 1 if you have the `clock_nanosleep' function.]) ++ test "$ac_res" = "none required" || AC_SUBST(RT_LIBS,"$ac_res")]) ++ LIBS=$ac_save_LIBS ++ ;; ++esac ++ + AC_CACHE_CHECK([for sched_setaffinity],wine_cv_have_sched_setaffinity, + AC_LINK_IFELSE([AC_LANG_PROGRAM( + [[#include ]], [[sched_setaffinity(0, 0, 0);]])],[wine_cv_have_sched_setaffinity=yes],[wine_cv_have_sched_setaffinity=no])) diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 008a92dad98..f46b03ca2e4 100644 --- a/dlls/winex11.drv/opengl.c diff --git a/9500-testing/0001-WIP-rawmouse-no-raw-pthread-optimize-atomics-barely-.patch b/9500-testing/0001-WIP-rawmouse-no-raw-pthread-optimize-atomics-barely-.patch deleted file mode 100644 index 1de871f..0000000 --- a/9500-testing/0001-WIP-rawmouse-no-raw-pthread-optimize-atomics-barely-.patch +++ /dev/null @@ -1,607 +0,0 @@ -From 41152ee7743e2a9ab88425e9ff02003e0f6bb544 Mon Sep 17 00:00:00 2001 -From: William Horvath -Date: Fri, 22 Nov 2024 20:37:03 -0800 -Subject: [PATCH] WIP: rawmouse: no raw pthread, optimize atomics (barely - tested), autograb - -based on work by Aeodyn ---- - dlls/win32u/cursoricon.c | 2 + - dlls/win32u/input.c | 3 + - dlls/win32u/message.c | 36 ++- - dlls/win32u/ntuser_private.h | 34 +++ - dlls/win32u/rawinput.c | 327 +++++++++++++++++++++++++ - dlls/winewayland.drv/wayland_pointer.c | 10 +- - dlls/winewayland.drv/waylanddrv.h | 1 + - dlls/winex11.drv/mouse.c | 8 +- - 8 files changed, 412 insertions(+), 9 deletions(-) - -diff --git a/dlls/win32u/cursoricon.c b/dlls/win32u/cursoricon.c -index c77b9d67e2d..57e528d4a1d 100644 ---- a/dlls/win32u/cursoricon.c -+++ b/dlls/win32u/cursoricon.c -@@ -98,6 +98,8 @@ INT WINAPI NtUserShowCursor( BOOL show ) - } - SERVER_END_REQ; - -+ rawmouse_grab(!show); -+ - TRACE("%d, count=%d\n", show, count ); - return count; - } -diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c -index 400dee04968..8ceda70ffe5 100644 ---- a/dlls/win32u/input.c -+++ b/dlls/win32u/input.c -@@ -1848,6 +1848,9 @@ static HWND set_focus_window( HWND hwnd ) - } - SERVER_END_REQ; - if (!ret) return 0; -+ -+ rawmouse_grab(hwnd == rawmouse_get_target()); -+ - if (previous == hwnd) return previous; - - if (previous) -diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c -index 698586375e9..2f61a58975e 100644 ---- a/dlls/win32u/message.c -+++ b/dlls/win32u/message.c -@@ -2770,6 +2770,34 @@ int peek_message( MSG *msg, const struct peek_message_filter *filter, BOOL waite - thread_info->client_info.msg_source = prev_source; - wake_mask = filter->mask & (QS_SENDMESSAGE | QS_SMRESULT); - -+ if ((signal_bits & QS_RAWINPUT) && rawmouse_msg(msg, hwnd, flags & PM_REMOVE)) { -+ thread_info->last_getmsg_time = NtGetTickCount(); -+ thread_info->client_info.message_time = NtGetTickCount(); -+ if (buffer != buffer_init) free( buffer ); -+ return 1; -+ } -+ -+ if (rawmouse.btn_event && rawmouse.btn_head != rawmouse.btn_tail) { -+ unsigned char tail = rawmouse.btn_tail; -+ msg->message = rawmouse.button_queue[tail].message; -+ msg->wParam = rawmouse.button_queue[tail].wparam; -+ msg->lParam = rawmouse.button_queue[tail].lparam; -+ msg->hwnd = rawmouse_get_target(); -+ msg->time = NtGetTickCount(); -+ -+ if (flags & PM_REMOVE) { -+ __atomic_store_n(&rawmouse.btn_tail, (tail + 1) & 63, __ATOMIC_SEQ_CST); -+ if (rawmouse.btn_head == ((tail + 1) & 63)) -+ NtClearEvent(rawmouse.btn_event); -+ } -+ -+ thread_info->last_getmsg_time = msg->time; -+ thread_info->client_info.message_time = msg->time; -+ if (buffer != buffer_init) free( buffer ); -+ return 1; -+ } -+ -+ - if ((!waited && (NtGetTickCount() - thread_info->last_getmsg_time < 3000)) && /* avoid hung queue */ - check_queue_bits( wake_mask, filter->mask, wake_mask | signal_bits, filter->mask | clear_bits, - &wake_bits, &changed_bits )) -@@ -3301,7 +3329,7 @@ BOOL WINAPI NtUserPeekMessage( MSG *msg_out, HWND hwnd, UINT first, UINT last, U - BOOL WINAPI NtUserGetMessage( MSG *msg, HWND hwnd, UINT first, UINT last ) - { - struct peek_message_filter filter = {.hwnd = hwnd, .first = first, .last = last}; -- HANDLE server_queue = get_server_queue_handle(); -+ HANDLE handles[] = {get_server_queue_handle(), rawmouse.event}; - unsigned int mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */ - int ret; - -@@ -3316,14 +3344,18 @@ BOOL WINAPI NtUserGetMessage( MSG *msg, HWND hwnd, UINT first, UINT last ) - if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER; - if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER; - if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT; -+ if ((first <= WM_INPUT) && (last >= WM_INPUT)) mask |= QS_RAWINPUT; - } - else mask = QS_ALLINPUT; - -+ if (rawmouse.event && (mask & QS_RAWINPUT) && rawmouse_msg(msg, hwnd, TRUE)) -+ return 1; -+ - filter.mask = mask; - filter.flags = PM_REMOVE | (mask << 16); - while (!(ret = peek_message( msg, &filter, TRUE ))) - { -- wait_objects( 1, &server_queue, INFINITE, mask & (QS_SENDMESSAGE | QS_SMRESULT), mask, 0 ); -+ wait_objects( (rawmouse.event && (mask & QS_RAWINPUT)) && (!hwnd || hwnd == rawmouse_get_target()) ? 2 : 1, handles, INFINITE, mask & (QS_SENDMESSAGE | QS_SMRESULT), mask, 0 ); - } - if (ret < 0) return -1; - -diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h -index 1f599bb00ea..c3c1395050d 100644 ---- a/dlls/win32u/ntuser_private.h -+++ b/dlls/win32u/ntuser_private.h -@@ -246,4 +246,38 @@ WND *get_win_ptr( HWND hwnd ); - BOOL is_child( HWND parent, HWND child ); - BOOL is_window( HWND hwnd ); - -+struct button_message { -+ DWORD message; -+ WPARAM wparam; -+ LPARAM lparam; -+}; -+ -+struct _rawmouse { -+ BOOL enabled; -+ BOOL grab; -+ int fd; -+ HANDLE thread; -+ HANDLE event; -+ HWND target; -+ RAWMOUSE data[256]; -+ union { -+ short headtail; -+ struct { unsigned char tail, head; }; -+ }; -+ unsigned char msg_pend; -+ struct button_message button_queue[64]; -+ unsigned char btn_head, btn_tail; -+ HANDLE btn_event; -+}; -+ -+typedef struct { -+ RAWINPUTHEADER header; -+ RAWMOUSE data; -+} RAWINPUTM; -+ -+extern struct _rawmouse rawmouse; -+ -+HWND rawmouse_get_target(void); -+void rawmouse_grab(BOOL grab); -+ - #endif /* __WINE_NTUSER_PRIVATE_H */ -diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c -index a1dfcd463c6..cdb962979d4 100644 ---- a/dlls/win32u/rawinput.c -+++ b/dlls/win32u/rawinput.c -@@ -25,6 +25,11 @@ - - #include - #include -+#include -+#include -+#include -+#include -+#include - - #include "win32u_private.h" - #include "ntuser_private.h" -@@ -67,6 +72,292 @@ static unsigned int registered_device_count; - static struct list devices = LIST_INIT( devices ); - static pthread_mutex_t rawinput_mutex = PTHREAD_MUTEX_INITIALIZER; - -+struct _rawmouse rawmouse = {.fd = -1, .target = (HWND)(-1)}; -+ -+static void queue_button_message(DWORD message, WPARAM wparam, LPARAM lparam) { -+ unsigned char next = (rawmouse.btn_head + 1) & 63; -+ unsigned char tail = __atomic_load_n(&rawmouse.btn_tail, __ATOMIC_RELAXED); -+ -+ if (next != tail) { -+ rawmouse.button_queue[rawmouse.btn_head].message = message; -+ rawmouse.button_queue[rawmouse.btn_head].wparam = wparam; -+ rawmouse.button_queue[rawmouse.btn_head].lparam = lparam; -+ -+ __atomic_store_n(&rawmouse.btn_head, next, __ATOMIC_RELEASE); -+ NtSetEvent(rawmouse.btn_event, NULL); -+ } -+} -+ -+static inline unsigned char rawmouse_count(void) { -+ unsigned short ht = __atomic_load_n(&rawmouse.headtail, __ATOMIC_RELAXED); -+ return (ht >> 8) - (ht & 0xFF); -+} -+ -+static unsigned char rawmouse_inc(void) { -+ unsigned char r, t = 0; -+ if (rawmouse_count() == 255) -+ r = __atomic_load_n(&rawmouse.head, __ATOMIC_RELAXED); -+ else -+ r = __atomic_add_fetch(&rawmouse.head, 1, __ATOMIC_RELAXED); -+ -+ if (__atomic_compare_exchange_n(&rawmouse.msg_pend, &t, 1, false, -+ __ATOMIC_RELEASE, __ATOMIC_RELAXED) && rawmouse.event) -+ NtSetEvent(rawmouse.event, NULL); -+ else if (t < 255) { -+ if (!__atomic_add_fetch(&rawmouse.msg_pend, 1, __ATOMIC_RELAXED)) -+ __atomic_fetch_sub(&rawmouse.msg_pend, 1, __ATOMIC_RELAXED); -+ } -+ return r; -+} -+ -+static unsigned char rawmouse_dec(unsigned char *tail) { -+ unsigned char r = rawmouse_count(); -+ switch (r) { -+ case 0: -+ return 0; -+ case 1: -+ __atomic_store_n(&rawmouse.msg_pend, 0, __ATOMIC_RELAXED); -+ NtClearEvent(rawmouse.event); -+ } -+ -+ *tail = __atomic_fetch_add(&rawmouse.tail, 1, __ATOMIC_RELAXED); -+ return r; -+} -+ -+static unsigned char rawmouse_check(unsigned char remove) { -+ if (remove) { -+ unsigned char t = 1; -+ if (__atomic_compare_exchange_n(&rawmouse.msg_pend, &t, 0, false, -+ __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) { -+ NtClearEvent(rawmouse.event); -+ return 1; -+ } -+ return t ? __atomic_fetch_sub(&rawmouse.msg_pend, 1, __ATOMIC_RELAXED) : 0; -+ } -+ -+ return __atomic_load_n(&rawmouse.msg_pend, __ATOMIC_RELAXED); -+} -+ -+static void rawmouse_clear(void) { -+ __atomic_clear(&rawmouse.msg_pend, __ATOMIC_RELEASE); -+ if (rawmouse.event) -+ NtClearEvent(rawmouse.event); -+ __atomic_store_n(&rawmouse.headtail, 0, __ATOMIC_RELAXED); -+ memset(rawmouse.data, 0, sizeof(rawmouse.data)); -+ return; -+} -+ -+HWND rawmouse_get_target(void) { -+ return __atomic_load_n(&rawmouse.target, __ATOMIC_SEQ_CST); -+} -+ -+void rawmouse_grab(BOOL grab) { -+ if (!rawmouse.enabled || !rawmouse.grab || rawmouse.fd == -1) return; -+ ioctl(rawmouse.fd, EVIOCGRAB, grab); -+} -+ -+static NTSTATUS WINAPI rawmouse_reader_thread(void) -+{ -+ RAWMOUSE* out; -+ int bytes; -+ struct input_event in; -+ struct input_absinfo absinfo_x, absinfo_y; -+ int priority = THREAD_PRIORITY_TIME_CRITICAL; -+ -+ absinfo_x.minimum = 0; -+ absinfo_x.maximum = 65535; -+ absinfo_y.minimum = 0; -+ absinfo_y.maximum = 65535; -+ -+ NtSetInformationThread(GetCurrentThread(), ThreadBasePriority, -+ &priority, sizeof(priority)); -+ -+ setpriority(PRIO_PROCESS, getpid(), -12); -+ -+ ioctl(rawmouse.fd, EVIOCGABS(ABS_X), &absinfo_x); -+ ioctl(rawmouse.fd, EVIOCGABS(ABS_Y), &absinfo_y); -+ -+ out = rawmouse.data; -+ -+ while (1) { -+ bytes = read(rawmouse.fd, &in, sizeof(in)); -+ if (rawmouse_get_target() == (HWND)(-1)) -+ continue; -+ -+ if (bytes < 0) { -+ ERR("Failed to read from rawmouse device: %d\n", errno); -+ continue; -+ } -+ -+ switch (in.type) { -+ case EV_REL: -+ switch (in.code) { -+ case REL_X: -+ __atomic_fetch_add(&out->lLastX, (int)in.value, __ATOMIC_RELAXED); -+ break; -+ case REL_Y: -+ __atomic_fetch_add(&out->lLastY, (int)in.value, __ATOMIC_RELAXED); -+ break; -+ case REL_WHEEL: -+ __atomic_fetch_or(&out->usButtonFlags, RI_MOUSE_WHEEL, __ATOMIC_RELAXED); -+ __atomic_fetch_add(&out->usButtonData, (int)in.value, __ATOMIC_RELAXED); -+ break; -+ } -+ break; -+ case EV_ABS: -+ switch (in.code) { -+ case ABS_X: -+ absinfo_x.value = in.value; -+ break; -+ case ABS_Y: -+ absinfo_y.value = in.value; -+ break; -+ } -+ __atomic_store_n(&out->lLastX, (int)((absinfo_x.value - absinfo_x.minimum) * 65535./(absinfo_x.maximum - absinfo_x.minimum)), __ATOMIC_RELAXED); -+ __atomic_store_n(&out->lLastY, (int)((absinfo_y.value - absinfo_y.minimum) * 65535./(absinfo_y.maximum - absinfo_y.minimum)), __ATOMIC_RELAXED); -+ __atomic_fetch_or(&out->usFlags, MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP, __ATOMIC_RELAXED); -+ break; -+ case EV_KEY: -+ switch (in.code) { -+ case BTN_LEFT: -+ case BTN_TOUCH: -+ case BTN_STYLUS: -+ __atomic_fetch_or(&out->usButtonFlags, in.value ? RI_MOUSE_LEFT_BUTTON_DOWN : RI_MOUSE_LEFT_BUTTON_UP, __ATOMIC_RELAXED); -+ queue_button_message(in.value ? WM_LBUTTONDOWN : WM_LBUTTONUP, 0, MAKELPARAM(0, 0)); -+ break; -+ case BTN_RIGHT: -+ case BTN_STYLUS2: -+ __atomic_fetch_or(&out->usButtonFlags, in.value ? RI_MOUSE_RIGHT_BUTTON_DOWN : RI_MOUSE_RIGHT_BUTTON_UP, __ATOMIC_RELAXED); -+ queue_button_message(in.value ? WM_RBUTTONDOWN : WM_RBUTTONUP, 0, MAKELPARAM(0, 0)); -+ break; -+ case BTN_MIDDLE: -+ __atomic_fetch_or(&out->usButtonFlags, in.value ? RI_MOUSE_MIDDLE_BUTTON_DOWN : RI_MOUSE_MIDDLE_BUTTON_UP, __ATOMIC_RELAXED); -+ break; -+ case BTN_SIDE: -+ __atomic_fetch_or(&out->usButtonFlags, in.value ? RI_MOUSE_BUTTON_4_DOWN : RI_MOUSE_BUTTON_4_UP, __ATOMIC_RELAXED); -+ break; -+ case BTN_EXTRA: -+ __atomic_fetch_or(&out->usButtonFlags, in.value ? RI_MOUSE_BUTTON_5_DOWN : RI_MOUSE_BUTTON_5_UP, __ATOMIC_RELAXED); -+ break; -+ } -+ break; -+ case EV_SYN: -+ out = rawmouse.data + rawmouse_inc(); -+ break; -+ } -+ } -+ return 0; -+} -+ -+static bool create_rawmouse_thread(void) -+{ -+ NTSTATUS status; -+ -+ status = NtCreateEvent(&rawmouse.event, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); -+ if (!NT_SUCCESS(status)) return false; -+ -+ status = NtCreateEvent(&rawmouse.btn_event, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); -+ if (!NT_SUCCESS(status)) return false; -+ -+ status = NtCreateThreadEx(&rawmouse.thread, -+ THREAD_ALL_ACCESS, -+ NULL, -+ NtCurrentProcess(), -+ rawmouse_reader_thread, -+ NULL, -+ 0, 0, 0, 0, NULL); -+ -+ if (!NT_SUCCESS(status)) -+ { -+ ERR("Failed to create rawmouse thread\n"); -+ NtClose(rawmouse.event); -+ NtClose(rawmouse.btn_event); -+ rawmouse.event = NULL; -+ rawmouse.btn_event = NULL; -+ return false; -+ } -+ return true; -+} -+ -+bool rawmouse_register(HWND target) { -+ char* env = getenv("RAWMOUSE"); -+ if (!(rawmouse.enabled = env && *env)) -+ return false; -+ -+ char* grabenv = getenv("RAWMOUSE_GRAB"); -+ rawmouse.grab = !(grabenv && *grabenv == '0'); -+ -+ if (rawmouse.fd == -1) { -+ rawmouse.fd = open(env, O_RDONLY); -+ if (rawmouse.fd == -1) { -+ ERR("rawmouse_register: failed opening %s, error=%d\n", env, errno); -+ rawmouse.enabled = false; -+ return false; -+ } -+ TRACE("rawmouse_register: opened %s, fd=%d\n", env, rawmouse.fd); -+ } -+ -+ if (!rawmouse.event && !rawmouse.btn_event) -+ { -+ if (!create_rawmouse_thread()) -+ { -+ ERR("rawmouse_register: failed to create thread\n"); -+ rawmouse.enabled = false; -+ return false; -+ } -+ } -+ -+ rawmouse_clear(); -+ __atomic_store_n(&rawmouse.target, target, __ATOMIC_SEQ_CST); -+ rawmouse_grab(TRUE); -+ rawmouse.btn_head = rawmouse.btn_tail = 0; -+ -+ return true; -+} -+ -+void rawmouse_unregister(void) { -+ __atomic_store_n(&rawmouse.target, (HWND)(-1), __ATOMIC_SEQ_CST); -+ rawmouse_clear(); -+ rawmouse_grab(FALSE); -+ return; -+} -+ -+unsigned int rawmouse_fetch(RAWMOUSE *buffer) { -+ unsigned char t; -+ unsigned char c = rawmouse_dec(&t); -+ if (!c) return 0; -+ memset(buffer, 0, sizeof(RAWMOUSE)); -+ do { -+ buffer->usFlags |= __atomic_exchange_n(&rawmouse.data[t].usFlags, 0, __ATOMIC_RELAXED); -+ buffer->lLastX += __atomic_exchange_n(&rawmouse.data[t].lLastX, 0, __ATOMIC_RELAXED); -+ buffer->lLastY += __atomic_exchange_n(&rawmouse.data[t].lLastY, 0, __ATOMIC_RELAXED); -+ buffer->ulButtons |= __atomic_exchange_n(&rawmouse.data[t].ulButtons, 0, __ATOMIC_RELAXED); -+ } while (c > (unsigned short)__atomic_load_n(&rawmouse.msg_pend, __ATOMIC_RELAXED) + 1 && (c = rawmouse_dec(&t))); -+ -+ return sizeof(RAWINPUTM); -+} -+ -+unsigned char rawmouse_msg(MSG *msg, HWND hwnd, unsigned char remove) { -+ HWND target; -+ -+ if (!rawmouse.thread) -+ return 0; -+ -+ target = rawmouse_get_target(); -+ -+ if (hwnd && hwnd != target) -+ return 0; -+ -+ if (!rawmouse_check(remove)) -+ return 0; -+ -+ msg->hwnd = target; -+ msg->message = WM_INPUT; -+ msg->lParam = (LPARAM)0; -+ return 1; -+} -+ -+ - static struct device *add_device( HKEY key, DWORD type ) - { - static const WCHAR symbolic_linkW[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0}; -@@ -479,6 +770,21 @@ UINT WINAPI NtUserGetRawInputBuffer( RAWINPUT *data, UINT *data_size, UINT heade - /* with old WOW64 mode we didn't go through the WOW64 thunks, patch the header size here */ - if (NtCurrentTeb()->WowTebOffset) header_size = sizeof(RAWINPUTHEADER64); - -+ if (count = rawmouse_count()) { -+ if (data == NULL) { -+ *data_size = sizeof(RAWINPUTM); -+ return 0; -+ } -+ -+ RAWINPUTM *datam = data; -+ if (count * sizeof(RAWINPUTM) > *data_size) { -+ count = *data_size / sizeof(RAWINPUTM); -+ } -+ for (int i = 0; i < count; ++i) -+ rawmouse_fetch(&datam[i].data); -+ return count; -+ } -+ - thread_info = get_user_thread_info(); - SERVER_START_REQ( get_rawinput_buffer ) - { -@@ -507,6 +813,18 @@ UINT WINAPI NtUserGetRawInputData( HRAWINPUT handle, UINT command, void *data, U - TRACE( "handle %p, command %#x, data %p, data_size %p, header_size %u.\n", - handle, command, data, data_size, header_size ); - -+ if (!handle) { -+ const RAWINPUTHEADER header = {.dwType = RIM_TYPEMOUSE, .dwSize = sizeof(RAWINPUTM), .hDevice = WINE_MOUSE_HANDLE, .wParam = 0}; -+ if (command == RID_HEADER && rawmouse_count()) { -+ rawinput->header = header; -+ return sizeof(RAWINPUTHEADER); -+ } -+ if (rawmouse_fetch(&rawinput->data.mouse)) { -+ rawinput->header = header; -+ return sizeof(RAWINPUTM); -+ } else return -1; -+ } -+ - if (!(msg_data = thread_info->rawinput) || msg_data->hw_id != (UINT_PTR)handle) - { - RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); -@@ -724,6 +1042,15 @@ BOOL WINAPI NtUserRegisterRawInputDevices( const RAWINPUTDEVICE *devices, UINT d - - rawinput_update_device_list( TRUE ); - -+ for (i = 0; i < device_count; ++i) { -+ if ((devices+i)->usUsagePage == 1 && (devices+i)->usUsage == 2) { -+ if ((devices+i)->dwFlags & RIDEV_REMOVE) -+ rawmouse_unregister(); -+ else -+ rawmouse_register((devices+i)->hwndTarget); -+ } -+ } -+ - registered_devices = new_registered_devices; - for (i = 0; i < device_count; ++i) register_rawinput_device( devices + i ); - -diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c -index 6c778f5566a..acf0b77e890 100644 ---- a/dlls/winewayland.drv/wayland_pointer.c -+++ b/dlls/winewayland.drv/wayland_pointer.c -@@ -98,7 +98,7 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, - struct wayland_pointer *pointer = &process_wayland.pointer; - - /* Ignore absolute motion events if in relative mode. */ -- if (pointer->zwp_relative_pointer_v1) return; -+ if (pointer->disable || pointer->zwp_relative_pointer_v1) return; - - pointer_handle_motion_internal(sx, sy); - } -@@ -157,7 +157,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, - INPUT input = {0}; - HWND hwnd; - -- if (!(hwnd = wayland_pointer_get_focused_hwnd())) return; -+ if (pointer->disable || !(hwnd = wayland_pointer_get_focused_hwnd())) return; - - input.type = INPUT_MOUSE; - -@@ -216,7 +216,7 @@ static void pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_point - INPUT input = {0}; - HWND hwnd; - -- if (!(hwnd = wayland_pointer_get_focused_hwnd())) return; -+ if (process_wayland.pointer.disable || !(hwnd = wayland_pointer_get_focused_hwnd())) return; - - input.type = INPUT_MOUSE; - -@@ -846,8 +846,8 @@ static void wayland_pointer_update_constraint(struct wl_surface *wl_surface, - needs_relative = !pointer->cursor.wl_surface && - pointer->constraint_hwnd && - pointer->constraint_hwnd == pointer->focused_hwnd; -- -- if (needs_relative && !pointer->zwp_relative_pointer_v1) -+ pointer->disable = needs_relative && getenv("RAWMOUSE") && *getenv("RAWMOUSE"); -+ if (!pointer->disable && needs_relative && !pointer->zwp_relative_pointer_v1) - { - pointer->zwp_relative_pointer_v1 = - zwp_relative_pointer_manager_v1_get_relative_pointer( -diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h -index 05083abc3fa..e6eb50b681a 100644 ---- a/dlls/winewayland.drv/waylanddrv.h -+++ b/dlls/winewayland.drv/waylanddrv.h -@@ -110,6 +110,7 @@ struct wayland_pointer - uint32_t button_serial; - struct wayland_cursor cursor; - pthread_mutex_t mutex; -+ BOOL disable; - }; - - struct wayland_seat -diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c -index f2201b8eeb2..332585fdb30 100644 ---- a/dlls/winex11.drv/mouse.c -+++ b/dlls/winex11.drv/mouse.c -@@ -366,6 +366,10 @@ void x11drv_xinput2_enable( Display *display, Window window ) - struct x11drv_thread_data *thread_data = x11drv_thread_data(); - XIEventMask mask; - unsigned char mask_bits[XIMaskLen(XI_LASTEVENT)]; -+ const char *rawmouse = getenv("RAWMOUSE"); -+ const char *rawmouse_grab = getenv("RAWMOUSE_GRAB"); -+ BOOL rawmouse_active = (rawmouse && *rawmouse != '\0' && *rawmouse != '0'); -+ BOOL raw_grabbed = rawmouse_active && !(rawmouse_grab && *rawmouse_grab == '0'); - - if (!xinput2_available) return; - -@@ -377,10 +381,10 @@ void x11drv_xinput2_enable( Display *display, Window window ) - if (window == DefaultRootWindow( display )) - { - XISetMask( mask_bits, XI_DeviceChanged ); -- XISetMask( mask_bits, XI_RawMotion ); -+ if (!rawmouse_active || raw_grabbed) XISetMask( mask_bits, XI_RawMotion ); - if (!thread_data->xinput2_rawinput) - XISetMask( mask_bits, XI_ButtonPress ); -- else -+ else if(!rawmouse_active || raw_grabbed) - { - XISetMask( mask_bits, XI_RawButtonPress ); - XISetMask( mask_bits, XI_RawButtonRelease ); --- -2.47.0 - diff --git a/9500-testing/0002-WIP-rawmouse-use-SynchronizationEvent-for-motion.patch b/9500-testing/0002-WIP-rawmouse-use-SynchronizationEvent-for-motion.patch deleted file mode 100644 index e093d86..0000000 --- a/9500-testing/0002-WIP-rawmouse-use-SynchronizationEvent-for-motion.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 8c9cc418e2ac55d5fe18c7872aa8e1875d1c12d2 Mon Sep 17 00:00:00 2001 -From: William Horvath -Date: Fri, 22 Nov 2024 21:19:03 -0800 -Subject: [PATCH] WIP: rawmouse: use SynchronizationEvent for motion - ---- - dlls/win32u/rawinput.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c -index cdb962979d4..caba1c6728a 100644 ---- a/dlls/win32u/rawinput.c -+++ b/dlls/win32u/rawinput.c -@@ -117,7 +117,6 @@ static unsigned char rawmouse_dec(unsigned char *tail) { - return 0; - case 1: - __atomic_store_n(&rawmouse.msg_pend, 0, __ATOMIC_RELAXED); -- NtClearEvent(rawmouse.event); - } - - *tail = __atomic_fetch_add(&rawmouse.tail, 1, __ATOMIC_RELAXED); -@@ -129,7 +128,6 @@ static unsigned char rawmouse_check(unsigned char remove) { - unsigned char t = 1; - if (__atomic_compare_exchange_n(&rawmouse.msg_pend, &t, 0, false, - __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) { -- NtClearEvent(rawmouse.event); - return 1; - } - return t ? __atomic_fetch_sub(&rawmouse.msg_pend, 1, __ATOMIC_RELAXED) : 0; -@@ -140,11 +138,8 @@ static unsigned char rawmouse_check(unsigned char remove) { - - static void rawmouse_clear(void) { - __atomic_clear(&rawmouse.msg_pend, __ATOMIC_RELEASE); -- if (rawmouse.event) -- NtClearEvent(rawmouse.event); - __atomic_store_n(&rawmouse.headtail, 0, __ATOMIC_RELAXED); - memset(rawmouse.data, 0, sizeof(rawmouse.data)); -- return; - } - - HWND rawmouse_get_target(void) { -@@ -253,11 +248,16 @@ static bool create_rawmouse_thread(void) - { - NTSTATUS status; - -- status = NtCreateEvent(&rawmouse.event, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); -+ status = NtCreateEvent(&rawmouse.event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); - if (!NT_SUCCESS(status)) return false; - - status = NtCreateEvent(&rawmouse.btn_event, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); -- if (!NT_SUCCESS(status)) return false; -+ if (!NT_SUCCESS(status)) -+ { -+ NtClose(rawmouse.event); -+ rawmouse.event = NULL; -+ return false; -+ } - - status = NtCreateThreadEx(&rawmouse.thread, - THREAD_ALL_ACCESS, --- -2.47.0 - diff --git a/staging-commit b/staging-commit index a145d78..b83db7e 100644 --- a/staging-commit +++ b/staging-commit @@ -1 +1 @@ -7ba8823e57e0a32c1373e5c304542c7ce578699c \ No newline at end of file +4f96088b1e12db6134dff4090797c3d61b05833d \ No newline at end of file diff --git a/staging-exclude b/staging-exclude index 9f7d086..f1155f4 100644 --- a/staging-exclude +++ b/staging-exclude @@ -1 +1 @@ --W eventfd_synchronization \ No newline at end of file +-W eventfd_synchronization -W wined3d-unset-flip-gdi \ No newline at end of file diff --git a/wine-commit b/wine-commit index 5035c9f..d6639d8 100644 --- a/wine-commit +++ b/wine-commit @@ -1 +1 @@ -51ccd95c49c2c61ad41960b25a01f834601d70c0 \ No newline at end of file +4161e62e478f61fdcd0365d9bd7b21e3b1a5197b \ No newline at end of file