diff --git a/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0001-ntdll-Wrap-current-modref-variable-in-a-new-structure.patch b/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0001-ntdll-Wrap-current-modref-variable-in-a-new-structure.patch new file mode 100644 index 0000000..30b7636 --- /dev/null +++ b/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0001-ntdll-Wrap-current-modref-variable-in-a-new-structure.patch @@ -0,0 +1,221 @@ +From ed184da3508b21c2e3b66de5708eced69ab4102e Mon Sep 17 00:00:00 2001 +From: Jinoh Kang +Date: Thu, 18 Apr 2024 23:58:21 +0900 +Subject: [PATCH] ntdll: Wrap current_modref variable in a new structure. + +Prepare for adding context information (e.g. static or dynamic) about +the current importer, which is needed for correct RelayFromExclude +handling. +--- + dlls/ntdll/loader.c | 70 ++++++++++++++++++++++++++++++--------------- + 1 file changed, 47 insertions(+), 23 deletions(-) + +diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c +index 2f2a7fe5427..0ce704da2b5 100644 +--- a/dlls/ntdll/loader.c ++++ b/dlls/ntdll/loader.c +@@ -181,9 +181,16 @@ static RTL_BITMAP tls_bitmap; + static RTL_BITMAP tls_expansion_bitmap; + + static WINE_MODREF *cached_modref; +-static WINE_MODREF *current_modref; + static WINE_MODREF *last_failed_modref; + ++struct importer ++{ ++ struct importer *prev; ++ WINE_MODREF *modref; ++}; ++ ++static struct importer *current_importer; ++ + static LDR_DDAG_NODE *node_ntdll, *node_kernel32; + + static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, DWORD flags, WINE_MODREF** pwm, BOOL system ); +@@ -563,6 +570,20 @@ static ULONG_PTR allocate_stub( const char *dll, const char *name ) + static inline ULONG_PTR allocate_stub( const char *dll, const char *name ) { return 0xdeadbeef; } + #endif /* __i386__ */ + ++/* The loader_section must be locked while calling this function. */ ++static void push_importer( struct importer *importer, WINE_MODREF *modref ) ++{ ++ importer->modref = modref; ++ importer->prev = current_importer; ++ current_importer = importer; ++} ++ ++/* The loader_section must be locked while calling this function. */ ++static void pop_importer( struct importer *importer ) ++{ ++ current_importer = importer->prev; ++} ++ + /* call ldr notifications */ + static void call_ldr_notifications( ULONG reason, LDR_DATA_TABLE_ENTRY *module ) + { +@@ -788,7 +809,7 @@ static NTSTATUS build_import_name( WCHAR buffer[256], const char *import, int le + { + const API_SET_NAMESPACE *map = NtCurrentTeb()->Peb->ApiSetMap; + const API_SET_NAMESPACE_ENTRY *entry; +- const WCHAR *host = current_modref ? current_modref->ldr.BaseDllName.Buffer : NULL; ++ const WCHAR *host = current_importer ? current_importer->modref->ldr.BaseDllName.Buffer : NULL; + UNICODE_STRING str; + + while (len && import[len-1] == ' ') len--; /* remove trailing spaces */ +@@ -972,9 +993,9 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS + if (load_dll( load_path, mod_name, 0, &wm, imp->system ) == STATUS_SUCCESS && + !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) + { +- if (!imports_fixup_done && current_modref) ++ if (!imports_fixup_done && current_importer) + { +- add_module_dependency( current_modref->ldr.DdagNode, wm->ldr.DdagNode ); ++ add_module_dependency( current_importer->modref->ldr.DdagNode, wm->ldr.DdagNode ); + } + else if (process_attach( wm->ldr.DdagNode, NULL ) != STATUS_SUCCESS) + { +@@ -1042,12 +1063,12 @@ static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY + + if (TRACE_ON(snoop)) + { +- const WCHAR *user = current_modref ? current_modref->ldr.BaseDllName.Buffer : NULL; ++ const WCHAR *user = current_importer ? current_importer->modref->ldr.BaseDllName.Buffer : NULL; + proc = SNOOP_GetProcAddress( module, exports, exp_size, proc, ordinal, user ); + } + if (TRACE_ON(relay)) + { +- const WCHAR *user = current_modref ? current_modref->ldr.BaseDllName.Buffer : NULL; ++ const WCHAR *user = current_importer ? current_importer->modref->ldr.BaseDllName.Buffer : NULL; + proc = RELAY_GetProcAddress( module, exports, exp_size, proc, ordinal, user ); + } + return proc; +@@ -1140,7 +1161,8 @@ void * WINAPI RtlFindExportedRoutineByName( HMODULE module, const char *name ) + */ + static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LPCWSTR load_path, WINE_MODREF **pwm ) + { +- BOOL system = current_modref->system || (current_modref->ldr.Flags & LDR_WINE_INTERNAL); ++ struct importer *importer = current_importer; ++ BOOL system = importer->modref->system || (importer->modref->ldr.Flags & LDR_WINE_INTERNAL); + NTSTATUS status; + WINE_MODREF *wmImp; + HMODULE imp_mod; +@@ -1175,10 +1197,10 @@ static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LP + { + if (status == STATUS_DLL_NOT_FOUND) + ERR("Library %s (which is needed by %s) not found\n", +- name, debugstr_w(current_modref->ldr.FullDllName.Buffer)); ++ name, debugstr_w(importer->modref->ldr.FullDllName.Buffer)); + else + ERR("Loading library %s (which is needed by %s) failed (error %lx).\n", +- name, debugstr_w(current_modref->ldr.FullDllName.Buffer), status); ++ name, debugstr_w(importer->modref->ldr.FullDllName.Buffer), status); + return FALSE; + } + +@@ -1211,7 +1233,7 @@ static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LP + thunk_list->u1.Function = allocate_stub( name, (const char*)pe_name->Name ); + } + WARN(" imported from %s, allocating stub %p\n", +- debugstr_w(current_modref->ldr.FullDllName.Buffer), ++ debugstr_w(importer->modref->ldr.FullDllName.Buffer), + (void *)thunk_list->u1.Function ); + import_list++; + thunk_list++; +@@ -1231,7 +1253,7 @@ static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LP + { + thunk_list->u1.Function = allocate_stub( name, IntToPtr(ordinal) ); + WARN("No implementation for %s.%d imported from %s, setting to %p\n", +- name, ordinal, debugstr_w(current_modref->ldr.FullDllName.Buffer), ++ name, ordinal, debugstr_w(importer->modref->ldr.FullDllName.Buffer), + (void *)thunk_list->u1.Function ); + } + TRACE_(imports)("--- Ordinal %s.%d = %p\n", name, ordinal, (void *)thunk_list->u1.Function ); +@@ -1247,7 +1269,7 @@ static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LP + { + thunk_list->u1.Function = allocate_stub( name, (const char*)pe_name->Name ); + WARN("No implementation for %s.%s imported from %s, setting to %p\n", +- name, pe_name->Name, debugstr_w(current_modref->ldr.FullDllName.Buffer), ++ name, pe_name->Name, debugstr_w(importer->modref->ldr.FullDllName.Buffer), + (void *)thunk_list->u1.Function ); + } + TRACE_(imports)("--- %s %s.%d = %p\n", +@@ -1446,21 +1468,21 @@ static void free_tls_slot( LDR_DATA_TABLE_ENTRY *mod ) + */ + static NTSTATUS fixup_imports_ilonly( WINE_MODREF *wm, LPCWSTR load_path, void **entry ) + { ++ struct importer importer; + NTSTATUS status; + void *proc; + const char *name; +- WINE_MODREF *prev, *imp; ++ WINE_MODREF *imp; + + if (!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) return STATUS_SUCCESS; /* already done */ + wm->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS; + +- prev = current_modref; +- current_modref = wm; ++ push_importer( &importer, wm ); + assert( !wm->ldr.DdagNode->Dependencies.Tail ); + if (!(status = load_dll( load_path, L"mscoree.dll", 0, &imp, FALSE )) + && !add_module_dependency_after( wm->ldr.DdagNode, imp->ldr.DdagNode, NULL )) + status = STATUS_NO_MEMORY; +- current_modref = prev; ++ pop_importer( &importer ); + if (status) + { + ERR( "mscoree.dll not found, IL-only binary %s cannot be loaded\n", +@@ -1487,7 +1509,8 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path ) + { + const IMAGE_IMPORT_DESCRIPTOR *imports; + SINGLE_LIST_ENTRY *dep_after; +- WINE_MODREF *prev, *imp; ++ struct importer importer; ++ WINE_MODREF *imp; + int i, nb_imports; + DWORD size; + NTSTATUS status; +@@ -1513,8 +1536,7 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path ) + /* load the imported modules. They are automatically + * added to the modref list of the process. + */ +- prev = current_modref; +- current_modref = wm; ++ push_importer( &importer, wm ); + status = STATUS_SUCCESS; + for (i = 0; i < nb_imports; i++) + { +@@ -1524,7 +1546,7 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path ) + else if (imp && imp->ldr.DdagNode != node_ntdll && imp->ldr.DdagNode != node_kernel32) + add_module_dependency_after( wm->ldr.DdagNode, imp->ldr.DdagNode, dep_after ); + } +- current_modref = prev; ++ pop_importer( &importer ); + if (wm->ldr.ActivationContext) RtlDeactivateActivationContext( 0, cookie ); + return status; + } +@@ -1804,8 +1826,9 @@ static NTSTATUS process_attach( LDR_DDAG_NODE *node, LPVOID lpReserved ) + /* Call DLL entry point */ + if (status == STATUS_SUCCESS) + { +- WINE_MODREF *prev = current_modref; +- current_modref = wm; ++ struct importer importer; ++ ++ push_importer( &importer, wm ); + + call_ldr_notifications( LDR_DLL_NOTIFICATION_REASON_LOADED, &wm->ldr ); + status = MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved ); +@@ -1822,7 +1845,8 @@ static NTSTATUS process_attach( LDR_DDAG_NODE *node, LPVOID lpReserved ) + last_failed_modref = wm; + WARN("Initialization of %s failed\n", debugstr_w(wm->ldr.BaseDllName.Buffer)); + } +- current_modref = prev; ++ ++ pop_importer( &importer ); + } + + if (wm->ldr.ActivationContext) RtlDeactivateActivationContext( 0, cookie ); +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0002-ntdll-Set-export-forwarder-DLL-as-the-dynamic-importer-in-LdrGetProcedureAddress-.patch b/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0002-ntdll-Set-export-forwarder-DLL-as-the-dynamic-importer-in-LdrGetProcedureAddress-.patch new file mode 100644 index 0000000..bccafea --- /dev/null +++ b/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0002-ntdll-Set-export-forwarder-DLL-as-the-dynamic-importer-in-LdrGetProcedureAddress-.patch @@ -0,0 +1,134 @@ +From c17600b062b4435626a8a13a79ac45083aaf5b2e Mon Sep 17 00:00:00 2001 +From: Jinoh Kang +Date: Fri, 19 Apr 2024 00:02:07 +0900 +Subject: [PATCH] ntdll: Set export forwarder DLL as the dynamic importer in + LdrGetProcedureAddress(). + +This matches the Windows GetProcAddress() behavior when handling dynamic +module dependencies. + +To avoid breaking WINEDEBUG=+relay, flag dynamic importers (`is_dynamic += TRUE`) and explicitly ignore them when testing for RelayFromExclude +modules. + +Otherwise, GetProcAddress() on kernel32 export forwarders (which +comprise most of the exports) will be recognized as relaying *from* +kernel32 itself (instead of the actual importer) and will be +subsequently excluded from WINEDEBUG=+relay due to the default +`RelayFromExclude` which includes `kernel32`. The current behavior is +to treat it as relaying from the actual importer, not kernel32, so this +doen't become a problem. + +This bit is true for all export forwarder DLLs in general, and also +affects RelayFromInclude as well as SnoopFrom{Exclude,Include} (+snoop). +--- + dlls/ntdll/loader.c | 38 ++++++++++++++++++++++++++++++-------- + 1 file changed, 30 insertions(+), 8 deletions(-) + +diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c +index 137bab5d124..de50e2e3468 100644 +--- a/dlls/ntdll/loader.c ++++ b/dlls/ntdll/loader.c +@@ -196,6 +196,7 @@ struct importer + { + struct importer *prev; + WINE_MODREF *modref; ++ BOOL is_dynamic; + }; + + static struct importer *current_importer; +@@ -580,9 +581,10 @@ static inline ULONG_PTR allocate_stub( const char *dll, const char *name ) { ret + #endif /* __i386__ */ + + /* The loader_section must be locked while calling this function. */ +-static void push_importer( struct importer *importer, WINE_MODREF *modref ) ++static void push_importer( struct importer *importer, WINE_MODREF *modref, BOOL is_dynamic ) + { + importer->modref = modref; ++ importer->is_dynamic = is_dynamic; + importer->prev = current_importer; + current_importer = importer; + } +@@ -593,6 +595,20 @@ static void pop_importer( struct importer *importer ) + current_importer = importer->prev; + } + ++/* The loader_section must be locked while calling this function. */ ++static const WCHAR *get_last_static_importer_name(void) ++{ ++ struct importer *importer; ++ for (importer = current_importer; importer != NULL; importer = importer->prev) ++ { ++ if (!importer->is_dynamic) ++ { ++ return importer->modref->ldr.BaseDllName.Buffer; ++ } ++ } ++ return NULL; ++} ++ + /* call ldr notifications */ + static void call_ldr_notifications( ULONG reason, LDR_DATA_TABLE_ENTRY *module ) + { +@@ -1081,12 +1097,12 @@ static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY + + if (TRACE_ON(snoop)) + { +- const WCHAR *user = current_importer ? current_importer->modref->ldr.BaseDllName.Buffer : NULL; ++ const WCHAR *user = get_last_static_importer_name(); + proc = SNOOP_GetProcAddress( module, exports, exp_size, proc, ordinal, user ); + } + if (TRACE_ON(relay)) + { +- const WCHAR *user = current_importer ? current_importer->modref->ldr.BaseDllName.Buffer : NULL; ++ const WCHAR *user = get_last_static_importer_name(); + proc = RELAY_GetProcAddress( module, exports, exp_size, proc, ordinal, user ); + } + return proc; +@@ -1495,7 +1511,7 @@ static NTSTATUS fixup_imports_ilonly( WINE_MODREF *wm, LPCWSTR load_path, void * + if (!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) return STATUS_SUCCESS; /* already done */ + wm->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS; + +- push_importer( &importer, wm ); ++ push_importer( &importer, wm, FALSE ); + assert( !wm->ldr.DdagNode->Dependencies.Tail ); + if (!(status = load_dll( load_path, L"mscoree.dll", 0, &imp, FALSE )) + && !add_module_dependency_after( wm->ldr.DdagNode, imp->ldr.DdagNode, NULL )) +@@ -1554,7 +1570,7 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path ) + /* load the imported modules. They are automatically + * added to the modref list of the process. + */ +- push_importer( &importer, wm ); ++ push_importer( &importer, wm, FALSE ); + status = STATUS_SUCCESS; + for (i = 0; i < nb_imports; i++) + { +@@ -1847,7 +1863,7 @@ static NTSTATUS process_attach( LDR_DDAG_NODE *node, LPVOID lpReserved ) + { + struct importer importer; + +- push_importer( &importer, wm ); ++ push_importer( &importer, wm, FALSE ); + + call_ldr_notifications( LDR_DLL_NOTIFICATION_REASON_LOADED, &wm->ldr ); + status = MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved ); +@@ -2221,8 +2237,14 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name, + else if ((exports = RtlImageDirectoryEntryToData( module, TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size ))) + { +- void *proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1, NULL ) +- : find_ordinal_export( module, exports, exp_size, ord - exports->Base, NULL ); ++ struct importer importer; ++ void *proc; ++ ++ push_importer( &importer, wm, TRUE ); ++ proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1, NULL ) ++ : find_ordinal_export( module, exports, exp_size, ord - exports->Base, NULL ); ++ pop_importer( &importer ); ++ + if (proc && !is_hidden_export( proc )) + { + *address = proc; +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0003-ntdll-Remove-some-unnecessary-NULL-checks-for-current-importer.patch b/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0003-ntdll-Remove-some-unnecessary-NULL-checks-for-current-importer.patch new file mode 100644 index 0000000..bd0fd2c --- /dev/null +++ b/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0003-ntdll-Remove-some-unnecessary-NULL-checks-for-current-importer.patch @@ -0,0 +1,37 @@ +From 70c7ad699e99be555301c6666739cad295ac3872 Mon Sep 17 00:00:00 2001 +From: Jinoh Kang +Date: Thu, 18 Apr 2024 23:23:32 +0900 +Subject: [PATCH] ntdll: Remove some unnecessary NULL checks for + current_importer. + +current_importer is now set by all callers of build_import_name, +find_forwarded_export, and find_ordinal_export. +--- + dlls/ntdll/loader.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c +index ea01263d023..5f7ce313113 100644 +--- a/dlls/ntdll/loader.c ++++ b/dlls/ntdll/loader.c +@@ -825,7 +825,7 @@ static NTSTATUS build_import_name( WCHAR buffer[256], const char *import, int le + { + const API_SET_NAMESPACE *map = NtCurrentTeb()->Peb->ApiSetMap; + const API_SET_NAMESPACE_ENTRY *entry; +- const WCHAR *host = current_importer ? current_importer->modref->ldr.BaseDllName.Buffer : NULL; ++ const WCHAR *host = current_importer->modref->ldr.BaseDllName.Buffer; + UNICODE_STRING str; + + while (len && import[len-1] == ' ') len--; /* remove trailing spaces */ +@@ -1009,7 +1009,7 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS + if (load_dll( load_path, mod_name, 0, &wm, imp->system ) == STATUS_SUCCESS && + !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) + { +- if (!imports_fixup_done && current_importer) ++ if (!imports_fixup_done) + { + add_module_dependency( current_importer->modref->ldr.DdagNode, wm->ldr.DdagNode ); + } +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0004-ntdll-Don-t-re-add-a-module-dependency-if-it-already-exists.patch b/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0004-ntdll-Don-t-re-add-a-module-dependency-if-it-already-exists.patch new file mode 100644 index 0000000..3e519fa --- /dev/null +++ b/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0004-ntdll-Don-t-re-add-a-module-dependency-if-it-already-exists.patch @@ -0,0 +1,65 @@ +From 7686456a4e8e427dde11b958c480eda7cc26e1d5 Mon Sep 17 00:00:00 2001 +From: Jinoh Kang +Date: Thu, 18 Apr 2024 23:23:43 +0900 +Subject: [PATCH] ntdll: Don't re-add a module dependency if it already exists. + +Today, calling add_module_dependency() multiple times with the same +arguments results in duplicate edges. + +Duplicate edges are harmless, but bloats memory usage. The number of +duplicate edges does not affect the dependency graph; the graph is +determined by the set of unique edges. + +Consciously avoid duplicates by checking for them in +add_module_dependency_after(). This allows us to generate a unique +dependency edge for all imports of export forwarders that belong to the +same DLL. +--- + dlls/ntdll/loader.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c +index 5f7ce313113..29108c401cc 100644 +--- a/dlls/ntdll/loader.c ++++ b/dlls/ntdll/loader.c +@@ -925,6 +925,21 @@ static void remove_single_list_entry( LDRP_CSLIST *list, SINGLE_LIST_ENTRY *entr + entry->Next = NULL; + } + ++static LDR_DEPENDENCY *find_module_dependency( LDR_DDAG_NODE *from, LDR_DDAG_NODE *to ) ++{ ++ SINGLE_LIST_ENTRY *entry, *mark = from->Dependencies.Tail; ++ ++ if (!mark) return NULL; ++ ++ for (entry = mark->Next; entry != mark; entry = entry->Next) ++ { ++ LDR_DEPENDENCY *dep = CONTAINING_RECORD( entry, LDR_DEPENDENCY, dependency_to_entry ); ++ if (dep->dependency_from == from && dep->dependency_to == to) return dep; ++ } ++ ++ return NULL; ++} ++ + /********************************************************************** + * add_module_dependency_after + */ +@@ -933,6 +948,15 @@ static BOOL add_module_dependency_after( LDR_DDAG_NODE *from, LDR_DDAG_NODE *to, + { + LDR_DEPENDENCY *dep; + ++ if ((dep = find_module_dependency( from, to ))) ++ { ++ /* Dependency already exists; consume the module reference stolen from the caller */ ++ LDR_DATA_TABLE_ENTRY *mod = CONTAINING_RECORD( to->Modules.Flink, LDR_DATA_TABLE_ENTRY, NodeModuleLink ); ++ WINE_MODREF *wm = CONTAINING_RECORD( mod, WINE_MODREF, ldr ); ++ LdrUnloadDll( wm->ldr.DllBase ); ++ return TRUE; ++ } ++ + if (!(dep = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*dep) ))) return FALSE; + + dep->dependency_from = from; +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0005-ntdll-Properly-track-refcount-with-forwarded-exports.patch b/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0005-ntdll-Properly-track-refcount-with-forwarded-exports.patch new file mode 100644 index 0000000..55e138f --- /dev/null +++ b/0003-pending-mrs-and-backports/0007-ntdll-Properly-track-refcount-with-forwarded-exports/0005-ntdll-Properly-track-refcount-with-forwarded-exports.patch @@ -0,0 +1,76 @@ +From 5ffce73492a388ebc5588c8b2154b0047420905a Mon Sep 17 00:00:00 2001 +From: Jinoh Kang +Date: Fri, 19 Apr 2024 00:42:57 +0900 +Subject: [PATCH] ntdll: Properly track refcount with forwarded exports. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52094 +--- + dlls/kernel32/tests/loader.c | 2 -- + dlls/ntdll/loader.c | 17 ++++++++++++----- + 2 files changed, 12 insertions(+), 7 deletions(-) + +diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c +index 9b0f8f6bff2..36f04afbf3d 100644 +--- a/dlls/kernel32/tests/loader.c ++++ b/dlls/kernel32/tests/loader.c +@@ -2775,7 +2775,6 @@ static void subtest_export_forwarder_dep_chain( size_t num_chained_export_module + + /* FreeLibrary() should *not* unload the DLL immediately */ + module = GetModuleHandleA( temp_paths[i] ); +- todo_wine_if(i < ultimate_depender_index && i + 1 != importer_index) + ok( module == modules[i], "modules[%Iu] expected %p, got %p (unloaded?) err=%lu\n", + i, modules[i], module, GetLastError() ); + } +@@ -2787,7 +2786,6 @@ static void subtest_export_forwarder_dep_chain( size_t num_chained_export_module + { + HMODULE module = GetModuleHandleA( temp_paths[i] ); + +- todo_wine_if(i < ultimate_depender_index && i + 1 != importer_index) + ok( module == modules[i], "modules[%Iu] expected %p, got %p (unloaded?) err=%lu\n", + i, modules[i], module, GetLastError() ); + } +diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c +index 29108c401cc..eadda01ac14 100644 +--- a/dlls/ntdll/loader.c ++++ b/dlls/ntdll/loader.c +@@ -1033,11 +1033,7 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS + if (load_dll( load_path, mod_name, 0, &wm, imp->system ) == STATUS_SUCCESS && + !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) + { +- if (!imports_fixup_done) +- { +- add_module_dependency( current_importer->modref->ldr.DdagNode, wm->ldr.DdagNode ); +- } +- else if (process_attach( wm->ldr.DdagNode, NULL ) != STATUS_SUCCESS) ++ if (imports_fixup_done && process_attach( wm->ldr.DdagNode, NULL ) != STATUS_SUCCESS) + { + LdrUnloadDll( wm->ldr.DllBase ); + wm = NULL; +@@ -1051,6 +1047,11 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS + return NULL; + } + } ++ else ++ { ++ if (wm->ldr.LoadCount != -1) wm->ldr.LoadCount++; ++ } ++ + if ((exports = RtlImageDirectoryEntryToData( wm->ldr.DllBase, TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size ))) + { +@@ -1070,6 +1071,12 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS + forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer), + debugstr_w(get_modref(module)->ldr.BaseDllName.Buffer) ); + } ++ else if (wm->ldr.DdagNode != node_ntdll && wm->ldr.DdagNode != node_kernel32) ++ { ++ add_module_dependency( current_importer->modref->ldr.DdagNode, wm->ldr.DdagNode ); ++ wm = NULL; ++ } ++ if (wm) LdrUnloadDll( wm->ldr.DllBase ); + return proc; + } + +-- +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 new file mode 100644 index 0000000..2b49507 --- /dev/null +++ b/0003-pending-mrs-and-backports/4833-ntdll-Improve-NtQuerySystemInformation-SystemCodeIntegrityInformation-/0001-ntdll-Improve-NtQuerySystemInformation-SystemCodeIntegrityInformation-.patch @@ -0,0 +1,44 @@ +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/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 new file mode 100644 index 0000000..c58b198 --- /dev/null +++ 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 @@ -0,0 +1,146 @@ +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/6584-wintab32-Improve-wow64-support/0001-wintab32-Pad-WTPACKET-to-align-32-64-bit-archs.patch b/0003-pending-mrs-and-backports/6584-wintab32-Improve-wow64-support/0001-wintab32-Pad-WTPACKET-to-align-32-64-bit-archs.patch deleted file mode 100644 index 1226d4e..0000000 --- a/0003-pending-mrs-and-backports/6584-wintab32-Improve-wow64-support/0001-wintab32-Pad-WTPACKET-to-align-32-64-bit-archs.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 07a919f355918c1b30dac747887a508fc499ee66 Mon Sep 17 00:00:00 2001 -From: John Chadwick -Date: Sun, 29 Sep 2024 19:24:40 -0400 -Subject: [PATCH] wintab32: Pad WTPACKET to align 32/64-bit archs - -WTPACKET's structure is never directly exposed via the API; it's -internal to Wine. The HCTX value is only used on the wintab32 side, -not the driver side, so this is safe to do. - -This eliminates the need to have a wow64 thunk for tablet_get_packet. ---- - dlls/winex11.drv/wintab.c | 3 +++ - dlls/wintab32/wintab_internal.h | 3 +++ - 2 files changed, 6 insertions(+) - -diff --git a/dlls/winex11.drv/wintab.c b/dlls/winex11.drv/wintab.c -index 6f1437f14c6..5bcbf1666d3 100644 ---- a/dlls/winex11.drv/wintab.c -+++ b/dlls/winex11.drv/wintab.c -@@ -237,6 +237,9 @@ typedef struct tagWTI_DEVICES_INFO - - typedef struct tagWTPACKET { - HCTX pkContext; -+#ifndef _WIN64 -+ DWORD dwPadding; -+#endif - UINT pkStatus; - LONG pkTime; - WTPKT pkChanged; -diff --git a/dlls/wintab32/wintab_internal.h b/dlls/wintab32/wintab_internal.h -index b0a2e8fd58f..7d06e59cb2f 100644 ---- a/dlls/wintab32/wintab_internal.h -+++ b/dlls/wintab32/wintab_internal.h -@@ -118,6 +118,9 @@ typedef struct tagWTI_EXTENSIONS_INFO - - typedef struct tagWTPACKET { - HCTX pkContext; -+#ifndef _WIN64 -+ DWORD dwPadding; -+#endif - UINT pkStatus; - LONG pkTime; - WTPKT pkChanged; --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6584-wintab32-Improve-wow64-support/0002-winex11-Remove-stub-tablet-get-packet-wow64-thunk.patch b/0003-pending-mrs-and-backports/6584-wintab32-Improve-wow64-support/0002-winex11-Remove-stub-tablet-get-packet-wow64-thunk.patch deleted file mode 100644 index ebd9955..0000000 --- a/0003-pending-mrs-and-backports/6584-wintab32-Improve-wow64-support/0002-winex11-Remove-stub-tablet-get-packet-wow64-thunk.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 5498c126f75f3d42d689a192040cc6d0d956d57f Mon Sep 17 00:00:00 2001 -From: John Chadwick -Date: Sun, 29 Sep 2024 19:29:05 -0400 -Subject: [PATCH] winex11: Remove stub tablet_get_packet wow64 thunk - -The previous commit ensures that the WTPACKET fields align between -32-bit and 64-bit architectures, so now we can use the same -tablet_get_packet without needing another thunk. ---- - dlls/winex11.drv/x11drv_main.c | 8 +------- - 1 file changed, 1 insertion(+), 7 deletions(-) - -diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c -index 3f8e48a7a8d..c4ec133cb0b 100644 ---- a/dlls/winex11.drv/x11drv_main.c -+++ b/dlls/winex11.drv/x11drv_main.c -@@ -826,12 +826,6 @@ C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count ); - - #ifdef _WIN64 - --static NTSTATUS x11drv_wow64_tablet_get_packet( void *arg ) --{ -- FIXME( "%p\n", arg ); -- return 0; --} -- - static NTSTATUS x11drv_wow64_tablet_info( void *arg ) - { - struct -@@ -852,7 +846,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = - { - x11drv_init, - x11drv_tablet_attach_queue, -- x11drv_wow64_tablet_get_packet, -+ x11drv_tablet_get_packet, - x11drv_wow64_tablet_info, - x11drv_tablet_load_info, - }; --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0001-winex11-Call-window-set-wm-state-when-unmapping-embedded-windows.patch b/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0001-winex11-Call-window-set-wm-state-when-unmapping-embedded-windows.patch deleted file mode 100644 index c2ecf2e..0000000 --- a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0001-winex11-Call-window-set-wm-state-when-unmapping-embedded-windows.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 1c91ef50127b26e184d453510262b08254de4ee8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Sat, 19 Oct 2024 10:43:41 +0200 -Subject: [PATCH] winex11: Call window_set_wm_state when unmapping embedded - windows. - ---- - dlls/winex11.drv/window.c | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - -diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c -index 58fc99275f4..46006874dfa 100644 ---- a/dlls/winex11.drv/window.c -+++ b/dlls/winex11.drv/window.c -@@ -2398,17 +2398,19 @@ void X11DRV_SystrayDockClear( HWND hwnd ) - BOOL X11DRV_SystrayDockRemove( HWND hwnd ) - { - struct x11drv_win_data *data; -- BOOL ret; -+ BOOL ret = FALSE; - -- /* make sure we don't try to unmap it, it confuses some systray docks */ - if ((data = get_win_data( hwnd ))) - { -- if ((ret = data->embedded)) data->mapped = FALSE; -+ if ((ret = data->embedded)) -+ { -+ window_set_wm_state( data, WithdrawnState ); -+ data->mapped = FALSE; -+ } - release_win_data( data ); -- return ret; - } - -- return FALSE; -+ return ret; - } - - --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0002-winex11-Compute-WindowPosChanged-updates-in-terms-of-style-changes.patch b/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0002-winex11-Compute-WindowPosChanged-updates-in-terms-of-style-changes.patch deleted file mode 100644 index 3085c80..0000000 --- a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0002-winex11-Compute-WindowPosChanged-updates-in-terms-of-style-changes.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 92a31166855bd2c0acd15093890f49815c373080 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Sat, 19 Oct 2024 10:25:45 +0200 -Subject: [PATCH] winex11: Compute WindowPosChanged updates in terms of style - changes. - -Making the changes computation more readable, matching styles between -the last requested (pending_state) style and the current style. ---- - dlls/winex11.drv/window.c | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - -diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c -index 46006874dfa..d75afa33ff9 100644 ---- a/dlls/winex11.drv/window.c -+++ b/dlls/winex11.drv/window.c -@@ -2773,13 +2773,21 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags, BOOL - { - struct x11drv_thread_data *thread_data; - struct x11drv_win_data *data; -- UINT new_style = NtUserGetWindowLongW( hwnd, GWL_STYLE ); -+ UINT new_style = NtUserGetWindowLongW( hwnd, GWL_STYLE ), old_style; - struct window_rects old_rects; - BOOL was_fullscreen; - int event_type; - - if (!(data = get_win_data( hwnd ))) return; - -+ /* Compute the necessary changes to transition from the last requested -+ * window state (old_style), to the desired window state (new_style). -+ */ -+ old_style = new_style & ~(WS_VISIBLE | WS_MINIMIZE | WS_MAXIMIZE); -+ if (data->pending_state.wm_state == IconicState) old_style |= WS_MINIMIZE; -+ if (data->pending_state.wm_state != WithdrawnState) old_style |= WS_VISIBLE; -+ if (data->pending_state.net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)) old_style |= WS_MAXIMIZE; -+ - thread_data = x11drv_thread_data(); - - old_rects = data->rects; -@@ -2816,7 +2824,7 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags, BOOL - event_type = 0; /* ignore other events */ - } - -- if (data->mapped && event_type != ReparentNotify) -+ if ((old_style & WS_VISIBLE) && event_type != ReparentNotify) - { - if (((swp_flags & SWP_HIDEWINDOW) && !(new_style & WS_VISIBLE)) || - (!event_type && !(new_style & WS_MINIMIZE) && -@@ -2853,7 +2861,7 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags, BOOL - if ((new_style & WS_VISIBLE) && - ((new_style & WS_MINIMIZE) || is_window_rect_mapped( &new_rects->window ))) - { -- if (!data->mapped) -+ if (!(old_style & WS_VISIBLE)) - { - BOOL needs_icon = !data->icon_pixmap; - BOOL needs_map = TRUE; -@@ -2866,7 +2874,7 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags, BOOL - if (needs_map) map_window( hwnd, new_style ); - return; - } -- else if ((swp_flags & SWP_STATECHANGED) && (!data->iconic != !(new_style & WS_MINIMIZE))) -+ else if ((swp_flags & SWP_STATECHANGED) && (old_style & WS_MINIMIZE) != (new_style & WS_MINIMIZE)) - { - set_wm_hints( data ); - data->iconic = (new_style & WS_MINIMIZE) != 0; --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0003-winex11-Compute-ConfigureNotify-updates-in-terms-of-style-changes.patch b/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0003-winex11-Compute-ConfigureNotify-updates-in-terms-of-style-changes.patch deleted file mode 100644 index e101012..0000000 --- a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0003-winex11-Compute-ConfigureNotify-updates-in-terms-of-style-changes.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0c73fa6637664622b41210476fdc0db06aab58f1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Sat, 19 Oct 2024 10:34:49 +0200 -Subject: [PATCH] winex11: Compute ConfigureNotify updates in terms of style - changes. - -Making the changes computation more readable, matching styles between -the current Win32 style and the current X11 (current_state) style. ---- - dlls/winex11.drv/event.c | 21 ++++++++++++++------- - 1 file changed, 14 insertions(+), 7 deletions(-) - -diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c -index 21bc5fc2813..2a95552b8d6 100644 ---- a/dlls/winex11.drv/event.c -+++ b/dlls/winex11.drv/event.c -@@ -1062,9 +1062,8 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) - struct x11drv_win_data *data; - RECT rect; - POINT pos = {event->x, event->y}; -- UINT flags; -+ UINT flags, old_style, new_style; - int cx, cy, x, y; -- DWORD style; - - if (!hwnd) return FALSE; - if (!(data = get_win_data( hwnd ))) return FALSE; -@@ -1083,6 +1082,15 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) - SetRect( &rect, pos.x, pos.y, pos.x + event->width, pos.y + event->height ); - window_configure_notify( data, event->serial, &rect ); - -+ /* Compute the necessary changes to transition from the current Win32 -+ * window state (old_style), to the current X11 window state (new_style). -+ */ -+ old_style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ); -+ new_style = old_style & ~(WS_VISIBLE | WS_MINIMIZE | WS_MAXIMIZE); -+ if (data->current_state.wm_state == IconicState) new_style |= WS_MINIMIZE; -+ if (data->current_state.wm_state != WithdrawnState) new_style |= WS_VISIBLE; -+ if (data->current_state.net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)) new_style |= WS_MAXIMIZE; -+ - if (!data->mapped || data->iconic) goto done; - if (!data->whole_window || !data->managed) goto done; - if (data->configure_serial && (long)(data->configure_serial - event->serial) > 0) -@@ -1124,13 +1132,12 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) - hwnd, (int)(data->rects.window.right - data->rects.window.left), - (int)(data->rects.window.bottom - data->rects.window.top), cx, cy ); - -- style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ); -- if ((style & WS_CAPTION) == WS_CAPTION || !data->is_fullscreen) -+ if ((old_style & WS_CAPTION) == WS_CAPTION || !data->is_fullscreen) - { - data->net_wm_state = get_window_net_wm_state( event->display, data->whole_window ); -- if ((data->net_wm_state & (1 << NET_WM_STATE_MAXIMIZED))) -+ if ((new_style & WS_MAXIMIZE)) - { -- if (!(style & WS_MAXIMIZE)) -+ if (!(old_style & WS_MAXIMIZE)) - { - TRACE( "win %p/%lx is maximized\n", data->hwnd, data->whole_window ); - release_win_data( data ); -@@ -1138,7 +1145,7 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) - return TRUE; - } - } -- else if (style & WS_MAXIMIZE) -+ else if (old_style & WS_MAXIMIZE) - { - TRACE( "window %p/%lx is no longer maximized\n", data->hwnd, data->whole_window ); - release_win_data( data ); --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0004-winex11-Compute-WM-STATE-notify-updates-in-terms-of-style-changes.patch b/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0004-winex11-Compute-WM-STATE-notify-updates-in-terms-of-style-changes.patch deleted file mode 100644 index cef0b51..0000000 --- a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0004-winex11-Compute-WM-STATE-notify-updates-in-terms-of-style-changes.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 01e72c56fbfc0a57e1188a9c287118f7573af6f2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Sat, 19 Oct 2024 10:52:16 +0200 -Subject: [PATCH] winex11: Compute WM_STATE notify updates in terms of style - changes. - -Making the changes computation more readable, matching styles between -the current Win32 style and the current X11 (current_state) style. ---- - dlls/winex11.drv/event.c | 33 ++++++++++++++++++++------------- - 1 file changed, 20 insertions(+), 13 deletions(-) - -diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c -index 2a95552b8d6..088a124654e 100644 ---- a/dlls/winex11.drv/event.c -+++ b/dlls/winex11.drv/event.c -@@ -1226,12 +1226,21 @@ static int get_window_xembed_info( Display *display, Window window ) - static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL update_window ) - { - struct x11drv_win_data *data; -- UINT style, value = 0; -+ UINT old_style, new_style, value = 0; - - if (!(data = get_win_data( hwnd ))) return; - if (event->state == PropertyNewValue) value = get_window_wm_state( event->display, event->window ); - if (update_window) window_wm_state_notify( data, event->serial, value ); - -+ /* Compute the necessary changes to transition from the current Win32 -+ * window state (old_style), to the current X11 window state (new_style). -+ */ -+ old_style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ); -+ new_style = old_style & ~(WS_VISIBLE | WS_MINIMIZE | WS_MAXIMIZE); -+ if (data->current_state.wm_state == IconicState) new_style |= WS_MINIMIZE; -+ if (data->current_state.wm_state != WithdrawnState) new_style |= WS_VISIBLE; -+ if (data->current_state.net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)) new_style |= WS_MAXIMIZE; -+ - switch(event->state) - { - case PropertyDelete: -@@ -1257,48 +1266,46 @@ static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL updat - - if (!update_window || !data->managed || !data->mapped) goto done; - -- style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ); -- -- if (data->iconic && data->wm_state == NormalState) /* restore window */ -+ if ((old_style & WS_MINIMIZE) && !(new_style & WS_MINIMIZE)) /* restore window */ - { - data->iconic = FALSE; - data->net_wm_state = get_window_net_wm_state( event->display, data->whole_window ); -- if ((style & WS_CAPTION) == WS_CAPTION && (data->net_wm_state & (1 << NET_WM_STATE_MAXIMIZED))) -+ if ((old_style & WS_CAPTION) == WS_CAPTION && (new_style & WS_MAXIMIZE)) - { -- if ((style & WS_MAXIMIZEBOX) && !(style & WS_DISABLED)) -+ if ((old_style & WS_MAXIMIZEBOX) && !(old_style & WS_DISABLED)) - { - TRACE( "restoring to max %p/%lx\n", data->hwnd, data->whole_window ); - release_win_data( data ); - send_message( hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0 ); - return; - } -- TRACE( "not restoring to max win %p/%lx style %08x\n", data->hwnd, data->whole_window, style ); -+ TRACE( "window %p/%lx style %#x not restoring to max\n", data->hwnd, data->whole_window, old_style ); - } - else - { -- if (style & (WS_MINIMIZE | WS_MAXIMIZE)) -+ if (old_style & (WS_MINIMIZE | WS_MAXIMIZE)) - { - TRACE( "restoring win %p/%lx\n", data->hwnd, data->whole_window ); - release_win_data( data ); -- if ((style & (WS_MINIMIZE | WS_VISIBLE)) == (WS_MINIMIZE | WS_VISIBLE)) -+ if ((old_style & (WS_MINIMIZE | WS_VISIBLE)) == (WS_MINIMIZE | WS_VISIBLE)) - NtUserSetActiveWindow( hwnd ); - send_message( hwnd, WM_SYSCOMMAND, SC_RESTORE, 0 ); - return; - } -- TRACE( "not restoring win %p/%lx style %08x\n", data->hwnd, data->whole_window, style ); -+ TRACE( "window %p/%lx style %#x not restoring\n", data->hwnd, data->whole_window, old_style ); - } - } -- else if (!data->iconic && data->wm_state == IconicState) -+ else if (!(old_style & WS_MINIMIZE) && (new_style & WS_MINIMIZE)) - { - data->iconic = TRUE; -- if ((style & WS_MINIMIZEBOX) && !(style & WS_DISABLED)) -+ if ((old_style & WS_MINIMIZEBOX) && !(old_style & WS_DISABLED)) - { - TRACE( "minimizing win %p/%lx\n", data->hwnd, data->whole_window ); - release_win_data( data ); - send_message( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0 ); - return; - } -- TRACE( "not minimizing win %p/%lx style %08x\n", data->hwnd, data->whole_window, style ); -+ TRACE( "window %p/%lx style %#x not minimizing\n", data->hwnd, data->whole_window, old_style ); - } - done: - release_win_data( data ); --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0005-winex11-Use-the-style-to-decide-whether-a-window-is-currently-visible-or-iconic.patch b/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0005-winex11-Use-the-style-to-decide-whether-a-window-is-currently-visible-or-iconic.patch deleted file mode 100644 index c5ab66b..0000000 --- a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0005-winex11-Use-the-style-to-decide-whether-a-window-is-currently-visible-or-iconic.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 84bbfcdb916752bbe3e72827aaff7752c6ee913d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Fri, 25 Oct 2024 08:40:37 +0200 -Subject: [PATCH] winex11: Use the style to decide whether a window is - currently visible or iconic. - -The mapped and iconic flags should match the last requested state at -all time. Unless we've missed sending an update this should match the -current Win32 state, and we should be able use it instead as a more -accurate source of information about the supposed window state. - -When receiving config changes, we don't want to apply changes to a -window which is supposed to be hidden or minimized. When receiving state -changes, we don't want to apply changes to a window which is supposed to -be hidden, regardless of the X11 believes. ---- - dlls/winex11.drv/event.c | 4 ++-- - dlls/winex11.drv/window.c | 4 ++-- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c -index 088a124654e..5e4e1e458dd 100644 ---- a/dlls/winex11.drv/event.c -+++ b/dlls/winex11.drv/event.c -@@ -1091,7 +1091,7 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) - if (data->current_state.wm_state != WithdrawnState) new_style |= WS_VISIBLE; - if (data->current_state.net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)) new_style |= WS_MAXIMIZE; - -- if (!data->mapped || data->iconic) goto done; -+ if (!(old_style & WS_VISIBLE) || (old_style & WS_MINIMIZE)) goto done; - if (!data->whole_window || !data->managed) goto done; - if (data->configure_serial && (long)(data->configure_serial - event->serial) > 0) - { -@@ -1264,7 +1264,7 @@ static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL updat - break; - } - -- if (!update_window || !data->managed || !data->mapped) goto done; -+ if (!update_window || !data->managed || !(old_style & WS_VISIBLE)) goto done; - - if ((old_style & WS_MINIMIZE) && !(new_style & WS_MINIMIZE)) /* restore window */ - { -diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c -index d75afa33ff9..0bb7175c29c 100644 ---- a/dlls/winex11.drv/window.c -+++ b/dlls/winex11.drv/window.c -@@ -1613,7 +1613,7 @@ static void sync_window_position( struct x11drv_win_data *data, UINT swp_flags ) - DWORD ex_style = NtUserGetWindowLongW( data->hwnd, GWL_EXSTYLE ); - BOOL above = FALSE; - -- if (data->managed && data->iconic) return; -+ if (data->managed && (style & WS_MINIMIZE)) return; - - if (!(swp_flags & SWP_NOZORDER) || (swp_flags & SWP_SHOWWINDOW)) - { -@@ -2927,7 +2927,7 @@ UINT X11DRV_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ) - } - goto done; - } -- if (!data->managed || !data->mapped || data->iconic) goto done; -+ if (!data->managed || !(style & WS_VISIBLE) || (style & WS_MINIMIZE)) goto done; - - /* only fetch the new rectangle if the ShowWindow was a result of a window manager event */ - --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0006-winex11-Use-pending-state-wm-state-to-decide-if-requests-can-be-sent-directly.patch b/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0006-winex11-Use-pending-state-wm-state-to-decide-if-requests-can-be-sent-directly.patch deleted file mode 100644 index 108df75..0000000 --- a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0006-winex11-Use-pending-state-wm-state-to-decide-if-requests-can-be-sent-directly.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 96d1d62cbfdb5f508c8df2c608db01cbe5a80a17 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Sat, 19 Oct 2024 10:40:45 +0200 -Subject: [PATCH] winex11: Use pending_state.wm_state to decide if requests can - be sent directly. - ---- - dlls/winex11.drv/window.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c -index 0bb7175c29c..035f8d5cf0b 100644 ---- a/dlls/winex11.drv/window.c -+++ b/dlls/winex11.drv/window.c -@@ -1187,7 +1187,7 @@ static void update_net_wm_fullscreen_monitors( struct x11drv_win_data *data ) - && !data->net_wm_fullscreen_monitors_set) - return; - -- if (!data->mapped) -+ if (data->pending_state.wm_state == WithdrawnState) - { - XChangeProperty( data->display, data->whole_window, x11drv_atom(_NET_WM_FULLSCREEN_MONITORS), - XA_CARDINAL, 32, PropModeReplace, (unsigned char *)monitors, 4 ); -@@ -1215,7 +1215,7 @@ static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_stat - - if (!data->whole_window) return; /* no window, nothing to update */ - -- if (!data->mapped) /* set the _NET_WM_STATE atom directly */ -+ if (data->pending_state.wm_state == WithdrawnState) /* set the _NET_WM_STATE atom directly */ - { - Atom atoms[NB_NET_WM_STATES + 1]; - -@@ -3272,7 +3272,7 @@ void X11DRV_FlashWindowEx( FLASHWINFO *pfinfo ) - if (!data) - return; - -- if (data->mapped) -+ if (data->pending_state.wm_state != WithdrawnState) - { - xev.type = ClientMessage; - xev.xclient.window = data->whole_window; --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0007-winex11-Use-pending-state-wm-state-to-decide-whether-a-window-is-mapped.patch b/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0007-winex11-Use-pending-state-wm-state-to-decide-whether-a-window-is-mapped.patch deleted file mode 100644 index 9e947ab..0000000 --- a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0007-winex11-Use-pending-state-wm-state-to-decide-whether-a-window-is-mapped.patch +++ /dev/null @@ -1,76 +0,0 @@ -From dba762f95b157d1a63853b73fc9fc97301d19b67 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Sun, 20 Oct 2024 11:03:10 +0200 -Subject: [PATCH] winex11: Use pending_state.wm_state to decide whether a - window is mapped. - ---- - dlls/winex11.drv/event.c | 2 +- - dlls/winex11.drv/window.c | 10 +++++----- - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c -index 5e4e1e458dd..11e93a3a100 100644 ---- a/dlls/winex11.drv/event.c -+++ b/dlls/winex11.drv/event.c -@@ -998,7 +998,7 @@ static BOOL X11DRV_MapNotify( HWND hwnd, XEvent *event ) - - if (!(data = get_win_data( hwnd ))) return FALSE; - -- if (!data->managed && !data->embedded && data->mapped) -+ if (!data->managed && !data->embedded && data->pending_state.wm_state == NormalState) - { - HWND hwndFocus = get_focus(); - if (hwndFocus && NtUserIsChild( hwnd, hwndFocus )) -diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c -index 035f8d5cf0b..dcba464daf8 100644 ---- a/dlls/winex11.drv/window.c -+++ b/dlls/winex11.drv/window.c -@@ -1448,7 +1448,7 @@ static void map_window( HWND hwnd, DWORD new_style ) - - if (!(data = get_win_data( hwnd ))) return; - -- if (data->whole_window && !data->mapped) -+ if (data->whole_window && data->pending_state.wm_state == WithdrawnState) - { - TRACE( "win %p/%lx\n", data->hwnd, data->whole_window ); - -@@ -1479,7 +1479,7 @@ static void unmap_window( HWND hwnd ) - - if (!(data = get_win_data( hwnd ))) return; - -- if (data->mapped) -+ if (data->pending_state.wm_state != WithdrawnState) - { - TRACE( "win %p/%lx\n", data->hwnd, data->whole_window ); - window_set_wm_state( data, WithdrawnState ); -@@ -3018,7 +3018,7 @@ void X11DRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWO - sync_window_opacity( data->display, data->whole_window, alpha, flags ); - - data->layered = TRUE; -- if (!data->mapped) /* mapping is delayed until attributes are set */ -+ if (data->pending_state.wm_state == WithdrawnState) /* mapping is delayed until attributes are set */ - { - DWORD style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ); - -@@ -3054,7 +3054,7 @@ void X11DRV_UpdateLayeredWindow( HWND hwnd, UINT flags ) - BOOL mapped; - - if (!(data = get_win_data( hwnd ))) return; -- mapped = data->mapped; -+ mapped = data->pending_state.wm_state != WithdrawnState; - release_win_data( data ); - - /* layered windows are mapped only once their attributes are set */ -@@ -3206,7 +3206,7 @@ LRESULT X11DRV_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam ) - if (wparam == SC_SCREENSAVE && hwnd == NtUserGetDesktopWindow()) return start_screensaver(); - return -1; - } -- if (!data->whole_window || !data->managed || !data->mapped) goto failed; -+ if (!data->whole_window || !data->managed || data->pending_state.wm_state == WithdrawnState) goto failed; - - switch (wparam & 0xfff0) - { --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0008-winex11-Get-rid-of-the-now-unnecessary-mapped-iconic-net-wm-state-flags.patch b/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0008-winex11-Get-rid-of-the-now-unnecessary-mapped-iconic-net-wm-state-flags.patch deleted file mode 100644 index 4c8c3f9..0000000 --- a/0003-pending-mrs-and-backports/6731-winex11-Replace-win-data-iconic-mapped-net-wm-state-flags/0008-winex11-Get-rid-of-the-now-unnecessary-mapped-iconic-net-wm-state-flags.patch +++ /dev/null @@ -1,182 +0,0 @@ -From 0f5161d4b419ea31a88175fb2fdea9e0bcb1a5f5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Sat, 19 Oct 2024 10:25:45 +0200 -Subject: [PATCH] winex11: Get rid of the now unnecessary - mapped/iconic/net_wm_state flags. - ---- - dlls/winex11.drv/event.c | 8 ++------ - dlls/winex11.drv/window.c | 34 ++++++++-------------------------- - dlls/winex11.drv/x11drv.h | 3 --- - 3 files changed, 10 insertions(+), 35 deletions(-) - -diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c -index 11e93a3a100..ccbf4f43688 100644 ---- a/dlls/winex11.drv/event.c -+++ b/dlls/winex11.drv/event.c -@@ -1134,7 +1134,6 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) - - if ((old_style & WS_CAPTION) == WS_CAPTION || !data->is_fullscreen) - { -- data->net_wm_state = get_window_net_wm_state( event->display, data->whole_window ); - if ((new_style & WS_MAXIMIZE)) - { - if (!(old_style & WS_MAXIMIZE)) -@@ -1268,8 +1267,6 @@ static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL updat - - if ((old_style & WS_MINIMIZE) && !(new_style & WS_MINIMIZE)) /* restore window */ - { -- data->iconic = FALSE; -- data->net_wm_state = get_window_net_wm_state( event->display, data->whole_window ); - if ((old_style & WS_CAPTION) == WS_CAPTION && (new_style & WS_MAXIMIZE)) - { - if ((old_style & WS_MAXIMIZEBOX) && !(old_style & WS_DISABLED)) -@@ -1297,7 +1294,6 @@ static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL updat - } - else if (!(old_style & WS_MINIMIZE) && (new_style & WS_MINIMIZE)) - { -- data->iconic = TRUE; - if ((old_style & WS_MINIMIZEBOX) && !(old_style & WS_DISABLED)) - { - TRACE( "minimizing win %p/%lx\n", data->hwnd, data->whole_window ); -@@ -1376,9 +1372,9 @@ void wait_for_withdrawn_state( HWND hwnd, BOOL set ) - if (!(data = get_win_data( hwnd ))) break; - if (!data->managed || data->embedded || data->display != display) break; - if (!(window = data->whole_window)) break; -- if (!data->mapped == !set) -+ if ((data->pending_state.wm_state == WithdrawnState) == !set) - { -- TRACE( "window %p/%lx now %smapped\n", hwnd, window, data->mapped ? "" : "un" ); -+ TRACE( "window %p/%lx now %smapped\n", hwnd, window, (data->pending_state.wm_state != WithdrawnState) ? "" : "un" ); - break; - } - if ((data->wm_state == WithdrawnState) != !set) -diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c -index dcba464daf8..8d7c5dd4b1c 100644 ---- a/dlls/winex11.drv/window.c -+++ b/dlls/winex11.drv/window.c -@@ -1155,13 +1155,13 @@ static void update_desktop_fullscreen( Display *display ) - - /* Update _NET_WM_FULLSCREEN_MONITORS when _NET_WM_STATE_FULLSCREEN is set to support fullscreen - * windows spanning multiple monitors */ --static void update_net_wm_fullscreen_monitors( struct x11drv_win_data *data ) -+static void update_net_wm_fullscreen_monitors( struct x11drv_win_data *data, UINT style ) - { - long monitors[4]; - XEvent xev; - -- if (!(data->net_wm_state & (1 << NET_WM_STATE_FULLSCREEN)) || is_virtual_desktop() -- || NtUserGetWindowLongW( data->hwnd, GWL_STYLE ) & WS_MINIMIZE) -+ if (!(data->pending_state.net_wm_state & (1 << NET_WM_STATE_FULLSCREEN)) || -+ is_virtual_desktop() || (style & WS_MINIMIZE)) - return; - - /* If the current display device handler cannot detect dynamic device changes, do not use -@@ -1322,7 +1322,7 @@ static void update_net_wm_states( struct x11drv_win_data *data ) - - style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ); - if (style & WS_MINIMIZE) -- new_state |= data->net_wm_state & ((1 << NET_WM_STATE_FULLSCREEN)|(1 << NET_WM_STATE_MAXIMIZED)); -+ new_state |= data->pending_state.net_wm_state & ((1 << NET_WM_STATE_FULLSCREEN)|(1 << NET_WM_STATE_MAXIMIZED)); - if (data->is_fullscreen) - { - if ((style & WS_MAXIMIZE) && (style & WS_CAPTION) == WS_CAPTION) -@@ -1346,8 +1346,7 @@ static void update_net_wm_states( struct x11drv_win_data *data ) - } - - window_set_net_wm_state( data, new_state ); -- data->net_wm_state = new_state; -- update_net_wm_fullscreen_monitors( data ); -+ update_net_wm_fullscreen_monitors( data, style ); - } - - /*********************************************************************** -@@ -1460,9 +1459,7 @@ static void map_window( HWND hwnd, DWORD new_style ) - window_set_wm_state( data, (new_style & WS_MINIMIZE) ? IconicState : NormalState ); - XFlush( data->display ); - -- data->mapped = TRUE; -- data->iconic = (new_style & WS_MINIMIZE) != 0; -- update_net_wm_fullscreen_monitors( data ); -+ update_net_wm_fullscreen_monitors( data, new_style ); - } - release_win_data( data ); - } -@@ -1478,14 +1475,7 @@ static void unmap_window( HWND hwnd ) - wait_for_withdrawn_state( hwnd, FALSE ); - - if (!(data = get_win_data( hwnd ))) return; -- -- if (data->pending_state.wm_state != WithdrawnState) -- { -- TRACE( "win %p/%lx\n", data->hwnd, data->whole_window ); -- window_set_wm_state( data, WithdrawnState ); -- data->mapped = FALSE; -- data->net_wm_state = 0; -- } -+ window_set_wm_state( data, WithdrawnState ); - release_win_data( data ); - } - -@@ -1594,7 +1584,6 @@ void make_window_embedded( struct x11drv_win_data *data ) - { - /* the window cannot be mapped before being embedded */ - window_set_wm_state( data, WithdrawnState ); -- data->net_wm_state = 0; - data->embedded = TRUE; - data->managed = TRUE; - sync_window_style( data ); -@@ -2006,8 +1995,6 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des - data->whole_window = data->client_window = 0; - data->whole_colormap = 0; - data->wm_state = WithdrawnState; -- data->net_wm_state = 0; -- data->mapped = FALSE; - - memset( &data->pending_state, 0, sizeof(data->pending_state) ); - memset( &data->current_state, 0, sizeof(data->current_state) ); -@@ -2402,11 +2389,7 @@ BOOL X11DRV_SystrayDockRemove( HWND hwnd ) - - if ((data = get_win_data( hwnd ))) - { -- if ((ret = data->embedded)) -- { -- window_set_wm_state( data, WithdrawnState ); -- data->mapped = FALSE; -- } -+ if ((ret = data->embedded)) window_set_wm_state( data, WithdrawnState ); - release_win_data( data ); - } - -@@ -2877,7 +2860,6 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags, BOOL - else if ((swp_flags & SWP_STATECHANGED) && (old_style & WS_MINIMIZE) != (new_style & WS_MINIMIZE)) - { - set_wm_hints( data ); -- data->iconic = (new_style & WS_MINIMIZE) != 0; - window_set_wm_state( data, (new_style & WS_MINIMIZE) ? IconicState : NormalState ); - update_net_wm_states( data ); - } -diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h -index 86749b1211f..c440fb73aea 100644 ---- a/dlls/winex11.drv/x11drv.h -+++ b/dlls/winex11.drv/x11drv.h -@@ -622,8 +622,6 @@ struct x11drv_win_data - struct host_window *parent; /* the host window parent, frame or embedder, NULL if root_window */ - XIC xic; /* X input context */ - UINT managed : 1; /* is window managed? */ -- UINT mapped : 1; /* is window mapped? (in either normal or iconic state) */ -- UINT iconic : 1; /* is window in iconic state? */ - UINT embedded : 1; /* is window an XEMBED client? */ - UINT shaped : 1; /* is window using a custom region shape? */ - UINT layered : 1; /* is window layered and with valid attributes? */ -@@ -634,7 +632,6 @@ struct x11drv_win_data - UINT is_fullscreen : 1; /* is the window visible rect fullscreen */ - UINT parent_invalid : 1; /* is the parent host window possibly invalid */ - int wm_state; /* current value of the WM_STATE property */ -- DWORD net_wm_state; /* bit mask of active x11drv_net_wm_state values */ - Window embedder; /* window id of embedder */ - Pixmap icon_pixmap; - Pixmap icon_mask; --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6787-wineps-drv-Use-locale-aware-variants-sprintf-l-and-sscanf-l-ASan-/0001-stdio-h-Add-ucrt-sprintf-l-declaration.patch b/0003-pending-mrs-and-backports/6787-wineps-drv-Use-locale-aware-variants-sprintf-l-and-sscanf-l-ASan-/0001-stdio-h-Add-ucrt-sprintf-l-declaration.patch deleted file mode 100644 index e3836d9..0000000 --- a/0003-pending-mrs-and-backports/6787-wineps-drv-Use-locale-aware-variants-sprintf-l-and-sscanf-l-ASan-/0001-stdio-h-Add-ucrt-sprintf-l-declaration.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 11e7024c52fe4ded7ac5790d83335012ef31137f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= -Date: Sat, 9 Nov 2024 00:13:03 +0100 -Subject: [PATCH] stdio.h: Add ucrt _sprintf_l declaration. - ---- - include/msvcrt/stdio.h | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/include/msvcrt/stdio.h b/include/msvcrt/stdio.h -index 8c75930322e..1e1d28f3f70 100644 ---- a/include/msvcrt/stdio.h -+++ b/include/msvcrt/stdio.h -@@ -326,6 +326,19 @@ static inline int __cdecl printf_s(const char *format, ...) - return ret; - } - -+static inline int __cdecl _sprintf_l(char *buffer, const char *format, _locale_t locale, ...) __WINE_CRT_PRINTF_ATTR(2, 4); -+static inline int __cdecl _sprintf_l(char *buffer, const char *format, _locale_t locale, ...) -+{ -+ int ret; -+ va_list args; -+ -+ va_start(args, locale); -+ ret = __stdio_common_vsprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, -+ buffer, -1, format, locale, args); -+ va_end(args); -+ return ret < 0 ? -1 : ret; -+} -+ - static inline int __cdecl sscanf(const char *buffer, const char *format, ...) __WINE_CRT_SCANF_ATTR(2, 3); - static inline int __cdecl sscanf(const char *buffer, const char *format, ...) - { -@@ -519,6 +532,7 @@ static inline int __cdecl sprintf(char *buffer, const char *format, ...) - _ACRTIMP int __cdecl snprintf(char*,size_t,const char*,...) __WINE_CRT_PRINTF_ATTR(3, 4); - _ACRTIMP int __cdecl _snprintf(char*,size_t,const char*,...) __WINE_CRT_PRINTF_ATTR(3, 4); - _ACRTIMP int __cdecl sprintf(char*,const char*,...) __WINE_CRT_PRINTF_ATTR(2, 3); -+_ACRTIMP int __cdecl _sprintf_l(char*,const char*,_locale_t,...) __WINE_CRT_PRINTF_ATTR(2, 4); - - #endif /* !_NO_CRT_STDIO_INLINE */ - --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6787-wineps-drv-Use-locale-aware-variants-sprintf-l-and-sscanf-l-ASan-/0002-wineps-drv-Use-locale-aware-variants-sprintf-l-and-sscanf-l-ASan-.patch b/0003-pending-mrs-and-backports/6787-wineps-drv-Use-locale-aware-variants-sprintf-l-and-sscanf-l-ASan-/0002-wineps-drv-Use-locale-aware-variants-sprintf-l-and-sscanf-l-ASan-.patch deleted file mode 100644 index 6382dd2..0000000 --- a/0003-pending-mrs-and-backports/6787-wineps-drv-Use-locale-aware-variants-sprintf-l-and-sscanf-l-ASan-/0002-wineps-drv-Use-locale-aware-variants-sprintf-l-and-sscanf-l-ASan-.patch +++ /dev/null @@ -1,176 +0,0 @@ -From 481ddf9798e3c0fcd5055e9514f5bd7ed2f8d506 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= -Date: Tue, 5 Nov 2024 17:40:00 +0100 -Subject: [PATCH] wineps.drv: Use locale aware variants _sprintf_l and - _sscanf_l. (ASan) - -Currently are the macros push_lc_numeric/pop_lc_numeric in place -to temporary switch locale for sprintf and sscanf calls. - -This macros retrieve current locale, save it to a temporary -variable "tmplocale", in between is the call to sprintf or sscanf, -and restore the old locale from the temproary variable. - -But in the second setlocale call the pointer in tmplocale gets freed. - -Therefore ASan gets triggered in the third setlocale call when it -attempts to read the already freed memory. - -This patch avoids this by removing this switching altogether. ---- - dlls/wineps.drv/init.c | 4 ++++ - dlls/wineps.drv/ppd.c | 9 ++------- - dlls/wineps.drv/ps.c | 17 ++++------------- - dlls/wineps.drv/psdrv.h | 8 +------- - dlls/wineps.drv/type42.c | 8 +++----- - 5 files changed, 14 insertions(+), 32 deletions(-) - -diff --git a/dlls/wineps.drv/init.c b/dlls/wineps.drv/init.c -index ec4dc174cf9..2893c92d30f 100644 ---- a/dlls/wineps.drv/init.c -+++ b/dlls/wineps.drv/init.c -@@ -21,6 +21,7 @@ - - #include - #include -+#include - - #include "windef.h" - #include "winbase.h" -@@ -87,6 +88,7 @@ static const PSDRV_DEVMODE DefaultDevmode = - - HINSTANCE PSDRV_hInstance = 0; - HANDLE PSDRV_Heap = 0; -+_locale_t c_locale; - - static BOOL import_ntf_from_reg(void) - { -@@ -294,6 +296,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) - { - PSDRV_hInstance = hinst; - DisableThreadLibraryCalls(hinst); -+ c_locale = _create_locale( LC_ALL, "C" ); - - if (__wine_init_unix_call()) - return FALSE; -@@ -319,6 +322,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) - case DLL_PROCESS_DETACH: - if (reserved) break; - WINE_UNIX_CALL(unix_free_printer_info, NULL); -+ _free_locale( c_locale ); - HeapDestroy( PSDRV_Heap ); - break; - } -diff --git a/dlls/wineps.drv/ppd.c b/dlls/wineps.drv/ppd.c -index d116f8ebbc0..a1f66cd27b5 100644 ---- a/dlls/wineps.drv/ppd.c -+++ b/dlls/wineps.drv/ppd.c -@@ -884,10 +884,7 @@ PPD *PSDRV_ParsePPD( const WCHAR *fname, HANDLE printer ) - #define PIA page->ImageableArea - if(!PIA) { - PIA = HeapAlloc( PSDRV_Heap, 0, sizeof(*PIA) ); -- push_lc_numeric("C"); -- sscanf(tuple.value, "%f%f%f%f", &PIA->llx, &PIA->lly, -- &PIA->urx, &PIA->ury); -- pop_lc_numeric(); -+ _sscanf_l(tuple.value, "%f%f%f%f", c_locale, &PIA->llx, &PIA->lly, &PIA->urx, &PIA->ury); - } - #undef PIA - } -@@ -908,9 +905,7 @@ PPD *PSDRV_ParsePPD( const WCHAR *fname, HANDLE printer ) - #define PD page->PaperDimension - if(!PD) { - PD = HeapAlloc( PSDRV_Heap, 0, sizeof(*PD) ); -- push_lc_numeric("C"); -- sscanf(tuple.value, "%f%f", &PD->x, &PD->y); -- pop_lc_numeric(); -+ _sscanf_l(tuple.value, "%f%f", c_locale, &PD->x, &PD->y); - } - #undef PD - } -diff --git a/dlls/wineps.drv/ps.c b/dlls/wineps.drv/ps.c -index 8e52a97867a..7a8feeaedb8 100644 ---- a/dlls/wineps.drv/ps.c -+++ b/dlls/wineps.drv/ps.c -@@ -625,9 +625,7 @@ BOOL PSDRV_WriteArc(print_ctx *ctx, INT x, INT y, INT w, INT h, double ang1, - - /* Make angles -ve and swap order because we're working with an upside - down y-axis */ -- push_lc_numeric("C"); -- sprintf(buf, psarc, x, y, w, h, -ang2, -ang1); -- pop_lc_numeric(); -+ _sprintf_l(buf, psarc, c_locale, x, y, w, h, -ang2, -ang1); - return PSDRV_WriteSpool(ctx, buf, strlen(buf)); - } - -@@ -678,16 +676,11 @@ BOOL PSDRV_WriteSetColor(print_ctx *ctx, PSCOLOR *color) - - switch(color->type) { - case PSCOLOR_RGB: -- push_lc_numeric("C"); -- sprintf(buf, pssetrgbcolor, color->value.rgb.r, color->value.rgb.g, -- color->value.rgb.b); -- pop_lc_numeric(); -+ _sprintf_l(buf, pssetrgbcolor, c_locale, color->value.rgb.r, color->value.rgb.g, color->value.rgb.b); - return PSDRV_WriteSpool(ctx, buf, strlen(buf)); - - case PSCOLOR_GRAY: -- push_lc_numeric("C"); -- sprintf(buf, pssetgray, color->value.gray.i); -- pop_lc_numeric(); -+ _sprintf_l(buf, pssetgray, c_locale, color->value.gray.i); - return PSDRV_WriteSpool(ctx, buf, strlen(buf)); - - default: -@@ -786,9 +779,7 @@ BOOL PSDRV_WriteRotate(print_ctx *ctx, float ang) - { - char buf[256]; - -- push_lc_numeric("C"); -- sprintf(buf, psrotate, ang); -- pop_lc_numeric(); -+ _sprintf_l(buf, psrotate, c_locale, ang); - return PSDRV_WriteSpool(ctx, buf, strlen(buf)); - } - -diff --git a/dlls/wineps.drv/psdrv.h b/dlls/wineps.drv/psdrv.h -index 2c4703de942..c69b2994479 100644 ---- a/dlls/wineps.drv/psdrv.h -+++ b/dlls/wineps.drv/psdrv.h -@@ -544,13 +544,7 @@ extern DWORD ASCII85_encode(BYTE *in_buf, DWORD len, BYTE *out_buf); - extern void passthrough_enter(print_ctx *ctx); - extern void passthrough_leave(print_ctx *ctx); - --#define push_lc_numeric(x) do { \ -- const char *tmplocale = setlocale(LC_NUMERIC,NULL); \ -- setlocale(LC_NUMERIC,x); -- --#define pop_lc_numeric() \ -- setlocale(LC_NUMERIC,tmplocale); \ --} while (0) -+extern _locale_t c_locale; - - static inline WCHAR *strdupW( const WCHAR *str ) - { -diff --git a/dlls/wineps.drv/type42.c b/dlls/wineps.drv/type42.c -index 0867881b68e..4f598962b73 100644 ---- a/dlls/wineps.drv/type42.c -+++ b/dlls/wineps.drv/type42.c -@@ -203,11 +203,9 @@ TYPE42 *T42_download_header(print_ctx *ctx, char *ps_name, - buf = HeapAlloc(GetProcessHeap(), 0, sizeof(start) + strlen(ps_name) + - 100); - -- push_lc_numeric("C"); -- sprintf(buf, start, ps_name, -- (float)bbox->left / emsize, (float)bbox->bottom / emsize, -- (float)bbox->right / emsize, (float)bbox->top / emsize); -- pop_lc_numeric(); -+ _sprintf_l(buf, start, c_locale, ps_name, -+ (float)bbox->left / emsize, (float)bbox->bottom / emsize, -+ (float)bbox->right / emsize, (float)bbox->top / emsize); - - PSDRV_WriteSpool(ctx, buf, strlen(buf)); - --- -GitLab - diff --git a/0003-pending-mrs-and-backports/6806-wined3d-Allow-reusing-current-GL-context-without-a-current-RT/0001-wined3d-Allow-reusing-current-GL-context-without-a-current-RT.patch b/0003-pending-mrs-and-backports/6806-wined3d-Allow-reusing-current-GL-context-without-a-current-RT/0001-wined3d-Allow-reusing-current-GL-context-without-a-current-RT.patch deleted file mode 100644 index c04c61a..0000000 --- a/0003-pending-mrs-and-backports/6806-wined3d-Allow-reusing-current-GL-context-without-a-current-RT/0001-wined3d-Allow-reusing-current-GL-context-without-a-current-RT.patch +++ /dev/null @@ -1,26 +0,0 @@ -From ff79da8f72e0b153a54e0337bf60a4877f9af76a Mon Sep 17 00:00:00 2001 -From: Matteo Bruni -Date: Mon, 8 Jan 2024 12:24:18 +0100 -Subject: [PATCH] wined3d: Allow reusing current GL context without a current - RT. - -Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57411 ---- - dlls/wined3d/context_gl.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c -index 6b606617f3d..93282529123 100644 ---- a/dlls/wined3d/context_gl.c -+++ b/dlls/wined3d/context_gl.c -@@ -4355,7 +4355,6 @@ struct wined3d_context *wined3d_context_gl_acquire(const struct wined3d_device * - if (!texture) - { - if (current_context -- && current_context->c.current_rt.texture - && current_context->c.device == device) - { - texture = current_context->c.current_rt.texture; --- -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 new file mode 100644 index 0000000..46aedb5 --- /dev/null +++ b/0003-pending-mrs-and-backports/6838-msi-Dynamically-determine-supported-package-architectures/0001-msi-Dynamically-determine-supported-package-architectures.patch @@ -0,0 +1,74 @@ +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/6841-wow64-Support-running-a-BT-module-provided-suspend-routine/0001-ntdll-Implement-WOW64-thread-suspension-helpers.patch b/0003-pending-mrs-and-backports/6841-wow64-Support-running-a-BT-module-provided-suspend-routine/0001-ntdll-Implement-WOW64-thread-suspension-helpers.patch new file mode 100644 index 0000000..5e62070 --- /dev/null +++ b/0003-pending-mrs-and-backports/6841-wow64-Support-running-a-BT-module-provided-suspend-routine/0001-ntdll-Implement-WOW64-thread-suspension-helpers.patch @@ -0,0 +1,138 @@ +From 772f54e2666f4a862bbfbd916c3d53c2b89b8b8b Mon Sep 17 00:00:00 2001 +From: Billy Laws +Date: Thu, 27 Jul 2023 08:00:43 -0700 +Subject: [PATCH] ntdll: Implement WOW64 thread suspension helpers. + +--- + dlls/ntdll/loader.c | 2 ++ + dlls/ntdll/ntdll.spec | 1 + + dlls/ntdll/ntdll_misc.h | 1 + + dlls/ntdll/signal_arm64.c | 17 +++++++++++++++++ + dlls/ntdll/signal_arm64ec.c | 7 +++++++ + dlls/ntdll/signal_x86_64.c | 7 +++++++ + include/winternl.h | 1 + + 7 files changed, 36 insertions(+) + +diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c +index 2f2a7fe5427..4ed27e734d6 100644 +--- a/dlls/ntdll/loader.c ++++ b/dlls/ntdll/loader.c +@@ -4261,6 +4261,7 @@ static void build_wow64_main_module(void) + static void (WINAPI *pWow64LdrpInitialize)( CONTEXT *ctx ); + + void (WINAPI *pWow64PrepareForException)( EXCEPTION_RECORD *rec, CONTEXT *context ) = NULL; ++NTSTATUS (WINAPI *pWow64SuspendLocalThread)( HANDLE thread, ULONG *count ) = NULL; + + static void init_wow64( CONTEXT *context ) + { +@@ -4285,6 +4286,7 @@ static void init_wow64( CONTEXT *context ) + + GET_PTR( Wow64LdrpInitialize ); + GET_PTR( Wow64PrepareForException ); ++ GET_PTR( Wow64SuspendLocalThread ); + #undef GET_PTR + imports_fixup_done = TRUE; + } +diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec +index ddf1a120517..70f2315a778 100644 +--- a/dlls/ntdll/ntdll.spec ++++ b/dlls/ntdll/ntdll.spec +@@ -1126,6 +1126,7 @@ + @ stdcall -arch=win64 RtlWow64PushCrossProcessWorkOntoWorkList(ptr ptr ptr) + @ stdcall -arch=win64 RtlWow64RequestCrossProcessHeavyFlush(ptr) + @ stdcall -arch=win64 RtlWow64SetThreadContext(long ptr) ++@ stdcall -arch=win64 RtlWow64SuspendThread(long ptr) + @ stub RtlWriteMemoryStream + @ stdcall RtlWriteRegistryValue(long ptr wstr long ptr long) + @ stub RtlZeroHeap +diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h +index e58a07ba02a..5196db9bb28 100644 +--- a/dlls/ntdll/ntdll_misc.h ++++ b/dlls/ntdll/ntdll_misc.h +@@ -78,6 +78,7 @@ extern void WINAPI KiUserApcDispatcher(CONTEXT*,ULONG_PTR,ULONG_PTR,ULONG_PTR,PN + extern void WINAPI KiUserCallbackDispatcher(ULONG,void*,ULONG); + extern void WINAPI KiUserCallbackDispatcherReturn(void); + extern void (WINAPI *pWow64PrepareForException)( EXCEPTION_RECORD *rec, CONTEXT *context ); ++extern NTSTATUS (WINAPI *pWow64SuspendLocalThread)( HANDLE thread, ULONG *count ); + + /* debug helpers */ + extern LPCSTR debugstr_us( const UNICODE_STRING *str ); +diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c +index c8eafc36211..0b6a414aabe 100644 +--- a/dlls/ntdll/signal_arm64.c ++++ b/dlls/ntdll/signal_arm64.c +@@ -643,6 +643,23 @@ BOOLEAN WINAPI RtlIsProcessorFeaturePresent( UINT feature ) + user_shared_data->ProcessorFeatures[feature]); + } + ++/*********************************************************************** ++ * RtlWow64SuspendThread (NTDLL.@) ++ */ ++NTSTATUS WINAPI RtlWow64SuspendThread( HANDLE thread, ULONG *count ) ++{ ++ THREAD_BASIC_INFORMATION tbi; ++ ++ NTSTATUS ret = NtQueryInformationThread( thread, ThreadBasicInformation, &tbi, sizeof(tbi), NULL); ++ if (ret) return ret; ++ ++ if (tbi.ClientId.UniqueProcess != NtCurrentTeb()->ClientId.UniqueProcess) { ++ FIXME( "Non-local process thread suspend\n" ); ++ return STATUS_SUCCESS; ++ } ++ ++ return pWow64SuspendLocalThread( thread, count ); ++} + + /************************************************************************* + * RtlWalkFrameChain (NTDLL.@) +diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c +index 438dfe8d439..1652be4a896 100644 +--- a/dlls/ntdll/signal_arm64ec.c ++++ b/dlls/ntdll/signal_arm64ec.c +@@ -1656,6 +1656,13 @@ BOOLEAN WINAPI RtlIsProcessorFeaturePresent( UINT feature ) + return emulated_processor_features[feature]; + } + ++/*********************************************************************** ++ * RtlWow64SuspendThread (NTDLL.@) ++ */ ++NTSTATUS WINAPI RtlWow64SuspendThread( HANDLE thread, ULONG *count ) ++{ ++ return NtSuspendThread( thread, count ); ++} + + /************************************************************************* + * RtlWalkFrameChain (NTDLL.@) +diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c +index 7320aeabd49..24e513de0ef 100644 +--- a/dlls/ntdll/signal_x86_64.c ++++ b/dlls/ntdll/signal_x86_64.c +@@ -846,6 +846,13 @@ BOOLEAN WINAPI RtlIsProcessorFeaturePresent( UINT feature ) + return feature < PROCESSOR_FEATURE_MAX && user_shared_data->ProcessorFeatures[feature]; + } + ++/*********************************************************************** ++ * RtlWow64SuspendThread (NTDLL.@) ++ */ ++NTSTATUS WINAPI RtlWow64SuspendThread( HANDLE thread, ULONG *count ) ++{ ++ return NtSuspendThread( thread, count ); ++} + + /************************************************************************* + * RtlWalkFrameChain (NTDLL.@) +diff --git a/include/winternl.h b/include/winternl.h +index bc3ef12bc0d..1f30811e0e7 100644 +--- a/include/winternl.h ++++ b/include/winternl.h +@@ -5119,6 +5119,7 @@ NTSYSAPI USHORT WINAPI RtlWow64GetCurrentMachine(void); + NTSYSAPI NTSTATUS WINAPI RtlWow64GetProcessMachines(HANDLE,USHORT*,USHORT*); + NTSYSAPI NTSTATUS WINAPI RtlWow64GetSharedInfoProcess(HANDLE,BOOLEAN*,WOW64INFO*); + NTSYSAPI NTSTATUS WINAPI RtlWow64IsWowGuestMachineSupported(USHORT,BOOLEAN*); ++NTSYSAPI NTSTATUS WINAPI RtlWow64SuspendThread(HANDLE,ULONG*); + NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG,PCWSTR,PCWSTR,ULONG,PVOID,ULONG); + NTSYSAPI NTSTATUS WINAPI RtlZombifyActivationContext(HANDLE); + NTSYSAPI NTSTATUS WINAPI RtlpNtCreateKey(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES*,ULONG,const UNICODE_STRING*,ULONG,PULONG); +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6841-wow64-Support-running-a-BT-module-provided-suspend-routine/0002-wow64-Support-running-a-BT-module-provided-suspend-routine.patch b/0003-pending-mrs-and-backports/6841-wow64-Support-running-a-BT-module-provided-suspend-routine/0002-wow64-Support-running-a-BT-module-provided-suspend-routine.patch new file mode 100644 index 0000000..1762c48 --- /dev/null +++ b/0003-pending-mrs-and-backports/6841-wow64-Support-running-a-BT-module-provided-suspend-routine/0002-wow64-Support-running-a-BT-module-provided-suspend-routine.patch @@ -0,0 +1,74 @@ +From 69375a437de103e35e76c2a25de330ca837dc17e Mon Sep 17 00:00:00 2001 +From: Billy Laws +Date: Thu, 27 Jul 2023 08:20:59 -0700 +Subject: [PATCH] wow64: Support running a BT module provided suspend routine. + +Suspension in JITs cannot easily be handled on the unix side, so allow BT +modules to provide their own suspend helper. +--- + dlls/wow64/process.c | 2 +- + dlls/wow64/syscall.c | 10 ++++++++++ + dlls/wow64/wow64.spec | 2 +- + 3 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/dlls/wow64/process.c b/dlls/wow64/process.c +index 0153dba3433..6cb2fb0125f 100644 +--- a/dlls/wow64/process.c ++++ b/dlls/wow64/process.c +@@ -1054,7 +1054,7 @@ NTSTATUS WINAPI wow64_NtSuspendThread( UINT *args ) + HANDLE handle = get_handle( &args ); + ULONG *count = get_ptr( &args ); + +- return NtSuspendThread( handle, count ); ++ return RtlWow64SuspendThread( handle, count ); + } + + +diff --git a/dlls/wow64/syscall.c b/dlls/wow64/syscall.c +index 790656b311e..db58a15ce9c 100644 +--- a/dlls/wow64/syscall.c ++++ b/dlls/wow64/syscall.c +@@ -102,6 +102,7 @@ static void (WINAPI *pBTCpuProcessInit)(void); + static NTSTATUS (WINAPI *pBTCpuSetContext)(HANDLE,HANDLE,void *,void *); + static void (WINAPI *pBTCpuThreadInit)(void); + static void (WINAPI *pBTCpuSimulate)(void) __attribute__((used)); ++static NTSTATUS (WINAPI *pBTCpuSuspendLocalThread)(HANDLE,ULONG *); + static void * (WINAPI *p__wine_get_unix_opcode)(void); + static void * (WINAPI *pKiRaiseUserExceptionDispatcher)(void); + void (WINAPI *pBTCpuFlushInstructionCache2)( const void *, SIZE_T ) = NULL; +@@ -824,6 +825,7 @@ static DWORD WINAPI process_init( RTL_RUN_ONCE *once, void *param, void **contex + GET_PTR( BTCpuProcessInit ); + GET_PTR( BTCpuThreadInit ); + GET_PTR( BTCpuResetToConsistentState ); ++ GET_PTR( BTCpuSuspendLocalThread ); + GET_PTR( BTCpuSetContext ); + GET_PTR( BTCpuSimulate ); + GET_PTR( BTCpuFlushInstructionCache2 ); +@@ -1510,3 +1512,11 @@ NTSTATUS WINAPI Wow64RaiseException( int code, EXCEPTION_RECORD *rec ) + + return STATUS_SUCCESS; + } ++ ++/********************************************************************** ++ * Wow64SuspendLocalThread (wow64.@) ++ */ ++NTSTATUS WINAPI Wow64SuspendLocalThread( HANDLE thread, ULONG *count ) ++{ ++ return pBTCpuSuspendLocalThread( thread, count ); ++} +diff --git a/dlls/wow64/wow64.spec b/dlls/wow64/wow64.spec +index 5b4e565e593..8f95dfcdbe5 100644 +--- a/dlls/wow64/wow64.spec ++++ b/dlls/wow64/wow64.spec +@@ -22,7 +22,7 @@ + @ stub Wow64ShallowThunkAllocSecurityQualityOfService32TO64_FNC + @ stub Wow64ShallowThunkSIZE_T32TO64 + @ stub Wow64ShallowThunkSIZE_T64TO32 +-@ stub Wow64SuspendLocalThread ++@ stdcall Wow64SuspendLocalThread(long ptr) + @ stdcall -norelay Wow64SystemServiceEx(long ptr) + @ stub Wow64ValidateUserCallTarget + @ stub Wow64ValidateUserCallTargetFilter +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/6848-mf-evr-Increase-the-number-of-prerolled-samples-to-3/0001-mf-evr-Increase-the-number-of-prerolled-samples-to-3.patch b/0003-pending-mrs-and-backports/6848-mf-evr-Increase-the-number-of-prerolled-samples-to-3/0001-mf-evr-Increase-the-number-of-prerolled-samples-to-3.patch new file mode 100644 index 0000000..c3c7d40 --- /dev/null +++ b/0003-pending-mrs-and-backports/6848-mf-evr-Increase-the-number-of-prerolled-samples-to-3/0001-mf-evr-Increase-the-number-of-prerolled-samples-to-3.patch @@ -0,0 +1,72 @@ +From 11dac8e157770d6337837cbf799ecb3115bbc7b3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Fri, 8 Dec 2023 15:42:32 +0100 +Subject: [PATCH] mf/evr: Increase the number of prerolled samples to 3. + +Fixes some stuttering in Secret of Mana. + +Native seems to only preroll 2 samples, but it still stutters a bit in +Secret of Mana without at least 3 buffers. This is probably caused by +a different sample decoding pattern, and 3 buffers in flight should be +fine. +--- + dlls/mf/evr.c | 15 ++++++++++++--- + dlls/mf/session.c | 2 +- + 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c +index db7053a1405..5ac526c9651 100644 +--- a/dlls/mf/evr.c ++++ b/dlls/mf/evr.c +@@ -64,6 +64,7 @@ struct video_stream + LONG refcount; + unsigned int id; + unsigned int flags; ++ unsigned int preroll_count; + struct video_renderer *parent; + IMFMediaEventQueue *event_queue; + IMFVideoSampleAllocator *allocator; +@@ -420,9 +421,16 @@ static HRESULT WINAPI video_stream_sink_ProcessSample(IMFStreamSink *iface, IMFS + + if (stream->flags & EVR_STREAM_PREROLLING) + { +- IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkPrerolled, &GUID_NULL, S_OK, NULL); +- stream->flags &= ~EVR_STREAM_PREROLLING; +- stream->flags |= EVR_STREAM_PREROLLED; ++ if (stream->preroll_count--) ++ IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample, ++ &GUID_NULL, S_OK, NULL); ++ else ++ { ++ IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkPrerolled, ++ &GUID_NULL, S_OK, NULL); ++ stream->flags &= ~EVR_STREAM_PREROLLING; ++ stream->flags |= EVR_STREAM_PREROLLED; ++ } + } + } + +@@ -1528,6 +1536,7 @@ static HRESULT WINAPI video_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll * + IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample, + &GUID_NULL, S_OK, NULL); + stream->flags |= EVR_STREAM_PREROLLING; ++ stream->preroll_count = 3; + } + LeaveCriticalSection(&stream->cs); + } +diff --git a/dlls/mf/session.c b/dlls/mf/session.c +index 3c989249229..d01f2728782 100644 +--- a/dlls/mf/session.c ++++ b/dlls/mf/session.c +@@ -1798,7 +1798,7 @@ static HRESULT session_append_node(struct media_session *session, IMFTopologyNod + &IID_IMFVideoSampleAllocator, (void **)&topo_node->u.sink.allocator))) + { + if (FAILED(hr = IMFVideoSampleAllocator_InitializeSampleAllocator(topo_node->u.sink.allocator, +- 2, media_type))) ++ 4, media_type))) + { + WARN("Failed to initialize sample allocator for the stream, hr %#lx.\n", hr); + } +-- +GitLab + diff --git a/0003-pending-mrs-and-backports/9999-misc-loose/0003-ps5483-server-Correctly-align-64-bit-integer-types.patch b/0003-pending-mrs-and-backports/9999-misc-loose/0003-ps5483-server-Correctly-align-64-bit-integer-types.patch index 7743c6a..ee608b7 100644 --- a/0003-pending-mrs-and-backports/9999-misc-loose/0003-ps5483-server-Correctly-align-64-bit-integer-types.patch +++ b/0003-pending-mrs-and-backports/9999-misc-loose/0003-ps5483-server-Correctly-align-64-bit-integer-types.patch @@ -332,3 +332,17 @@ index 6148f072919..ea3a4978305 100755 -- GitLab +fixup for 75e2ec479beff86c52bebdab6d5e8b78c8f6ca8d +diff --git a/tools/make_requests b/tools/make_requests +index 11111111111..11111111111 100755 +--- a/tools/make_requests ++++ b/tools/make_requests +@@ -34,7 +34,7 @@ my %formats = + "atom_t" => [ 4, 4, "%04x" ], + "process_id_t" => [ 4, 4, "%04x" ], + "thread_id_t" => [ 4, 4, "%04x" ], +- "unsigned __int64" => [ 8, 8, "&uint64" ], ++ "UINT64" => [ 8, 8, "&uint64" ], + "timeout_t" => [ 8, 8 ], + "abstime_t" => [ 8, 8 ], + "rectangle_t" => [ 16, 4 ], diff --git a/0003-pending-mrs-and-backports/9999-misc-loose/0110-ps6211-wined3d-Fix-a-memory-leak.patch b/0003-pending-mrs-and-backports/9999-misc-loose/0110-ps6211-wined3d-Fix-a-memory-leak.patch deleted file mode 100644 index 313ec63..0000000 --- a/0003-pending-mrs-and-backports/9999-misc-loose/0110-ps6211-wined3d-Fix-a-memory-leak.patch +++ /dev/null @@ -1,24 +0,0 @@ -From b63bcb68f61910196b58d7e7d2d0f59ea9884a26 Mon Sep 17 00:00:00 2001 -From: Haoyang Chen -Date: Tue, 6 Aug 2024 15:35:01 +0800 -Subject: [PATCH] wined3d: Fix a memory leak. - ---- - dlls/wined3d/context_gl.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c -index 75f94678e14..cc7f766b20a 100644 ---- a/dlls/wined3d/context_gl.c -+++ b/dlls/wined3d/context_gl.c -@@ -1286,6 +1286,7 @@ static BOOL wined3d_context_gl_set_gl_context(struct wined3d_context_gl *context - return FALSE; - } - -+ wined3d_release_dc(context_gl->window, context_gl->dc); - if (!(context_gl->dc = wined3d_device_gl_get_backup_dc(device_gl))) - { - wined3d_context_gl_set_current(NULL); --- -GitLab - diff --git a/0003-pending-mrs-and-backports/9999-misc-loose/0125-ps6346-winex11.drv-Properly-check-if-the-desktop-window-is-fullscreen.patch b/0003-pending-mrs-and-backports/9999-misc-loose/0125-ps6346-winex11.drv-Properly-check-if-the-desktop-window-is-fullscreen.patch deleted file mode 100644 index 55f743f..0000000 --- a/0003-pending-mrs-and-backports/9999-misc-loose/0125-ps6346-winex11.drv-Properly-check-if-the-desktop-window-is-fullscreen.patch +++ /dev/null @@ -1,214 +0,0 @@ -From a65ed1eaa8bdf544766cf1a0b2c2c162ae71e743 Mon Sep 17 00:00:00 2001 -From: Zhiyi Zhang -Date: Thu, 22 Aug 2024 11:55:22 +0800 -Subject: [PATCH 1/2] winex11.drv: Delete unused parameters for - X11DRV_init_desktop(). - ---- - dlls/winex11.drv/desktop.c | 4 ++-- - dlls/winex11.drv/window.c | 2 +- - dlls/winex11.drv/x11drv.h | 2 +- - 3 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c -index dae0d652737..da9edfecaa8 100644 ---- a/dlls/winex11.drv/desktop.c -+++ b/dlls/winex11.drv/desktop.c -@@ -51,7 +51,7 @@ BOOL is_virtual_desktop(void) - * - * Setup the desktop when not using the root window. - */ --void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) -+void X11DRV_init_desktop( Window win ) - { - host_primary_rect = get_host_primary_monitor_rect(); - root_window = win; -@@ -90,7 +90,7 @@ BOOL X11DRV_CreateDesktop( const WCHAR *name, UINT width, UINT height ) - x11drv_xinput2_enable( display, win ); - XFlush( display ); - -- X11DRV_init_desktop( win, width, height ); -+ X11DRV_init_desktop( win ); - return TRUE; - } - -diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c -index 0e06939f67d..f1a609d4cd5 100644 ---- a/dlls/winex11.drv/window.c -+++ b/dlls/winex11.drv/window.c -@@ -1948,7 +1948,7 @@ void X11DRV_SetDesktopWindow( HWND hwnd ) - else - { - Window win = (Window)NtUserGetProp( hwnd, whole_window_prop ); -- if (win && win != root_window) X11DRV_init_desktop( win, width, height ); -+ if (win && win != root_window) X11DRV_init_desktop( win ); - } - } - -diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h -index 9c47a7462ba..6a157befeae 100644 ---- a/dlls/winex11.drv/x11drv.h -+++ b/dlls/winex11.drv/x11drv.h -@@ -740,7 +740,7 @@ struct x11drv_settings_handler - - extern void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *handler); - --extern void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ); -+extern void X11DRV_init_desktop( Window win ); - extern BOOL is_virtual_desktop(void); - extern BOOL is_desktop_fullscreen(void); - extern BOOL is_detached_mode(const DEVMODEW *); --- -GitLab - - -From f25a4e2c48f69559bd2512d627b562194361ddd7 Mon Sep 17 00:00:00 2001 -From: Zhiyi Zhang -Date: Thu, 22 Aug 2024 12:14:31 +0800 -Subject: [PATCH 2/2] winex11.drv: Properly check if the desktop window is - fullscreen on multi-monitor systems. - -If there are two monitors and the primary monitor is on the right side and the virtual desktop -resolution happens to be the same as the primary monitor, then the X11 desktop window will -not have window frames and show as a fullscreen window before this patch. is_desktop_fullscreen() -should check which monitor that it is on to decide whether to use fullscreen mode instead of always -checking against the primary monitor. ---- - dlls/winex11.drv/desktop.c | 23 ++++++++++---- - dlls/winex11.drv/display.c | 61 ++++++++++++++++++++++++++++++++++++++ - dlls/winex11.drv/x11drv.h | 1 + - 3 files changed, 80 insertions(+), 5 deletions(-) - -diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c -index da9edfecaa8..29d454e0e97 100644 ---- a/dlls/winex11.drv/desktop.c -+++ b/dlls/winex11.drv/desktop.c -@@ -35,7 +35,8 @@ - - WINE_DEFAULT_DEBUG_CHANNEL(x11drv); - --static RECT host_primary_rect; -+static RECT *host_monitor_rects; -+static int host_monitor_rect_count; - - #define _NET_WM_STATE_REMOVE 0 - #define _NET_WM_STATE_ADD 1 -@@ -53,7 +54,9 @@ BOOL is_virtual_desktop(void) - */ - void X11DRV_init_desktop( Window win ) - { -- host_primary_rect = get_host_primary_monitor_rect(); -+ if (host_monitor_rects) free( host_monitor_rects ); -+ if (!get_host_monitor_rects( &host_monitor_rects, &host_monitor_rect_count )) -+ ERR("Failed to get host monitor rectangle.\n"); - root_window = win; - managed_mode = FALSE; /* no managed windows in desktop mode */ - } -@@ -96,7 +99,17 @@ BOOL X11DRV_CreateDesktop( const WCHAR *name, UINT width, UINT height ) - - BOOL is_desktop_fullscreen(void) - { -- RECT primary_rect = NtUserGetPrimaryMonitorRect(); -- return (primary_rect.right - primary_rect.left == host_primary_rect.right - host_primary_rect.left && -- primary_rect.bottom - primary_rect.top == host_primary_rect.bottom - host_primary_rect.top); -+ Display *display = thread_display(); -+ unsigned int width, height, border, depth; -+ int x, y, i; -+ Window root; -+ RECT rect; -+ -+ XGetGeometry( display, root_window, &root, &x, &y, &width, &height, &border, &depth ); -+ SetRect( &rect, x, y, x + width, y + height ); -+ -+ for (i = 0; i < host_monitor_rect_count; i++) -+ if (EqualRect( &host_monitor_rects[i], &rect) ) return TRUE; -+ -+ return FALSE; - } -diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c -index 6b92e046fb8..3187f23ea9a 100644 ---- a/dlls/winex11.drv/display.c -+++ b/dlls/winex11.drv/display.c -@@ -415,6 +415,67 @@ RECT get_host_primary_monitor_rect(void) - return rect; - } - -+/* Get an array of host monitor rectangles in X11 root coordinates. Free the array when it's done */ -+BOOL get_host_monitor_rects( RECT **ret_rects, int *ret_count ) -+{ -+ int gpu_count, adapter_count, monitor_count, rect_count = 0; -+ int gpu_idx, adapter_idx, monitor_idx, rect_idx; -+ struct x11drv_gpu *gpus = NULL; -+ struct x11drv_adapter *adapters = NULL; -+ struct gdi_monitor *monitors = NULL; -+ RECT *rects = NULL, *new_rects; -+ POINT left_top = {INT_MAX, INT_MAX}; -+ -+ if (!host_handler.get_gpus( &gpus, &gpu_count, FALSE )) goto failed; -+ -+ for (gpu_idx = 0; gpu_idx < gpu_count; gpu_idx++) -+ { -+ if (!host_handler.get_adapters( gpus[gpu_idx].id, &adapters, &adapter_count )) goto failed; -+ -+ for (adapter_idx = 0; adapter_idx < adapter_count; adapter_idx++) -+ { -+ if (!host_handler.get_monitors( adapters[adapter_idx].id, &monitors, &monitor_count )) goto failed; -+ -+ new_rects = realloc( rects, (rect_count + monitor_count) * sizeof(*rects) ); -+ if (!new_rects) goto failed; -+ rects = new_rects; -+ -+ for (monitor_idx = 0; monitor_idx < monitor_count; monitor_idx++) -+ { -+ rects[rect_count++] = monitors[monitor_idx].rc_monitor; -+ left_top.x = min( left_top.x, monitors[monitor_idx].rc_monitor.left ); -+ left_top.y = min( left_top.y, monitors[monitor_idx].rc_monitor.top ); -+ } -+ -+ host_handler.free_monitors( monitors, monitor_count ); -+ monitors = NULL; -+ } -+ -+ host_handler.free_adapters( adapters ); -+ adapters = NULL; -+ } -+ -+ host_handler.free_gpus( gpus, gpu_count ); -+ gpus = NULL; -+ -+ /* Convert from win32 virtual screen coordinates to X11 root coordinates */ -+ for (rect_idx = 0; rect_idx < rect_count; rect_idx++) -+ OffsetRect( &rects[rect_idx], -left_top.x, -left_top.y ); -+ -+ *ret_rects = rects; -+ *ret_count = rect_count; -+ return TRUE; -+ -+failed: -+ if (monitors) host_handler.free_monitors( monitors, monitor_count ); -+ if (adapters) host_handler.free_adapters( adapters ); -+ if (gpus) host_handler.free_gpus( gpus, gpu_count ); -+ free( rects ); -+ *ret_rects = NULL; -+ *ret_count = 0; -+ return FALSE; -+} -+ - RECT get_work_area(const RECT *monitor_rect) - { - Atom type; -diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h -index 6a157befeae..1eae4996266 100644 ---- a/dlls/winex11.drv/x11drv.h -+++ b/dlls/winex11.drv/x11drv.h -@@ -680,6 +680,7 @@ extern int X11DRV_check_error(void); - extern POINT virtual_screen_to_root( INT x, INT y ); - extern POINT root_to_virtual_screen( INT x, INT y ); - extern RECT get_host_primary_monitor_rect(void); -+extern BOOL get_host_monitor_rects( RECT **ret_rects, int *ret_count ); - extern RECT get_work_area( const RECT *monitor_rect ); - extern BOOL xinerama_get_fullscreen_monitors( const RECT *rect, long *indices ); - extern void xinerama_init( unsigned int width, unsigned int height ); --- -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 new file mode 100644 index 0000000..d7f655c --- /dev/null +++ b/0004-build-fix-undebug-optimize/0001-ntdll-Unroll-memcpy-instead-of-preventing-optimisati.patch @@ -0,0 +1,157 @@ +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/0002-msvcrt-Check-for-ERMS-support-and-use-rep-stosb-for-.patch b/0004-build-fix-undebug-optimize/0002-msvcrt-Check-for-ERMS-support-and-use-rep-stosb-for-.patch new file mode 100644 index 0000000..ce83596 --- /dev/null +++ b/0004-build-fix-undebug-optimize/0002-msvcrt-Check-for-ERMS-support-and-use-rep-stosb-for-.patch @@ -0,0 +1,157 @@ +From 72c450bb5195eb3fc6b842940a60564254c3e321 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 14 Sep 2021 14:16:47 +0200 +Subject: [PATCH 2/4] msvcrt: Check for ERMS support and use rep stosb for + large memset calls. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rémi Bernon +--- + dlls/msvcrt/math.c | 13 +++++++++ + dlls/msvcrt/msvcrt.h | 1 + + dlls/msvcrt/string.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 79 insertions(+) + +diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c +index 854403a71bf..ce6e9ccfb4f 100644 +--- a/dlls/msvcrt/math.c ++++ b/dlls/msvcrt/math.c +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + #include "msvcrt.h" + #include "winternl.h" +@@ -64,11 +65,23 @@ typedef int (CDECL *MSVCRT_matherr_func)(struct _exception *); + + static MSVCRT_matherr_func MSVCRT_default_matherr_func = NULL; + ++BOOL erms_supported; + BOOL sse2_supported; + static BOOL sse2_enabled; + + void msvcrt_init_math( void *module ) + { ++#if defined(__i386__) || defined(__x86_64__) ++ int regs[4]; ++ ++ __cpuid(regs, 0); ++ if (regs[0] >= 7) ++ { ++ __cpuidex(regs, 7, 0); ++ erms_supported = ((regs[1] >> 9) & 1); ++ } ++#endif ++ + sse2_supported = IsProcessorFeaturePresent( PF_XMMI64_INSTRUCTIONS_AVAILABLE ); + #if _MSVCR_VER <=71 + sse2_enabled = FALSE; +diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h +index 1d965ff8ffc..29da150db3f 100644 +--- a/dlls/msvcrt/msvcrt.h ++++ b/dlls/msvcrt/msvcrt.h +@@ -33,6 +33,7 @@ + #undef strncpy + #undef wcsncpy + ++extern BOOL erms_supported; + extern BOOL sse2_supported; + + #define DBL80_MAX_10_EXP 4932 +diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c +index d58a21406b1..9a0e899ffa8 100644 +--- a/dlls/msvcrt/string.c ++++ b/dlls/msvcrt/string.c +@@ -3039,6 +3039,13 @@ __ASM_GLOBAL_FUNC( sse2_memmove, + MEMMOVE_CLEANUP + "ret" ) + ++#undef MEMMOVE_INIT ++#undef MEMMOVE_CLEANUP ++#undef DEST_REG ++#undef SRC_REG ++#undef LEN_REG ++#undef TMP_REG ++ + #endif + + /********************************************************************* +@@ -3174,6 +3181,57 @@ void * __cdecl _memccpy(void *dst, const void *src, int c, size_t n) + } + + ++#if defined(__i386__) || defined(__x86_64__) ++ ++#ifdef __i386__ ++#define DEST_REG "%edi" ++#define LEN_REG "%ecx" ++#define VAL_REG "%eax" ++ ++#define MEMSET_INIT \ ++ "movl " DEST_REG ", %edx\n\t" \ ++ "movl 4(%esp), " DEST_REG "\n\t" \ ++ "movl 8(%esp), " VAL_REG "\n\t" \ ++ "movl 12(%esp), " LEN_REG "\n\t" ++ ++#define MEMSET_RET \ ++ "movl %edx, " DEST_REG "\n\t" \ ++ "ret" ++ ++#else ++ ++#define DEST_REG "%rdi" ++#define LEN_REG "%rcx" ++#define VAL_REG "%eax" ++ ++#define MEMSET_INIT \ ++ "movq " DEST_REG ", %r9\n\t" \ ++ "movq %rcx, " DEST_REG "\n\t" \ ++ "movl %edx, " VAL_REG "\n\t" \ ++ "movq %r8, " LEN_REG "\n\t" ++ ++#define MEMSET_RET \ ++ "movq %r9, " DEST_REG "\n\t" \ ++ "ret" ++ ++#endif ++ ++void __cdecl erms_memset_aligned_32(unsigned char *d, unsigned int c, size_t n); ++__ASM_GLOBAL_FUNC( erms_memset_aligned_32, ++ MEMSET_INIT ++ "rep\n\t" ++ "stosb\n\t" ++ MEMSET_RET ) ++ ++#undef MEMSET_INIT ++#undef MEMSET_RET ++#undef DEST_REG ++#undef LEN_REG ++#undef VAL_REG ++ ++#endif ++ ++ + static inline void memset_aligned_32(unsigned char *d, uint64_t v, size_t n) + { + unsigned char *end = d + n; +@@ -3214,6 +3272,13 @@ void *__cdecl memset(void *dst, int c, size_t n) + if (n <= 64) return dst; + + n = (n - a) & ~0x1f; ++#if defined(__i386__) || defined(__x86_64__) ++ if (n >= 2048 && erms_supported) ++ { ++ erms_memset_aligned_32(d + a, v, n); ++ return dst; ++ } ++#endif + memset_aligned_32(d + a, v, n); + return dst; + } +-- +2.45.0 + diff --git a/0004-build-fix-undebug-optimize/0003-msvcrt-Add-an-SSE2-memset_aligned_32-implementation.patch b/0004-build-fix-undebug-optimize/0003-msvcrt-Add-an-SSE2-memset_aligned_32-implementation.patch new file mode 100644 index 0000000..e1bb7cd --- /dev/null +++ b/0004-build-fix-undebug-optimize/0003-msvcrt-Add-an-SSE2-memset_aligned_32-implementation.patch @@ -0,0 +1,68 @@ +From 08eca900cc93c0b3b16efb3c1d82b8c37f3594ec Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 14 Sep 2021 14:16:48 +0200 +Subject: [PATCH 3/4] msvcrt: Add an SSE2 memset_aligned_32 implementation. + +--- + dlls/msvcrt/string.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c +index 9a0e899ffa8..a4e05bd4e7e 100644 +--- a/dlls/msvcrt/string.c ++++ b/dlls/msvcrt/string.c +@@ -3223,6 +3223,29 @@ __ASM_GLOBAL_FUNC( erms_memset_aligned_32, + "stosb\n\t" + MEMSET_RET ) + ++void __cdecl sse2_memset_aligned_32(unsigned char *d, unsigned int c, size_t n); ++__ASM_GLOBAL_FUNC( sse2_memset_aligned_32, ++ MEMSET_INIT ++ "movd " VAL_REG ", %xmm0\n\t" ++ "pshufd $0, %xmm0, %xmm0\n\t" ++ "test $0x20, " LEN_REG "\n\t" ++ "je 1f\n\t" ++ "add $0x20, " DEST_REG "\n\t" ++ "sub $0x20, " LEN_REG "\n\t" ++ "movdqa %xmm0, -0x20(" DEST_REG ")\n\t" ++ "movdqa %xmm0, -0x10(" DEST_REG ")\n\t" ++ "je 2f\n\t" ++ "1:\n\t" ++ "add $0x40, " DEST_REG "\n\t" ++ "sub $0x40, " LEN_REG "\n\t" ++ "movdqa %xmm0, -0x40(" DEST_REG ")\n\t" ++ "movdqa %xmm0, -0x30(" DEST_REG ")\n\t" ++ "movdqa %xmm0, -0x20(" DEST_REG ")\n\t" ++ "movdqa %xmm0, -0x10(" DEST_REG ")\n\t" ++ "ja 1b\n\t" ++ "2:\n\t" ++ MEMSET_RET ) ++ + #undef MEMSET_INIT + #undef MEMSET_RET + #undef DEST_REG +@@ -3278,9 +3301,21 @@ void *__cdecl memset(void *dst, int c, size_t n) + erms_memset_aligned_32(d + a, v, n); + return dst; + } ++#ifdef __x86_64__ ++ sse2_memset_aligned_32(d + a, v, n); ++ return dst; ++#else ++ if (sse2_supported) ++ { ++ sse2_memset_aligned_32(d + a, v, n); ++ return dst; ++ } ++#endif + #endif ++#ifndef __x86_64__ + memset_aligned_32(d + a, v, n); + return dst; ++#endif + } + if (n >= 8) + { +-- +2.45.0 + diff --git a/0004-build-fix-undebug-optimize/2000-configure.ac-Omit-frame-pointers.patch b/0004-build-fix-undebug-optimize/2000-configure.ac-Omit-frame-pointers-and-align-stack.patch similarity index 59% rename from 0004-build-fix-undebug-optimize/2000-configure.ac-Omit-frame-pointers.patch rename to 0004-build-fix-undebug-optimize/2000-configure.ac-Omit-frame-pointers-and-align-stack.patch index ccede93..d350e6c 100644 --- a/0004-build-fix-undebug-optimize/2000-configure.ac-Omit-frame-pointers.patch +++ b/0004-build-fix-undebug-optimize/2000-configure.ac-Omit-frame-pointers-and-align-stack.patch @@ -1,30 +1,39 @@ From 2303f24ee7fb119d9ab3dad1fb6eff3cf911b1ee Mon Sep 17 00:00:00 2001 From: William Horvath Date: Sat, 5 Oct 2024 06:34:55 -0700 -Subject: [PATCH] configure.ac: Omit frame pointers. +Subject: [PATCH v2] configure.ac: Omit frame pointers and align stack on clang. + +Align the stack to 4 bytes for PE targets on clang, same as -mpreferred-stack-boundary=2 for gcc. +The previous version of this patch incorrectly used -mstack-alignment=2, but clang interprets this +as "n" bytes, while gcc uses "2^n" bytes. + +https://linux.kernel.narkive.com/y7hAplfS/patch-x86-build-specify-stack-alignment-for-clang --- diff --git a/configure.ac b/configure.ac index 11111111111..11111111111 100644 --- a/configure.ac +++ b/configure.ac -@@ -960,13 +960,13 @@ This is an error since --enable-archs=$wine_arch was requested.])]) - WINE_TRY_PE_CFLAGS([-Wlogical-op]) +@@ -963,6 +963,7 @@ This is an error since --enable-archs=$wine_arch was requested.])]) WINE_TRY_PE_CFLAGS([-Wabsolute-value]) WINE_TRY_PE_CFLAGS([-Wenum-enum-conversion],[:],WINE_TRY_PE_CFLAGS([-Wenum-conversion])) + WINE_TRY_PE_CFLAGS([-ffunction-sections]) + WINE_TRY_PE_CFLAGS([-fomit-frame-pointer]) - dnl GCC can't handle large files when -Wmisleading-indentation is enabled (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89549) + dnl clang had broken -fms-hotpatch support before version 18 (https://github.com/llvm/llvm-project/pull/77245) + WINE_TRY_PE_CFLAGS([-fms-hotpatch -DMIN_CLANG_VERSION=18], +@@ -973,8 +974,8 @@ This is an error since --enable-archs=$wine_arch was requested.])]) WINE_TRY_PE_CFLAGS([-flarge-source-files -Wmisleading-indentation],[AS_VAR_APPEND(${wine_arch}_EXTRACFLAGS,[" -Wno-misleading-indentation"])]) case $wine_arch in - i386) WINE_TRY_PE_CFLAGS([-fno-omit-frame-pointer]) - WINE_TRY_PE_CFLAGS([-mpreferred-stack-boundary=2]) -+ i386) WINE_TRY_PE_CFLAGS([-mpreferred-stack-boundary=2]) ++ i386) WINE_TRY_PE_CFLAGS([-mstack-alignment=4]) ++ WINE_TRY_PE_CFLAGS([-mpreferred-stack-boundary=2]) WINE_TRY_PE_CFLAGS([-Wl,--disable-stdcall-fixup], [AS_VAR_APPEND([${wine_arch}_LDFLAGS],[" -Wl,--disable-stdcall-fixup"])]) ;; - x86_64) WINE_TRY_PE_CFLAGS([-Wformat-overflow]) -@@ -1953,7 +1953,6 @@ char*f(const char *h,char n) {return strchr(h,n);}]])],[ac_cv_c_logicalop_noisy= + x86_64) WINE_TRY_PE_CFLAGS([-Wformat-overflow]) +@@ -1968,7 +1969,6 @@ then case $HOST_ARCH in dnl gcc-4.6+ omits frame pointers by default, breaking some copy protections @@ -32,7 +41,7 @@ index 11111111111..11111111111 100644 x86_64) case $host_os in dnl Mingw uses Windows 64-bit types, not Unix ones -@@ -1972,6 +1971,7 @@ int a(int b, ...) { __builtin_ms_va_list list; __builtin_ms_va_start(list,b); }] +@@ -1987,6 +1987,7 @@ int a(int b, ...) { __builtin_ms_va_list list; __builtin_ms_va_start(list,b); }] esac ;; arm) WINE_TRY_CFLAGS([-Wincompatible-function-pointer-types],[EXTRACFLAGS="$EXTRACFLAGS -Wno-error=incompatible-function-pointer-types"]) ;; diff --git a/0004-build-fix-undebug-optimize/4000-musl-precision.patch b/0004-build-fix-undebug-optimize/4000-musl-precision.patch deleted file mode 100644 index d58d72c..0000000 --- a/0004-build-fix-undebug-optimize/4000-musl-precision.patch +++ /dev/null @@ -1,28 +0,0 @@ -see: https://git.musl-libc.org/cgit/musl/tree/configure?h=v1.2.4&id=f5f55d6589940fd2c2188d76686efe3a530e64e0#n352 -diff --git a/libs/musl/Makefile.in b/libs/musl/Makefile.in -index 11111111111..11111111111 100644 ---- a/libs/musl/Makefile.in -+++ b/libs/musl/Makefile.in -@@ -1,6 +1,6 @@ - EXTLIB = libmusl.a - EXTRAINCL = -I$(srcdir)/src/internal -I$(srcdir)/arch/generic --EXTRADEFS = -D_ACRTIMP= -D_NO_CRT_MATH_INLINE -+EXTRADEFS = -D_ACRTIMP= -D_NO_CRT_MATH_INLINE $(MUSL_EXTRA_FLAGS) - - SOURCES = \ - src/math/__cos.c \ -diff --git a/configure.ac b/configure.ac -index 11111111111..11111111111 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -891,6 +891,10 @@ do - [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], [AS_VAR_SET([wine_cv_crosscc],[yes])], [AS_VAR_SET([wine_cv_crosscc],[no])])]) - AS_VAR_IF([wine_cv_crosscc], [no], [AS_VAR_SET([target],[])]) - AS_VAR_POPDEF([wine_cv_crosscc]) -+ case $wine_arch in -+ i386) AC_SUBST(MUSL_EXTRA_FLAGS,"-frounding-math -fexcess-precision=standard -ffloat-store") ;; -+ x86_64) AC_SUBST(MUSL_EXTRA_FLAGS,"-frounding-math -fexcess-precision=standard") ;; -+ esac - fi - - if test -z "$target" diff --git a/0004-build-fix-undebug-optimize/5000-clang-fixup-lto.patch b/0004-build-fix-undebug-optimize/5000-clang-fixup-lto.patch new file mode 100644 index 0000000..b99e6a5 --- /dev/null +++ b/0004-build-fix-undebug-optimize/5000-clang-fixup-lto.patch @@ -0,0 +1,34 @@ +From e7a411e0739b101f737a31e3908691efa49c8874 Mon Sep 17 00:00:00 2001 +From: William Horvath +Date: Thu, 14 Nov 2024 02:29:41 -0800 +Subject: [PATCH] clang: fixup lto + +--- + loader/preloader.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/loader/preloader.c b/loader/preloader.c +index 6dbd1cbd743..161f4348964 100644 +--- a/loader/preloader.c ++++ b/loader/preloader.c +@@ -94,7 +94,9 @@ + #include "wine/asm.h" + #include "main.h" + ++#if !defined(__LLD_LTO__) + #pragma GCC visibility push(hidden) ++#endif + + /* ELF definitions */ + #define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref) +@@ -2817,6 +2819,8 @@ void* wld_start( void **stack ) + return (void *)ld_so_map.l_entry; + } + ++#if !defined(__LLD_LTO__) + #pragma GCC visibility pop ++#endif + + #endif /* __linux__ */ +-- +2.47.0 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 new file mode 100644 index 0000000..bd1475a --- /dev/null +++ b/0004-build-fix-undebug-optimize/6000-msvcrt-Allow-SSE-if-_MSVCR_VER-0.patch @@ -0,0 +1,25 @@ +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/0007-proton-esync-fsync/0103-Revert-ntdll-Handle-user-APCs-explicitly-in-NtRemove.patch b/0007-proton-esync-fsync/0103-Revert-ntdll-Handle-user-APCs-explicitly-in-NtRemove.patch index 943fb24..5cbb3fa 100644 --- a/0007-proton-esync-fsync/0103-Revert-ntdll-Handle-user-APCs-explicitly-in-NtRemove.patch +++ b/0007-proton-esync-fsync/0103-Revert-ntdll-Handle-user-APCs-explicitly-in-NtRemove.patch @@ -175,32 +175,32 @@ index ac22f9853e5..0ad102283d1 100644 @REPLY apc_param_t ckey; /* completion key */ apc_param_t cvalue; /* completion value */ -diff --git a/server/request.h b/server/request.h -index 68fa71e39fb..8222fc73dc4 100644 ---- a/server/request.h -+++ b/server/request.h -@@ -2237,8 +2237,7 @@ C_ASSERT( FIELD_OFFSET(struct add_completion_request, information) == 32 ); - C_ASSERT( FIELD_OFFSET(struct add_completion_request, status) == 40 ); - C_ASSERT( sizeof(struct add_completion_request) == 48 ); - C_ASSERT( FIELD_OFFSET(struct remove_completion_request, handle) == 12 ); --C_ASSERT( FIELD_OFFSET(struct remove_completion_request, alertable) == 16 ); --C_ASSERT( sizeof(struct remove_completion_request) == 24 ); -+C_ASSERT( sizeof(struct remove_completion_request) == 16 ); - C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, ckey) == 8 ); - C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, cvalue) == 16 ); - C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, information) == 24 ); -diff --git a/server/trace.c b/server/trace.c -index 7142c37218a..a59cf6c5b5f 100644 ---- a/server/trace.c -+++ b/server/trace.c -@@ -4519,7 +4519,6 @@ static void dump_add_completion_request( const struct add_completion_request *re - static void dump_remove_completion_request( const struct remove_completion_request *req ) - { - fprintf( stderr, " handle=%04x", req->handle ); -- fprintf( stderr, ", alertable=%d", req->alertable ); - } - - static void dump_remove_completion_reply( const struct remove_completion_reply *req ) +#diff --git a/server/request.h b/server/request.h +#index 68fa71e39fb..8222fc73dc4 100644 +#--- a/server/request.h +#+++ b/server/request.h +#@@ -2237,8 +2237,7 @@ C_ASSERT( FIELD_OFFSET(struct add_completion_request, information) == 32 ); +# C_ASSERT( FIELD_OFFSET(struct add_completion_request, status) == 40 ); +# C_ASSERT( sizeof(struct add_completion_request) == 48 ); +# C_ASSERT( FIELD_OFFSET(struct remove_completion_request, handle) == 12 ); +#-C_ASSERT( FIELD_OFFSET(struct remove_completion_request, alertable) == 16 ); +#-C_ASSERT( sizeof(struct remove_completion_request) == 24 ); +#+C_ASSERT( sizeof(struct remove_completion_request) == 16 ); +# C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, ckey) == 8 ); +# C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, cvalue) == 16 ); +# C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, information) == 24 ); +#diff --git a/server/trace.c b/server/trace.c +#index 7142c37218a..a59cf6c5b5f 100644 +#--- a/server/trace.c +#+++ b/server/trace.c +#@@ -4519,7 +4519,6 @@ static void dump_add_completion_request( const struct add_completion_request *re +# static void dump_remove_completion_request( const struct remove_completion_request *req ) +# { +# fprintf( stderr, " handle=%04x", req->handle ); +#- fprintf( stderr, ", alertable=%d", req->alertable ); +# } +# +# static void dump_remove_completion_reply( const struct remove_completion_reply *req ) -- 2.47.0 diff --git a/0007-proton-esync-fsync/0104-Revert-ntdll-Assign-completion-to-thread-when-wait-f.patch b/0007-proton-esync-fsync/0104-Revert-ntdll-Assign-completion-to-thread-when-wait-f.patch index b6d58e3..101ff99 100644 --- a/0007-proton-esync-fsync/0104-Revert-ntdll-Assign-completion-to-thread-when-wait-f.patch +++ b/0007-proton-esync-fsync/0104-Revert-ntdll-Assign-completion-to-thread-when-wait-f.patch @@ -356,86 +356,86 @@ index 0ad102283d1..693a20e3437 100644 /* get completion queue depth */ @REQ(query_completion) obj_handle_t handle; /* port handle */ -diff --git a/server/request.h b/server/request.h -index 8222fc73dc4..b2679ceae9a 100644 ---- a/server/request.h -+++ b/server/request.h -@@ -381,7 +381,6 @@ DECL_HANDLER(create_completion); - DECL_HANDLER(open_completion); - DECL_HANDLER(add_completion); - DECL_HANDLER(remove_completion); --DECL_HANDLER(get_thread_completion); - DECL_HANDLER(query_completion); - DECL_HANDLER(set_completion_info); - DECL_HANDLER(add_fd_completion); -@@ -677,7 +676,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = - (req_handler)req_open_completion, - (req_handler)req_add_completion, - (req_handler)req_remove_completion, -- (req_handler)req_get_thread_completion, - (req_handler)req_query_completion, - (req_handler)req_set_completion_info, - (req_handler)req_add_fd_completion, -@@ -2244,12 +2242,6 @@ C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, information) == 24 ); - C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, status) == 32 ); - C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, wait_handle) == 36 ); - C_ASSERT( sizeof(struct remove_completion_reply) == 40 ); --C_ASSERT( sizeof(struct get_thread_completion_request) == 16 ); --C_ASSERT( FIELD_OFFSET(struct get_thread_completion_reply, ckey) == 8 ); --C_ASSERT( FIELD_OFFSET(struct get_thread_completion_reply, cvalue) == 16 ); --C_ASSERT( FIELD_OFFSET(struct get_thread_completion_reply, information) == 24 ); --C_ASSERT( FIELD_OFFSET(struct get_thread_completion_reply, status) == 32 ); --C_ASSERT( sizeof(struct get_thread_completion_reply) == 40 ); - C_ASSERT( FIELD_OFFSET(struct query_completion_request, handle) == 12 ); - C_ASSERT( sizeof(struct query_completion_request) == 16 ); - C_ASSERT( FIELD_OFFSET(struct query_completion_reply, depth) == 8 ); -diff --git a/server/trace.c b/server/trace.c -index a59cf6c5b5f..66ff3000c65 100644 ---- a/server/trace.c -+++ b/server/trace.c -@@ -4530,18 +4530,6 @@ static void dump_remove_completion_reply( const struct remove_completion_reply * - fprintf( stderr, ", wait_handle=%04x", req->wait_handle ); - } - --static void dump_get_thread_completion_request( const struct get_thread_completion_request *req ) --{ --} -- --static void dump_get_thread_completion_reply( const struct get_thread_completion_reply *req ) --{ -- dump_uint64( " ckey=", &req->ckey ); -- dump_uint64( ", cvalue=", &req->cvalue ); -- dump_uint64( ", information=", &req->information ); -- fprintf( stderr, ", status=%08x", req->status ); --} -- - static void dump_query_completion_request( const struct query_completion_request *req ) - { - fprintf( stderr, " handle=%04x", req->handle ); -@@ -5047,7 +5035,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { - (dump_func)dump_open_completion_request, - (dump_func)dump_add_completion_request, - (dump_func)dump_remove_completion_request, -- (dump_func)dump_get_thread_completion_request, - (dump_func)dump_query_completion_request, - (dump_func)dump_set_completion_info_request, - (dump_func)dump_add_fd_completion_request, -@@ -5340,7 +5327,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { - (dump_func)dump_open_completion_reply, - NULL, - (dump_func)dump_remove_completion_reply, -- (dump_func)dump_get_thread_completion_reply, - (dump_func)dump_query_completion_reply, - NULL, - NULL, -@@ -5633,7 +5619,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = { - "open_completion", - "add_completion", - "remove_completion", -- "get_thread_completion", - "query_completion", - "set_completion_info", - "add_fd_completion", +#diff --git a/server/request.h b/server/request.h +#index 8222fc73dc4..b2679ceae9a 100644 +#--- a/server/request.h +#+++ b/server/request.h +#@@ -381,7 +381,6 @@ DECL_HANDLER(create_completion); +# DECL_HANDLER(open_completion); +# DECL_HANDLER(add_completion); +# DECL_HANDLER(remove_completion); +#-DECL_HANDLER(get_thread_completion); +# DECL_HANDLER(query_completion); +# DECL_HANDLER(set_completion_info); +# DECL_HANDLER(add_fd_completion); +#@@ -677,7 +676,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = +# (req_handler)req_open_completion, +# (req_handler)req_add_completion, +# (req_handler)req_remove_completion, +#- (req_handler)req_get_thread_completion, +# (req_handler)req_query_completion, +# (req_handler)req_set_completion_info, +# (req_handler)req_add_fd_completion, +#@@ -2244,12 +2242,6 @@ C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, information) == 24 ); +# C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, status) == 32 ); +# C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, wait_handle) == 36 ); +# C_ASSERT( sizeof(struct remove_completion_reply) == 40 ); +#-C_ASSERT( sizeof(struct get_thread_completion_request) == 16 ); +#-C_ASSERT( FIELD_OFFSET(struct get_thread_completion_reply, ckey) == 8 ); +#-C_ASSERT( FIELD_OFFSET(struct get_thread_completion_reply, cvalue) == 16 ); +#-C_ASSERT( FIELD_OFFSET(struct get_thread_completion_reply, information) == 24 ); +#-C_ASSERT( FIELD_OFFSET(struct get_thread_completion_reply, status) == 32 ); +#-C_ASSERT( sizeof(struct get_thread_completion_reply) == 40 ); +# C_ASSERT( FIELD_OFFSET(struct query_completion_request, handle) == 12 ); +# C_ASSERT( sizeof(struct query_completion_request) == 16 ); +# C_ASSERT( FIELD_OFFSET(struct query_completion_reply, depth) == 8 ); +#diff --git a/server/trace.c b/server/trace.c +#index a59cf6c5b5f..66ff3000c65 100644 +#--- a/server/trace.c +#+++ b/server/trace.c +#@@ -4530,18 +4530,6 @@ static void dump_remove_completion_reply( const struct remove_completion_reply * +# fprintf( stderr, ", wait_handle=%04x", req->wait_handle ); +# } +# +#-static void dump_get_thread_completion_request( const struct get_thread_completion_request *req ) +#-{ +#-} +#- +#-static void dump_get_thread_completion_reply( const struct get_thread_completion_reply *req ) +#-{ +#- dump_uint64( " ckey=", &req->ckey ); +#- dump_uint64( ", cvalue=", &req->cvalue ); +#- dump_uint64( ", information=", &req->information ); +#- fprintf( stderr, ", status=%08x", req->status ); +#-} +#- +# static void dump_query_completion_request( const struct query_completion_request *req ) +# { +# fprintf( stderr, " handle=%04x", req->handle ); +#@@ -5047,7 +5035,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { +# (dump_func)dump_open_completion_request, +# (dump_func)dump_add_completion_request, +# (dump_func)dump_remove_completion_request, +#- (dump_func)dump_get_thread_completion_request, +# (dump_func)dump_query_completion_request, +# (dump_func)dump_set_completion_info_request, +# (dump_func)dump_add_fd_completion_request, +#@@ -5340,7 +5327,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { +# (dump_func)dump_open_completion_reply, +# NULL, +# (dump_func)dump_remove_completion_reply, +#- (dump_func)dump_get_thread_completion_reply, +# (dump_func)dump_query_completion_reply, +# NULL, +# NULL, +#@@ -5633,7 +5619,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = { +# "open_completion", +# "add_completion", +# "remove_completion", +#- "get_thread_completion", +# "query_completion", +# "set_completion_info", +# "add_fd_completion", -- 2.47.0 diff --git a/0007-proton-esync-fsync/0105-Revert-ntdll-Introduce-a-separate-per-thread-object-.patch b/0007-proton-esync-fsync/0105-Revert-ntdll-Introduce-a-separate-per-thread-object-.patch index bbac9c8..02252f7 100644 --- a/0007-proton-esync-fsync/0105-Revert-ntdll-Introduce-a-separate-per-thread-object-.patch +++ b/0007-proton-esync-fsync/0105-Revert-ntdll-Introduce-a-separate-per-thread-object-.patch @@ -306,18 +306,18 @@ index 693a20e3437..a4f25e805f8 100644 @END -diff --git a/server/request.h b/server/request.h -index b2679ceae9a..9e1bdf403ea 100644 ---- a/server/request.h -+++ b/server/request.h -@@ -2240,7 +2240,6 @@ C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, ckey) == 8 ); - C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, cvalue) == 16 ); - C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, information) == 24 ); - C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, status) == 32 ); --C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, wait_handle) == 36 ); - C_ASSERT( sizeof(struct remove_completion_reply) == 40 ); - C_ASSERT( FIELD_OFFSET(struct query_completion_request, handle) == 12 ); - C_ASSERT( sizeof(struct query_completion_request) == 16 ); +#diff --git a/server/request.h b/server/request.h +#index b2679ceae9a..9e1bdf403ea 100644 +#--- a/server/request.h +#+++ b/server/request.h +#@@ -2240,7 +2240,6 @@ C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, ckey) == 8 ); +# C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, cvalue) == 16 ); +# C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, information) == 24 ); +# C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, status) == 32 ); +#-C_ASSERT( FIELD_OFFSET(struct remove_completion_reply, wait_handle) == 36 ); +# C_ASSERT( sizeof(struct remove_completion_reply) == 40 ); +# C_ASSERT( FIELD_OFFSET(struct query_completion_request, handle) == 12 ); +# C_ASSERT( sizeof(struct query_completion_request) == 16 ); diff --git a/server/thread.c b/server/thread.c index f3880eebedb..6542e1584ab 100644 --- a/server/thread.c @@ -358,18 +358,18 @@ index 3448f332b0b..766ed78a72f 100644 struct timeout_user *exit_poll; /* poll if the thread/process has exited already */ }; -diff --git a/server/trace.c b/server/trace.c -index 66ff3000c65..a108043ea8d 100644 ---- a/server/trace.c -+++ b/server/trace.c -@@ -4527,7 +4527,6 @@ static void dump_remove_completion_reply( const struct remove_completion_reply * - dump_uint64( ", cvalue=", &req->cvalue ); - dump_uint64( ", information=", &req->information ); - fprintf( stderr, ", status=%08x", req->status ); -- fprintf( stderr, ", wait_handle=%04x", req->wait_handle ); - } - - static void dump_query_completion_request( const struct query_completion_request *req ) +#diff --git a/server/trace.c b/server/trace.c +#index 66ff3000c65..a108043ea8d 100644 +#--- a/server/trace.c +#+++ b/server/trace.c +#@@ -4527,7 +4527,6 @@ static void dump_remove_completion_reply( const struct remove_completion_reply * +# dump_uint64( ", cvalue=", &req->cvalue ); +# dump_uint64( ", information=", &req->information ); +# fprintf( stderr, ", status=%08x", req->status ); +#- fprintf( stderr, ", wait_handle=%04x", req->wait_handle ); +# } +# +# static void dump_query_completion_request( const struct query_completion_request *req ) -- 2.47.0 diff --git a/0007-proton-esync-fsync/0119-server-Create-eventfd-file-descriptors-for-process-o.patch b/0007-proton-esync-fsync/0119-server-Create-eventfd-file-descriptors-for-process-o.patch index 7de322d..b580bc5 100644 --- a/0007-proton-esync-fsync/0119-server-Create-eventfd-file-descriptors-for-process-o.patch +++ b/0007-proton-esync-fsync/0119-server-Create-eventfd-file-descriptors-for-process-o.patch @@ -1,10 +1,8 @@ -From f8408057d3999cc4f481f8cad37642e4458c3834 Mon Sep 17 00:00:00 2001 +From ce164f9c292bc93ad50055bdb0a786e8a8770afa Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 6 Jul 2020 15:11:12 -0500 -Subject: [PATCH 0440/2346] server: Create eventfd file descriptors for process - objects. +Subject: [PATCH] server: Create eventfd file descriptors for process objects. -Wine-Staging: eventfd_synchronization --- server/esync.c | 18 ++++++++++++++++++ server/esync.h | 1 + @@ -51,7 +49,7 @@ index 00f9e638d83..8522d8a69ae 100644 void esync_init(void); +int esync_create_fd( int initval, int flags ); diff --git a/server/process.c b/server/process.c -index 777bf7c2fe2..f5b919cba00 100644 +index 3c5a58b7b03..30555d516c8 100644 --- a/server/process.c +++ b/server/process.c @@ -63,6 +63,7 @@ @@ -79,17 +77,17 @@ index 777bf7c2fe2..f5b919cba00 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -686,6 +688,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla - process->rawinput_mouse = NULL; +@@ -689,6 +691,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla process->rawinput_kbd = NULL; memset( &process->image_info, 0, sizeof(process->image_info) ); -+ process->esync_fd = -1; list_init( &process->rawinput_entry ); ++ process->esync_fd = -1; list_init( &process->kernel_object ); list_init( &process->thread_list ); -@@ -742,6 +745,9 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla - if (!token_assign_label( process->token, &high_label_sid )) - goto error; + list_init( &process->locks ); +@@ -739,6 +742,9 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla + if (!process->handles || !process->token) goto error; + process->session_id = token_get_session_id( process->token ); + if (do_esync()) + process->esync_fd = esync_create_fd( 0, 0 ); @@ -97,7 +95,7 @@ index 777bf7c2fe2..f5b919cba00 100644 set_fd_events( process->msg_fd, POLLIN ); /* start listening to events */ return process; -@@ -789,6 +795,7 @@ static void process_destroy( struct object *obj ) +@@ -787,6 +793,7 @@ static void process_destroy( struct object *obj ) free( process->rawinput_devices ); free( process->dir_cache ); free( process->image ); @@ -105,7 +103,7 @@ index 777bf7c2fe2..f5b919cba00 100644 } /* dump a process on stdout for debugging purposes */ -@@ -806,6 +813,13 @@ static int process_signaled( struct object *obj, struct wait_queue_entry *entry +@@ -804,6 +811,13 @@ static int process_signaled( struct object *obj, struct wait_queue_entry *entry return !process->running_threads; } @@ -120,17 +118,17 @@ index 777bf7c2fe2..f5b919cba00 100644 { access = default_map_access( obj, access ); diff --git a/server/process.h b/server/process.h -index 97e0d455ece..a0a071d8f88 100644 +index 96814ab7cf8..ec74ba0490a 100644 --- a/server/process.h +++ b/server/process.h -@@ -85,6 +85,7 @@ struct process - const struct rawinput_device *rawinput_kbd; /* rawinput keyboard device, if any */ +@@ -86,6 +86,7 @@ struct process + struct list rawinput_entry; /* entry in the rawinput process list */ struct list kernel_object; /* list of kernel object pointers */ - pe_image_info_t image_info; /* main exe image info */ + struct pe_image_info image_info; /* main exe image info */ + int esync_fd; /* esync file descriptor (signaled on exit) */ }; /* process functions */ -- -2.47.0 +2.45.2 diff --git a/0007-proton-esync-fsync/0170-server-Create-futex-sections-for-process-objects.patch b/0007-proton-esync-fsync/0170-server-Create-futex-sections-for-process-objects.patch index 1a3c2e3..d075d39 100644 --- a/0007-proton-esync-fsync/0170-server-Create-futex-sections-for-process-objects.patch +++ b/0007-proton-esync-fsync/0170-server-Create-futex-sections-for-process-objects.patch @@ -123,13 +123,13 @@ index 1db0d52cb34..38303e04193 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ @@ -692,6 +694,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla - process->rawinput_kbd = NULL; memset( &process->image_info, 0, sizeof(process->image_info) ); + list_init( &process->rawinput_entry ); process->esync_fd = -1; + process->fsync_idx = 0; - list_init( &process->rawinput_entry ); list_init( &process->kernel_object ); list_init( &process->thread_list ); + list_init( &process->locks ); @@ -748,6 +751,9 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla if (!token_assign_label( process->token, &high_label_sid )) goto error; diff --git a/0007-proton-esync-fsync/0253-ntdll-fsync-Introduce-explicit-server-wait-helper-an.patch b/0007-proton-esync-fsync/0253-ntdll-fsync-Introduce-explicit-server-wait-helper-an.patch index fc89248..30670f6 100644 --- a/0007-proton-esync-fsync/0253-ntdll-fsync-Introduce-explicit-server-wait-helper-an.patch +++ b/0007-proton-esync-fsync/0253-ntdll-fsync-Introduce-explicit-server-wait-helper-an.patch @@ -20,13 +20,13 @@ index fd3faf61997..b2db0247b76 100644 +NTSTATUS wait_internal_server( HANDLE handle, BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ -+ select_op_t select_op; ++ union select_op select_op; + UINT flags = SELECT_INTERRUPTIBLE; + + if (alertable) flags |= SELECT_ALERTABLE; + select_op.wait.op = SELECT_WAIT; + select_op.wait.handles[0] = wine_server_obj_handle( handle ); -+ return server_wait( &select_op, offsetof( select_op_t, wait.handles[1] ), flags, timeout ); ++ return server_wait( &select_op, offsetof( union select_op, wait.handles[1] ), flags, timeout ); +} /****************************************************************** @@ -58,8 +58,8 @@ index 82fc9d2bc02..9dc8ea627e0 100644 extern unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT flags, const LARGE_INTEGER *timeout ); +extern NTSTATUS wait_internal_server( HANDLE handle, BOOLEAN alertable, const LARGE_INTEGER *timeout ); - extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, - apc_result_t *result ); + extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call, + union apc_result *result ); extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, @@ -455,7 +456,7 @@ static inline async_data_t server_async( HANDLE handle, struct async_fileio *use 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 f5ded3d..4f62b14 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 @@ -1,137 +1,244 @@ -From 478b891109bfee55921d9af0ff75706f277096b5 Mon Sep 17 00:00:00 2001 +From 045d4846d673b0739eddc9ef1a53eb81b778ca27 Mon Sep 17 00:00:00 2001 From: William Horvath -Date: Mon, 11 Nov 2024 18:27:50 -0800 -Subject: [PATCH v2] fsync: Use monitorx+mwaitx and spin before relying on +Date: Fri, 22 Nov 2024 16:24:27 -0800 +Subject: [PATCH] fsync: Use monitorx+mwaitx and spin before relying on futex_waitv in wait-all. -Taking inspiration from a patch by Torge Matthies. +monitor/mwait inspired by a patch by Torge Matthies, spin setup with ideas from 'nsync'. -v2: Fix mutex reacquire to use atomic operations, general reorganization. +v3: more reorganization, add semaphore retry. --- - dlls/ntdll/unix/fsync.c | 94 ++++++++++++++++++++++++++++++++++++++--- - dlls/ntdll/unix/fsync.h | 62 +++++++++++++++++++++++++++ - 2 files changed, 151 insertions(+), 5 deletions(-) + dlls/ntdll/unix/fsync.c | 203 ++++++++++++++++++++++++++++++++++++---- + 1 file changed, 185 insertions(+), 18 deletions(-) diff --git a/dlls/ntdll/unix/fsync.c b/dlls/ntdll/unix/fsync.c -index 169ceab10ad..eb74b658b0c 100644 +index 169ceab10ad..40b10b0d8d2 100644 --- a/dlls/ntdll/unix/fsync.c +++ b/dlls/ntdll/unix/fsync.c -@@ -773,6 +773,72 @@ static NTSTATUS do_single_wait( int *addr, int val, const struct timespec64 *end +@@ -773,6 +773,166 @@ static NTSTATUS do_single_wait( int *addr, int val, const struct timespec64 *end return STATUS_PENDING; } -+#define MUTEX_MON_TIMEOUT 1000 -+#define MUTEX_BASE_SPIN 2 -+#define AUTO_MON_TIMEOUT 1000 -+#define AUTO_BASE_SPIN 3 -+#define MANUAL_MON_TIMEOUT 2000 -+#define MANUAL_BASE_SPIN 4 -+ -+/* Fast path attempt to detect a value change using monitorx/mwaitx and spinning. ++#if defined(__x86_64__) || defined(__i386__) ++static inline int mwaitx_supported( void ) ++{ ++ static int supported; ++ if (!supported) ++ { ++ unsigned int eax, ecx; ++ __asm__ __volatile__ ( ++ "cpuid" ++ : "=a" (eax), "=c" (ecx) ++ : "a" (0x80000001U) ++ : "ebx", "edx" ++ ); ++ if (ecx & (1U << 29)) ++ supported = 1; ++ else ++ supported = -1; ++ } ++ return supported > 0; ++} ++#else ++#define mwaitx_supported() 0 ++#endif ++ ++#define CHECK_VALUE_CHANGED( addr, expected, observed ) \ ++ do \ ++ { \ ++ int __val = __atomic_load_n( (addr), __ATOMIC_SEQ_CST ); \ ++ if (__val != (expected)) \ ++ { \ ++ if (observed) \ ++ *(observed) = __val; \ ++ return STATUS_SUCCESS; \ ++ } \ ++ } while (0) ++ ++/* Time to wait in mwaitx, tuned based on a synchronization benchmark ++ * that probably captures 0 real-world scenarios. */ ++#define MUTEX_MON_TIMEOUT 1000 ++#define AUTO_MON_TIMEOUT 1000 ++#define MANUAL_MON_TIMEOUT 2000 ++#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 */ ++ ++/* Fast path attempt to detect a value change using monitorx/mwaitx instructions + spinning + * Returns STATUS_SUCCESS if the value changed, STATUS_UNSUCCESSFUL otherwise. + * + * Parameters: + * addr - Memory address to monitor + * expected_val - Value we're waiting to change + * observed_val - If non-NULL, receives the last observed value -+ * mon_timeout - Max cycles to wait in mwaitx -+ * base_spin - # of spin iterations (mwaitx being unavailable will add 2 to base_spin) ++ * mon_timeout - Max cycles to wait in mwaitx before falling back to spin + */ -+static inline NTSTATUS try_wait_value( volatile int *addr, int expected_val, int *observed_val, -+ const unsigned int mon_timeout, const unsigned int base_spin ) ++static inline NTSTATUS try_wait_value( volatile int *addr, int expected_val, ++ int *observed_val, const unsigned int mon_timeout ) +{ -+ static const unsigned int MIN_SPIN_ITERS = 4; -+ static const unsigned int SPIN_SHIFT = 4; -+ unsigned int spin_i, spin_o; -+ const unsigned int max_spin = mwaitx_supported() ? base_spin : base_spin + 2; -+ int val; -+ NTSTATUS status = STATUS_UNSUCCESSFUL; -+ -+ /* Fast path - check current value before waiting */ -+ val = __atomic_load_n( addr, __ATOMIC_SEQ_CST ); -+ if (val != expected_val) { -+ status = STATUS_SUCCESS; -+ goto done; -+ } ++ unsigned int attempts = 0; ++ ++ CHECK_VALUE_CHANGED( addr, expected_val, observed_val ); + -+ /* Try hardware wait if available */ + if (mwaitx_supported()) + { -+ val = monitor_wait( addr, expected_val, mon_timeout ); -+ if (val != expected_val) { -+ status = STATUS_SUCCESS; -+ goto done; -+ } ++ /* acts as acquire barrier */ ++ __asm__ __volatile__( ++ ".byte 0x0f,0x01,0xfa" /* monitorx */ ++ ::"a"(addr), ++ "c"(0U), "d"(0U) : "memory"); ++ ++ CHECK_VALUE_CHANGED( addr, expected_val, observed_val ); ++ ++ /* acts as full barrier */ ++ __asm__ __volatile__( ++ ".byte 0x0f,0x01,0xfb" /* mwaitx */ ++ ::"a"(0xF0U), ++ "b"(mon_timeout), "c"(0x2U) : "memory"); ++ ++ CHECK_VALUE_CHANGED( addr, expected_val, observed_val ); + } + -+ /* Try spinning with exponential backoff */ -+ do { -+ val = __atomic_load_n( addr, __ATOMIC_SEQ_CST ); -+ if (val != expected_val) { -+ status = STATUS_SUCCESS; -+ goto done; -+ } ++ /* exponential backoff transitioning to pure yields */ ++ while (attempts < SPIN_MAX_YIELDS) ++ { ++ CHECK_VALUE_CHANGED( addr, expected_val, observed_val ); + -+ /* backoff iterations: min(MIN_SPIN_ITERS, 2^(spin-SHIFT)) */ -+ spin_i = (spin_o <= SPIN_SHIFT) ? MIN_SPIN_ITERS -+ : (1U << (spin_o - SPIN_SHIFT)); -+ do { ++ if (attempts < SPIN_MAX_RETRIES) ++ { ++ volatile int i; ++ for (i = 0; i != 1 << attempts; i++) ++ { ++ YieldProcessor(); ++ } ++ } ++ else ++ { + YieldProcessor(); -+ } while (--spin_i); -+ } while (++spin_o < max_spin); ++ } ++ attempts++; ++ } + -+done: + if (observed_val) -+ *observed_val = val; -+ return status; ++ *observed_val = __atomic_load_n( addr, __ATOMIC_SEQ_CST ); ++ return STATUS_UNSUCCESSFUL; ++} ++ ++static inline BOOL try_reacquire_mutex( struct mutex *mutex, int current_tid, ++ int *observed_tid ) ++{ ++ int tid = *observed_tid; ++ ++ if (tid == current_tid) ++ { ++ mutex->count++; ++ return TRUE; ++ } ++ if (!tid && !__sync_val_compare_and_swap( &mutex->tid, 0, current_tid )) ++ { ++ mutex->count = 1; ++ return TRUE; ++ } ++ if (tid == ~0 && ++ (tid = __sync_val_compare_and_swap( &mutex->tid, ~0, current_tid )) == ~0) ++ { ++ mutex->count = 1; ++ return TRUE; ++ } ++ if (try_wait_value( &mutex->tid, tid, &tid, MUTEX_MON_TIMEOUT ) == STATUS_SUCCESS) ++ { ++ *observed_tid = tid; ++ return TRUE; ++ } ++ return FALSE; /* fall back to futex */ ++} ++ ++static inline BOOL try_acquire_semaphore( struct semaphore *semaphore ) ++{ ++ int count, new_count; ++ ++ new_count = __atomic_load_n( &semaphore->count, __ATOMIC_SEQ_CST ); ++ while ((count = new_count) > 0) ++ { ++ if ((new_count = __sync_val_compare_and_swap( &semaphore->count, ++ count, count - 1 )) == count) ++ { ++ return TRUE; ++ } ++ ++ if (!new_count && ++ try_wait_value( &semaphore->count, 0, &new_count, SEM_MON_TIMEOUT ) == STATUS_SUCCESS) ++ { ++ continue; ++ } ++ ++ break; ++ } ++ return FALSE; +} + static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { -@@ -908,27 +974,31 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, +@@ -890,17 +1050,13 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, + case FSYNC_SEMAPHORE: { - struct mutex *mutex = obj->shm; - int tid; -- -+ unsigned int try = 0; -+reacquire_mutex: - if (mutex->tid == current_tid) - { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -+ TRACE("Woken up by handle %p [%d] try_wait %u.\n", handles[i], i, try); - mutex->count++; - return i; - } + struct semaphore *semaphore = obj->shm; +- int current, new; - if (!(tid = __sync_val_compare_and_swap( &mutex->tid, 0, current_tid ))) +- new = __atomic_load_n( &semaphore->count, __ATOMIC_SEQ_CST ); +- while ((current = new)) ++ if (try_acquire_semaphore( semaphore )) { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -+ TRACE("Woken up by handle %p [%d] try_wait %u.\n", handles[i], i, try); - mutex->count = 1; +- if ((new = __sync_val_compare_and_swap( &semaphore->count, current, current - 1 )) == current) +- { +- TRACE("Woken up by handle %p [%d].\n", handles[i], i); +- return i; +- } ++ TRACE("Woken up by handle %p [%d].\n", handles[i], i); ++ return i; + } ++ + futex_vector_set( &futexes[i], &semaphore->count, 0 ); + break; + } +@@ -916,17 +1072,11 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, return i; } - else if (tid == ~0 && (tid = __sync_val_compare_and_swap( &mutex->tid, ~0, current_tid )) == ~0) + +- if (!(tid = __sync_val_compare_and_swap( &mutex->tid, 0, current_tid ))) ++ tid = __atomic_load_n( &mutex->tid, __ATOMIC_SEQ_CST ); ++ if (try_reacquire_mutex( mutex, current_tid, &tid )) { + TRACE("Woken up by handle %p [%d].\n", handles[i], i); +- mutex->count = 1; +- return i; +- } +- else if (tid == ~0 && (tid = __sync_val_compare_and_swap( &mutex->tid, ~0, current_tid )) == ~0) +- { - TRACE("Woken up by abandoned mutex %p [%d].\n", handles[i], i); -+ TRACE("Woken up by abandoned mutex %p [%d] try_wait %u.\n", handles[i], i, try); - mutex->count = 1; - return STATUS_ABANDONED_WAIT_0 + i; +- mutex->count = 1; +- return STATUS_ABANDONED_WAIT_0 + i; ++ return (tid == ~0) ? STATUS_ABANDONED_WAIT_0 + i : i; } -+ if (!try++ && try_wait_value( &mutex->tid, tid, &tid, MUTEX_MON_TIMEOUT, MUTEX_BASE_SPIN ) == STATUS_SUCCESS) -+ goto reacquire_mutex; -+ futex_vector_set( &futexes[i], &mutex->tid, tid ); - break; - } -@@ -942,6 +1012,13 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, +@@ -936,12 +1086,20 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, + case FSYNC_AUTO_SERVER: + { + struct event *event = obj->shm; ++ int signaled; + + if (__sync_val_compare_and_swap( &event->signaled, 1, 0 )) + { TRACE("Woken up by handle %p [%d].\n", handles[i], i); return i; } -+ int signaled; -+ if (try_wait_value( &event->signaled, 0, &signaled, AUTO_MON_TIMEOUT, AUTO_BASE_SPIN ) == STATUS_SUCCESS && -+ signaled && __sync_val_compare_and_swap( &event->signaled, 1, 0 )) ++ ++ if (try_wait_value( &event->signaled, 0, &signaled, AUTO_MON_TIMEOUT ) == STATUS_SUCCESS && ++ __sync_val_compare_and_swap( &event->signaled, 1, 0 )) + { + TRACE("Woken up by handle %p [%d].\n", handles[i], i); + return i; @@ -139,12 +246,13 @@ index 169ceab10ad..eb74b658b0c 100644 futex_vector_set( &futexes[i], &event->signaled, 0 ); break; } -@@ -950,8 +1027,15 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, +@@ -950,8 +1108,17 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, case FSYNC_QUEUE: { struct event *event = obj->shm; -+ int signaled = __atomic_load_n( &event->signaled, __ATOMIC_SEQ_CST ); ++ int signaled; + ++ signaled = __atomic_load_n( &event->signaled, __ATOMIC_SEQ_CST ); + if (signaled) + { + TRACE("Woken up by handle %p [%d].\n", handles[i], i); @@ -152,80 +260,11 @@ index 169ceab10ad..eb74b658b0c 100644 + } - if (__atomic_load_n( &event->signaled, __ATOMIC_SEQ_CST )) -+ if (try_wait_value( &event->signaled, 0, &signaled, MANUAL_MON_TIMEOUT, MANUAL_BASE_SPIN ) == STATUS_SUCCESS && signaled) ++ if (try_wait_value( &event->signaled, 0, &signaled, MANUAL_MON_TIMEOUT ) == STATUS_SUCCESS && ++ signaled) { TRACE("Woken up by handle %p [%d].\n", handles[i], i); return i; -diff --git a/dlls/ntdll/unix/fsync.h b/dlls/ntdll/unix/fsync.h -index 59013f83e7c..63691a0d207 100644 ---- a/dlls/ntdll/unix/fsync.h -+++ b/dlls/ntdll/unix/fsync.h -@@ -58,3 +58,65 @@ static inline int get_cached_tid(void) - static __thread int cached_tid; - return cached_tid ? cached_tid : (cached_tid = GetCurrentThreadId()); - } -+ -+#if defined(__x86_64__) || defined(__i386__) -+ -+static inline int mwaitx_supported( void ) -+{ -+ static int supported; -+ if (!supported) -+ { -+ unsigned int eax, ecx; -+ __asm__ __volatile__ ( -+ "cpuid" -+ : "=a" (eax), "=c" (ecx) -+ : "a" (0x80000001U) -+ : "ebx", "edx" -+ ); -+ if (ecx & (1U << 29)) -+ supported = 1; -+ else -+ supported = -1; -+ } -+ return supported > 0; -+} -+ -+/* Monitor memory location for changes using MONITORX/MWAITX -+ * addr: Memory address to monitor -+ * val: Expected value -+ * timeout: Max cycles to wait -+ * Returns: The current value at addr after monitoring -+ * -+ * Note: monitorx/mwaitx act as full memory barriers, so this -+ * function provides sequential consistency for the monitored address */ -+static inline int monitor_wait( volatile int *addr, int val, unsigned int timeout ) -+{ -+ /* monitorx setup - acts as acquire barrier */ -+ __asm__ __volatile__ ( -+ ".byte 0x0f,0x01,0xfa" /* monitorx */ -+ : -+ : "a" (addr), "c" (0U), "d" (0U) -+ : "memory" -+ ); -+ -+ /* The value check is done after monitorx since monitorx -+ * acts as an acquire barrier - if the value changed, we'll see it */ -+ if (*addr != val) -+ return *addr; -+ -+ /* mwaitx - acts as full barrier */ -+ __asm__ __volatile__ ( -+ ".byte 0x0f,0x01,0xfb" /* mwaitx */ -+ : -+ : "a" (0xF0U), "b" (timeout), "c" (0x2U) -+ : "memory" -+ ); -+ -+ /* mwaitx ensures we see latest value */ -+ return *addr; -+} -+ -+#else -+#define mwaitx_supported() 0 -+static inline int monitor_wait( volatile int *addr, int val, unsigned int timeout ) {} -+#endif -- 2.47.0 diff --git a/0009-windowing-system-integration/0001-misc-osu-related/0001-proton-focusin-focusout-workarounds.patch b/0009-windowing-system-integration/0001-misc-osu-related/0001-proton-focusin-focusout-workarounds.patch index 2d20648..f6655c5 100644 --- a/0009-windowing-system-integration/0001-misc-osu-related/0001-proton-focusin-focusout-workarounds.patch +++ b/0009-windowing-system-integration/0001-misc-osu-related/0001-proton-focusin-focusout-workarounds.patch @@ -1,9 +1,9 @@ diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c -index 3e9e0254c91..b273afa758a 100644 +index b08518220d9..4f155ecf29c 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c -@@ -775,6 +775,17 @@ static BOOL X11DRV_FocusIn( HWND hwnd, XEvent *xev ) - if (is_virtual_desktop() && hwnd == NtUserGetDesktopWindow()) retry_grab_clipping_window(); +@@ -894,6 +894,17 @@ static BOOL X11DRV_FocusIn( HWND hwnd, XEvent *xev ) + if (is_virtual_desktop() && hwnd == NtUserGetDesktopWindow()) reapply_cursor_clipping(); if (hwnd == NtUserGetDesktopWindow()) return FALSE; + /* Focus was just restored but it can be right after super was @@ -20,7 +20,7 @@ index 3e9e0254c91..b273afa758a 100644 x11drv_thread_data()->keymapnotify_hwnd = hwnd; /* when keyboard grab is released, re-apply the cursor clipping rect */ -@@ -805,8 +816,30 @@ static BOOL X11DRV_FocusIn( HWND hwnd, XEvent *xev ) +@@ -924,8 +935,30 @@ static BOOL X11DRV_FocusIn( HWND hwnd, XEvent *xev ) */ static void focus_out( Display *display , HWND hwnd ) { @@ -51,13 +51,17 @@ index 3e9e0254c91..b273afa758a 100644 x11drv_thread_data()->last_focus = hwnd; xim_set_focus( hwnd, FALSE ); -@@ -840,9 +873,21 @@ static void focus_out( Display *display , HWND hwnd ) - static BOOL X11DRV_FocusOut( HWND hwnd, XEvent *xev ) +@@ -962,6 +995,7 @@ static BOOL X11DRV_FocusOut( HWND hwnd, XEvent *xev ) { + HWND foreground = NtUserGetForegroundWindow(); XFocusChangeEvent *event = &xev->xfocus; + struct x11drv_win_data *data; - TRACE( "win %p xwin %lx detail=%s mode=%s\n", hwnd, event->window, focus_details[event->detail], focus_modes[event->mode] ); + if (event->detail == NotifyPointer) + { +@@ -976,6 +1010,17 @@ static BOOL X11DRV_FocusOut( HWND hwnd, XEvent *xev ) + } + if (!hwnd) return FALSE; + if ((data = get_win_data( hwnd ))) + { @@ -70,9 +74,9 @@ index 3e9e0254c91..b273afa758a 100644 + release_win_data( data ); + } + - if (event->detail == NotifyPointer) + if (window_has_pending_wm_state( hwnd, NormalState )) /* ignore FocusOut only if the window is being shown */ { - if (!hwnd && event->window == x11drv_thread_data()->clip_window) + WARN( "Ignoring window %p/%lx FocusOut serial %lu, detail %s, mode %s, foreground %p during WM_STATE change\n", diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index f975986a9d9..63f2861c101 100644 --- a/dlls/winex11.drv/window.c diff --git a/0009-windowing-system-integration/0001-misc-osu-related/0004-osu-undo-some-staging-alt-tab-changes.patch b/0009-windowing-system-integration/0001-misc-osu-related/0004-osu-undo-some-staging-alt-tab-changes.patch deleted file mode 100644 index 9b430bc..0000000 --- a/0009-windowing-system-integration/0001-misc-osu-related/0004-osu-undo-some-staging-alt-tab-changes.patch +++ /dev/null @@ -1,253 +0,0 @@ ---- b/dlls/winex11.drv/event.c -+++ a/dlls/winex11.drv/event.c -@@ -604,27 +604,16 @@ - */ - static void set_focus( Display *display, HWND hwnd, Time time ) - { -+ HWND focus; -- HWND focus, old_active; - Window win; - GUITHREADINFO threadinfo; - -- old_active = NtUserGetForegroundWindow(); -- - /* prevent recursion */ - x11drv_thread_data()->active_window = hwnd; - - TRACE( "setting foreground window to %p\n", hwnd ); - NtUserSetForegroundWindow( hwnd ); - -- /* Some applications expect that a being deactivated topmost window -- * receives the WM_WINDOWPOSCHANGING/WM_WINDOWPOSCHANGED messages, -- * and perform some specific actions. Chessmaster is one of such apps. -- * Window Manager keeps a topmost window on top in z-oder, so there is -- * no need to actually do anything, just send the messages. -- */ -- if (old_active && (NtUserGetWindowLongW( old_active, GWL_EXSTYLE ) & WS_EX_TOPMOST)) -- NtUserSetWindowPos( old_active, hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER ); -- - threadinfo.cbSize = sizeof(threadinfo); - NtUserGetGUIThreadInfo( 0, &threadinfo ); - focus = threadinfo.hwndFocus; ---- b/dlls/win32u/input.c -+++ a/dlls/win32u/input.c -@@ -1375,9 +1375,6 @@ - send_message( hwnd, WM_ACTIVATE, - MAKEWPARAM( mouse ? WA_CLICKACTIVE : WA_ACTIVE, is_iconic(hwnd) ), - (LPARAM)previous ); -- -- send_message( hwnd, WM_NCPOINTERUP, 0, 0); -- - if (NtUserGetAncestor( hwnd, GA_PARENT ) == get_desktop_window()) - NtUserPostMessage( get_desktop_window(), WM_PARENTNOTIFY, WM_NCACTIVATE, (LPARAM)hwnd ); - ---- b/dlls/win32u/input.c -+++ a/dlls/win32u/input.c -@@ -1633,10 +1633,6 @@ - (LPARAM)previous ); - if (NtUserGetAncestor( hwnd, GA_PARENT ) == get_desktop_window()) - NtUserPostMessage( get_desktop_window(), WM_PARENTNOTIFY, WM_NCACTIVATE, (LPARAM)hwnd ); -- -- if (hwnd == NtUserGetForegroundWindow() && !is_iconic( hwnd )) -- NtUserSetActiveWindow( hwnd ); -- - } - - user_driver->pSetActiveWindow( hwnd ); ---- b/dlls/win32u/driver.c -+++ a/dlls/win32u/driver.c -@@ -838,10 +838,6 @@ - hdc, rect.left - dx, rect.top - dy, SRCCOPY, 0, 0 ); - } - --static void nulldrv_SetActiveWindow( HWND hwnd ) --{ --} -- - static void nulldrv_SetCapture( HWND hwnd, UINT flags ) - { - } -@@ -1245,7 +1241,6 @@ - nulldrv_ProcessEvents, - nulldrv_ReleaseDC, - nulldrv_ScrollDC, -- nulldrv_SetActiveWindow, - nulldrv_SetCapture, - loaderdrv_SetDesktopWindow, - nulldrv_SetFocus, -@@ -1325,7 +1320,6 @@ - SET_USER_FUNC(ProcessEvents); - SET_USER_FUNC(ReleaseDC); - SET_USER_FUNC(ScrollDC); -- SET_USER_FUNC(SetActiveWindow); - SET_USER_FUNC(SetCapture); - SET_USER_FUNC(SetDesktopWindow); - SET_USER_FUNC(SetFocus); ---- b/dlls/win32u/input.c -+++ a/dlls/win32u/input.c -@@ -1887,8 +1887,6 @@ - NtUserPostMessage( get_desktop_window(), WM_PARENTNOTIFY, WM_NCACTIVATE, (LPARAM)hwnd ); - } - -- user_driver->pSetActiveWindow( hwnd ); -- - /* now change focus if necessary */ - if (focus) - { ---- b/dlls/winex11.drv/event.c -+++ a/dlls/winex11.drv/event.c -@@ -576,9 +576,6 @@ - Window win; - GUITHREADINFO threadinfo; - -- /* prevent recursion */ -- x11drv_thread_data()->active_window = hwnd; -- - TRACE( "setting foreground window to %p\n", hwnd ); - NtUserSetForegroundWindow( hwnd ); - -@@ -836,8 +833,6 @@ - - if (!focus_win) - { -- x11drv_thread_data()->active_window = 0; -- - /* Abey : 6-Oct-99. Check again if the focus out window is the - Foreground window, because in most cases the messages sent - above must have already changed the foreground window, in which ---- b/dlls/winex11.drv/init.c -+++ a/dlls/winex11.drv/init.c -@@ -421,7 +421,6 @@ - .pProcessEvents = X11DRV_ProcessEvents, - .pReleaseDC = X11DRV_ReleaseDC, - .pScrollDC = X11DRV_ScrollDC, -- .pSetActiveWindow = X11DRV_SetActiveWindow, - .pSetCapture = X11DRV_SetCapture, - .pSetDesktopWindow = X11DRV_SetDesktopWindow, - .pSetFocus = X11DRV_SetFocus, ---- b/dlls/winex11.drv/window.c -+++ a/dlls/winex11.drv/window.c -@@ -2431,54 +2431,6 @@ - } - - --/*********************************************************************** -- * SetActiveWindow (X11DRV.@) -- */ --void X11DRV_SetActiveWindow( HWND hwnd ) --{ -- struct x11drv_thread_data *thread_data = x11drv_init_thread_data(); -- struct x11drv_win_data *data; -- -- TRACE("%p\n", hwnd); -- -- if (thread_data->active_window == hwnd) -- { -- TRACE("ignoring activation for already active window %p\n", hwnd); -- return; -- } -- -- if (!(data = get_win_data( hwnd ))) return; -- -- if (data->mapped && data->managed && !data->iconic) -- { -- XEvent xev; -- struct x11drv_win_data *active = get_win_data( thread_data->active_window ); -- DWORD timestamp = NtUserGetThreadInfo()->message_time - EVENT_x11_time_to_win32_time( 0 ); -- -- TRACE("setting _NET_ACTIVE_WINDOW to %p/%lx, current active %p/%lx\n", -- data->hwnd, data->whole_window, active ? active->hwnd : NULL, active ? active->whole_window : 0 ); -- -- xev.xclient.type = ClientMessage; -- xev.xclient.window = data->whole_window; -- xev.xclient.message_type = x11drv_atom(_NET_ACTIVE_WINDOW); -- xev.xclient.serial = 0; -- xev.xclient.display = data->display; -- xev.xclient.send_event = True; -- xev.xclient.format = 32; -- -- xev.xclient.data.l[0] = 1; /* source: application */ -- xev.xclient.data.l[1] = timestamp; -- xev.xclient.data.l[2] = active ? active->whole_window : 0; -- xev.xclient.data.l[3] = 0; -- xev.xclient.data.l[4] = 0; -- XSendEvent( data->display, root_window, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev ); -- -- if (active) release_win_data( active ); -- } -- -- release_win_data( data ); --} -- - /*********************************************************************** - * SetCapture (X11DRV.@) - */ ---- b/dlls/winex11.drv/x11drv.h -+++ a/dlls/winex11.drv/x11drv.h -@@ -231,7 +231,6 @@ - const RECT *top_rect, DWORD flags ); - extern void X11DRV_ReleaseDC( HWND hwnd, HDC hdc ); - extern BOOL X11DRV_ScrollDC( HDC hdc, INT dx, INT dy, HRGN update ); --extern void X11DRV_SetActiveWindow( HWND hwnd ); - extern void X11DRV_SetCapture( HWND hwnd, UINT flags ); - extern void X11DRV_SetDesktopWindow( HWND hwnd ); - extern void X11DRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, -@@ -383,7 +382,6 @@ - Display *display; - XEvent *current_event; /* event currently being processed */ - HWND grab_hwnd; /* window that currently grabs the mouse */ -- HWND active_window; /* active window */ - HWND last_focus; /* last window that had focus */ - XIM xim; /* input method */ - HWND last_xic_hwnd; /* last xic window */ -@@ -490,7 +488,6 @@ - XATOM__ICC_PROFILE, - XATOM__KDE_NET_WM_STATE_SKIP_SWITCHER, - XATOM__MOTIF_WM_HINTS, -- XATOM__NET_ACTIVE_WINDOW, - XATOM__NET_STARTUP_INFO_BEGIN, - XATOM__NET_STARTUP_INFO, - XATOM__NET_SUPPORTED, ---- b/dlls/winex11.drv/x11drv_main.c -+++ a/dlls/winex11.drv/x11drv_main.c -@@ -154,7 +154,6 @@ - "_ICC_PROFILE", - "_KDE_NET_WM_STATE_SKIP_SWITCHER", - "_MOTIF_WM_HINTS", -- "_NET_ACTIVE_WINDOW", - "_NET_STARTUP_INFO_BEGIN", - "_NET_STARTUP_INFO", - "_NET_SUPPORTED", ---- b/include/wine/gdi_driver.h -+++ a/include/wine/gdi_driver.h -@@ -316,7 +316,6 @@ - BOOL (*pProcessEvents)(DWORD); - void (*pReleaseDC)(HWND,HDC); - BOOL (*pScrollDC)(HDC,INT,INT,HRGN); -- void (*pSetActiveWindow)(HWND); - void (*pSetCapture)(HWND,UINT); - void (*pSetDesktopWindow)(HWND); - void (*pSetFocus)(HWND); ---- b/dlls/winex11.drv/window.c -+++ a/dlls/winex11.drv/window.c -@@ -278,6 +278,9 @@ - if (style & WS_MINIMIZEBOX) ret |= MWM_DECOR_MINIMIZE; - if (style & WS_MAXIMIZEBOX) ret |= MWM_DECOR_MAXIMIZE; - } -+ if (ex_style & WS_EX_DLGMODALFRAME) ret |= MWM_DECOR_BORDER; -+ else if (style & WS_THICKFRAME) ret |= MWM_DECOR_BORDER; -+ else if ((style & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME) ret |= MWM_DECOR_BORDER; - return ret; - } - ---- b/dlls/winex11.drv/window.c -+++ a/dlls/winex11.drv/window.c -@@ -279,7 +279,7 @@ - if (style & WS_MAXIMIZEBOX) ret |= MWM_DECOR_MAXIMIZE; - } - if (ex_style & WS_EX_DLGMODALFRAME) ret |= MWM_DECOR_BORDER; -+ else if (style & WS_THICKFRAME) ret |= MWM_DECOR_BORDER | MWM_DECOR_RESIZEH; -- else if (style & WS_THICKFRAME) ret |= MWM_DECOR_BORDER; - else if ((style & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME) ret |= MWM_DECOR_BORDER; - return ret; - } diff --git a/0009-windowing-system-integration/0001-misc-osu-related/0005-ps0112-p0001-winex11.drv-Always-call-XSync-in-destroy_who.patch b/0009-windowing-system-integration/0001-misc-osu-related/0005-ps0112-p0001-winex11.drv-Always-call-XSync-in-destroy_who.patch deleted file mode 100644 index 4f01b83..0000000 --- a/0009-windowing-system-integration/0001-misc-osu-related/0005-ps0112-p0001-winex11.drv-Always-call-XSync-in-destroy_who.patch +++ /dev/null @@ -1,30 +0,0 @@ -From: Paul Gofman -Subject: [PATCH 1/1] winex11.drv: Always call XSync() in destroy_whole_window() if there is client window. -Message-Id: -Date: Fri, 17 Jun 2022 15:30:20 +0000 -In-Reply-To: -References: - -From: Paul Gofman - -Signed-off-by: Paul Gofman ---- - dlls/winex11.drv/window.c | 2 ++ - 1 file changed, 2 insertions(+) - -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 -@@ -1930,6 +1930,8 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des - } - return; - } -+ if (data->client_window && !already_destroyed) -+ XSync( data->display, False ); - } - else - { - - - diff --git a/0009-windowing-system-integration/0004-proton/0012-winex11.drv-Call-SetForegroundWindow-instead-of-SetA.patch b/0009-windowing-system-integration/0004-proton/0012-winex11.drv-Call-SetForegroundWindow-instead-of-SetA.patch deleted file mode 100644 index 137fc32..0000000 --- a/0009-windowing-system-integration/0004-proton/0012-winex11.drv-Call-SetForegroundWindow-instead-of-SetA.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 96eda2fd0e8a3b136a95e816f8630cead39599f8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Mon, 7 Mar 2022 16:53:09 +0100 -Subject: [PATCH 0268/1516] winex11.drv: Call SetForegroundWindow instead of - SetActiveWindow on restore. - -So that the window is both active and foreground before we send the -SC_RESTORE command. Project Cars 3 expects that as it tries to reacquire -DInput devices on SC_RESTORE. - -CW-Bug-Id: #19011 -CW-Bug-Id: #20227 ---- - dlls/winex11.drv/event.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c -index c6729e89d42..e72aac8c8bd 100644 ---- a/dlls/winex11.drv/event.c -+++ b/dlls/winex11.drv/event.c -@@ -1334,7 +1334,7 @@ static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL updat - TRACE( "restoring win %p/%lx\n", data->hwnd, data->whole_window ); - release_win_data( data ); - if ((old_style & (WS_MINIMIZE | WS_VISIBLE)) == (WS_MINIMIZE | WS_VISIBLE)) -- NtUserSetActiveWindow( hwnd ); -+ NtUserSetForegroundWindow( hwnd ); - send_message( hwnd, WM_SYSCOMMAND, SC_RESTORE, 0 ); - return; - } --- -2.44.0 - diff --git a/0013-server-optimization/0001-misc/0050-user32-Send-WM_NCPAINT-as-notify-message-in-send_ncp.patch b/0013-server-optimization/0001-misc/0050-user32-Send-WM_NCPAINT-as-notify-message-in-send_ncp.patch deleted file mode 100644 index d223a9e..0000000 --- a/0013-server-optimization/0001-misc/0050-user32-Send-WM_NCPAINT-as-notify-message-in-send_ncp.patch +++ /dev/null @@ -1,27 +0,0 @@ -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/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 index 62bc3df..e44a5e1 100644 --- 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 @@ -15,8 +15,8 @@ index 6745b257a7a..8e0d9816996 100644 +++ b/server/thread.c @@ -1923,9 +1923,7 @@ DECL_HANDLER(select) { - apc_call_t *data; - data_size_t size = sizeof(*data) + (ctx->regs[CTX_WOW].flags ? 2 : 1) * sizeof(context_t); + 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 ); diff --git a/0013-server-optimization/0001-misc/ps0248-ntdll-server-Write-system-handle-info-directly-to-.patch b/0013-server-optimization/0001-misc/ps0248-ntdll-server-Write-system-handle-info-directly-to-.patch index 3a006e0..24dfbd1 100644 --- a/0013-server-optimization/0001-misc/ps0248-ntdll-server-Write-system-handle-info-directly-to-.patch +++ b/0013-server-optimization/0001-misc/ps0248-ntdll-server-Write-system-handle-info-directly-to-.patch @@ -362,18 +362,6 @@ index 11111111111..11111111111 100644 @END -diff --git a/server/request.h b/server/request.h -index 11111111111..11111111111 100644 ---- a/server/request.h -+++ b/server/request.h -@@ -741,7 +741,6 @@ C_ASSERT( sizeof(select_op_t) == 264 ); - C_ASSERT( sizeof(short int) == 2 ); - C_ASSERT( sizeof(startup_info_t) == 96 ); - C_ASSERT( sizeof(struct filesystem_event) == 12 ); --C_ASSERT( sizeof(struct handle_info) == 20 ); - C_ASSERT( sizeof(struct luid) == 8 ); - C_ASSERT( sizeof(struct luid_attr) == 12 ); - C_ASSERT( sizeof(struct object_attributes) == 16 ); diff --git a/server/trace.c b/server/trace.c index 11111111111..11111111111 100644 --- a/server/trace.c @@ -403,14 +391,14 @@ diff --git a/tools/make_requests b/tools/make_requests index 11111111111..11111111111 100755 --- a/tools/make_requests +++ b/tools/make_requests -@@ -64,7 +64,6 @@ my %formats = - "startup_info_t" => [ 96, 4 ], - "user_apc_t" => [ 40, 8 ], +@@ -58,7 +58,6 @@ my %formats = + "union debug_event_data" => [ 160, 8 ], "struct filesystem_event" => [ 12, 4 ], + "struct generic_map" => [ 16, 4 ], - "struct handle_info" => [ 20, 4 ], - "struct luid_attr" => [ 12, 4 ], - "struct object_attributes" => [ 16, 4 ], - "struct object_type_info" => [ 44, 4 ], + "union hw_input" => [ 40, 8 ], + "union irp_params" => [ 32, 8 ], + "struct luid" => [ 8, 4 ], -- 0.0.0 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 deleted file mode 100644 index 333dd61..0000000 --- a/0013-server-optimization/0004-time-wait/0011-remove-yield-syscall.patch +++ /dev/null @@ -1,22 +0,0 @@ -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/0004-time-wait/0014-win32u-Factor-out-and-export-__wine_msg_wait.patch b/0013-server-optimization/0004-time-wait/0014-win32u-Factor-out-and-export-__wine_msg_wait.patch deleted file mode 100644 index beb0189..0000000 --- a/0013-server-optimization/0004-time-wait/0014-win32u-Factor-out-and-export-__wine_msg_wait.patch +++ /dev/null @@ -1,121 +0,0 @@ -From cf4be2d7e708730a6b26dedb3e02f6ecb5a77283 Mon Sep 17 00:00:00 2001 -From: Torge Matthies -Date: Fri, 27 May 2022 00:51:49 +0200 -Subject: [PATCH 1/2] win32u: Factor out and export __wine_msg_wait_objects for - high-resolution waits. - ---- - dlls/win32u/message.c | 34 +++++++++++++++++++++++----------- - include/winuser.h | 2 ++ - 2 files changed, 25 insertions(+), 11 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 -@@ -3047,10 +3047,10 @@ static inline LARGE_INTEGER *get_nt_timeout( LARGE_INTEGER *time, DWORD timeout - } - - /* wait for message or signaled handle */ --static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DWORD mask, DWORD flags ) -+static DWORD wait_message( DWORD count, const HANDLE *handles, -+ const LARGE_INTEGER *timeout, DWORD mask, DWORD flags ) - { - struct thunk_lock_params params = {.dispatch.callback = thunk_lock_callback}; -- LARGE_INTEGER time; - DWORD ret; - void *ret_ptr; - ULONG ret_len; -@@ -3066,7 +3066,7 @@ static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DW - else - { - ret = NtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL), -- !!(flags & MWMO_ALERTABLE), get_nt_timeout( &time, timeout )); -+ !!(flags & MWMO_ALERTABLE), timeout); - if (ret == count - 1) user_driver->pProcessEvents( mask ); - else if (HIWORD(ret)) /* is it an error code? */ - { -@@ -3075,7 +3075,7 @@ static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DW - } - } - -- if (ret == WAIT_TIMEOUT && !count && !timeout) NtYieldExecution(); -+ if (ret == WAIT_TIMEOUT && !count && !timeout->QuadPart) NtYieldExecution(); - if (ret == count - 1) get_user_thread_info()->last_driver_time = NtGetTickCount(); - - KeUserDispatchCallback( ¶ms.dispatch, sizeof(params), &ret_ptr, &ret_len ); -@@ -3105,7 +3105,7 @@ static BOOL check_queue_masks( UINT wake_mask, UINT changed_mask ) - * - * Wait for multiple objects including the server queue, with specific queue masks. - */ --static DWORD wait_objects( DWORD count, const HANDLE *handles, DWORD timeout, -+static DWORD wait_objects( DWORD count, const HANDLE *handles, const LARGE_INTEGER *timeout, - DWORD wake_mask, DWORD changed_mask, DWORD flags ) - { - assert( count ); /* we must have at least the server queue */ -@@ -3140,10 +3140,10 @@ static HANDLE normalize_std_handle( HANDLE handle ) - } - - /*********************************************************************** -- * NtUserMsgWaitForMultipleObjectsEx (win32u.@) -+ * __wine_msg_wait_objects (win32u.@) - */ --DWORD WINAPI NtUserMsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, -- DWORD timeout, DWORD mask, DWORD flags ) -+DWORD CDECL __wine_msg_wait_objects( DWORD count, const HANDLE *handles, -+ const LARGE_INTEGER *timeout, DWORD mask, DWORD flags ) - { - HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS]; - DWORD i; -@@ -3162,6 +3162,17 @@ DWORD WINAPI NtUserMsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handl - (flags & MWMO_INPUTAVAILABLE) ? mask : 0, mask, flags ); - } - -+/*********************************************************************** -+ * NtUserMsgWaitForMultipleObjectsEx (win32u.@) -+ */ -+DWORD WINAPI NtUserMsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, -+ DWORD timeout, DWORD mask, DWORD flags ) -+{ -+ LARGE_INTEGER time; -+ return __wine_msg_wait_objects( count, handles, get_nt_timeout( &time, timeout ), -+ mask, flags ); -+} -+ - /*********************************************************************** - * NtUserWaitForInputIdle (win32u.@) - */ -@@ -3287,7 +3298,7 @@ BOOL WINAPI NtUserGetMessage( MSG *msg, HWND hwnd, UINT first, UINT last ) - 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( 1, &server_queue, NULL, mask & (QS_SENDMESSAGE | QS_SMRESULT), mask, 0 ); - } - if (ret < 0) return -1; - -@@ -3416,7 +3427,7 @@ static void wait_message_reply( UINT flags ) - continue; - } - -- wait_message( 1, &server_queue, INFINITE, wake_mask, 0 ); -+ wait_message( 1, &server_queue, NULL, wake_mask, 0 ); - } - } - -diff --git a/include/winuser.h b/include/winuser.h -index 11111111111..11111111111 100644 ---- a/include/winuser.h -+++ b/include/winuser.h -@@ -4797,6 +4797,8 @@ static inline BOOL WINAPI SetRectEmpty(LPRECT rect) - WORD WINAPI SYSTEM_KillSystemTimer( WORD ); - - #ifdef __WINESRC__ -+WINUSERAPI DWORD CDECL __wine_msg_wait_objects( DWORD count, const HANDLE *handles, -+ const LARGE_INTEGER *timeout, DWORD mask, DWORD flags ); - - /* Uxtheme hook functions and struct */ - --- -0.0.0 - diff --git a/0013-server-optimization/0006-futex/0003-ntdll-tests-Add-tests-for-RtlWaitOnAddress-and-Keyed.patch b/0013-server-optimization/0006-futex/0003-ntdll-tests-Add-tests-for-RtlWaitOnAddress-and-Keyed.patch deleted file mode 100644 index 94ab063..0000000 --- a/0013-server-optimization/0006-futex/0003-ntdll-tests-Add-tests-for-RtlWaitOnAddress-and-Keyed.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 23de3e262ed22886f947058735300bb42afaf6bf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Thu, 24 Dec 2020 15:54:48 +0100 -Subject: [PATCH 3/5] ntdll/tests: Add tests for RtlWaitOnAddress and - KeyedEvent interop. - ---- - dlls/ntdll/tests/sync.c | 93 +++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 93 insertions(+) - -diff --git a/dlls/ntdll/tests/sync.c b/dlls/ntdll/tests/sync.c -index 11111111111..11111111111 100644 ---- a/dlls/ntdll/tests/sync.c -+++ b/dlls/ntdll/tests/sync.c -@@ -529,13 +529,63 @@ static void test_semaphore(void) - NtClose( semaphore ); - } - -+static DWORD WINAPI test_wait_on_address_thread( void *arg ) -+{ -+ LARGE_INTEGER timeout; -+ NTSTATUS status; -+ LONG64 *address = arg, compare = 0; -+ DWORD i; -+ -+ for (i = 0; i < 10; ++i) -+ { -+ Sleep(10); -+ pRtlWakeAddressSingle(address); -+ status = pRtlWaitOnAddress(address, &compare, 8, NULL); -+ ok(!status, "got 0x%08x\n", status); -+ -+ Sleep(10); -+ pRtlWakeAddressSingle((char *)address + 1); -+ status = pRtlWaitOnAddress(address, &compare, 8, NULL); -+ ok(!status, "got 0x%08x\n", status); -+ -+ Sleep(10); -+ pRtlWakeAddressSingle((char *)address + 2); -+ status = pRtlWaitOnAddress(address, &compare, 8, NULL); -+ ok(!status, "got 0x%08x\n", status); -+ -+ Sleep(10); -+ pRtlWakeAddressSingle((char *)address + 3); -+ status = pRtlWaitOnAddress(address, &compare, 8, NULL); -+ ok(!status, "got 0x%08x\n", status); -+ -+ Sleep(10); -+ pRtlWakeAddressSingle((char *)address + 4); -+ status = pRtlWaitOnAddress(address, &compare, 8, NULL); -+ ok(!status, "got 0x%08x\n", status); -+ } -+ -+ timeout.QuadPart = -100 * 10000; -+ for (i = 0; i < 10; ++i) -+ { -+ Sleep(10); -+ status = pNtReleaseKeyedEvent(0, address, FALSE, &timeout); -+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status); -+ status = pNtWaitForKeyedEvent(0, address, FALSE, &timeout); -+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status); -+ } -+ -+ return 0; -+} -+ - static void test_wait_on_address(void) - { -+ DWORD i; - SIZE_T size; - NTSTATUS status; - LARGE_INTEGER start, end, timeout; - DWORD elapsed; - LONG64 address, compare; -+ HANDLE thread; - - if (!pRtlWaitOnAddress) - { -@@ -601,6 +651,49 @@ static void test_wait_on_address(void) - ok(address == 0, "got %s\n", wine_dbgstr_longlong(address)); - pRtlWakeAddressAll(&address); - ok(address == 0, "got %s\n", wine_dbgstr_longlong(address)); -+ -+ address = 0; -+ compare = 0; -+ thread = CreateThread( NULL, 0, test_wait_on_address_thread, &address, 0, NULL ); -+ timeout.QuadPart = -100 * 10000; -+ -+ for (i = 0; i < 10; ++i) -+ { -+ status = pRtlWaitOnAddress(&address, &compare, 8, NULL); -+ ok(!status, "got 0x%08x\n", status); -+ Sleep(10); -+ pRtlWakeAddressSingle(&address); -+ -+ status = pRtlWaitOnAddress(&address, &compare, 8, &timeout); -+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status); -+ Sleep(10); -+ pRtlWakeAddressSingle(&address); -+ -+ status = pRtlWaitOnAddress(&address, &compare, 8, &timeout); -+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status); -+ Sleep(10); -+ pRtlWakeAddressSingle(&address); -+ -+ status = pRtlWaitOnAddress(&address, &compare, 8, &timeout); -+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status); -+ Sleep(10); -+ pRtlWakeAddressSingle(&address); -+ -+ status = pRtlWaitOnAddress(&address, &compare, 8, &timeout); -+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status); -+ Sleep(10); -+ pRtlWakeAddressSingle(&address); -+ } -+ -+ for (i = 0; i < 10; ++i) -+ { -+ status = pRtlWaitOnAddress(&address, &compare, 8, &timeout); -+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status); -+ Sleep(10); -+ pRtlWakeAddressSingle(&address); -+ } -+ -+ ok( WaitForSingleObject( thread, 30000 ) == 0, "wait failed\n" ); - } - - static HANDLE thread_ready, thread_done; --- -0.0.0 - diff --git a/0013-server-optimization/0006-futex/0004-ntdll-Track-active-keyed-events-on-the-client-side.patch b/0013-server-optimization/0006-futex/0004-ntdll-Track-active-keyed-events-on-the-client-side.patch deleted file mode 100644 index 76c1c8d..0000000 --- a/0013-server-optimization/0006-futex/0004-ntdll-Track-active-keyed-events-on-the-client-side.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 310668d72ed26864842ef1c5b00315e11816fa1a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Thu, 24 Dec 2020 16:11:56 +0100 -Subject: [PATCH 4/5] ntdll: Track active keyed events on the client side. - ---- - dlls/ntdll/unix/sync.c | 70 +++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 66 insertions(+), 4 deletions(-) - -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 -@@ -79,6 +79,58 @@ WINE_DEFAULT_DEBUG_CHANNEL(sync); - - HANDLE keyed_event = 0; - -+static pthread_mutex_t keyed_mutex = PTHREAD_MUTEX_INITIALIZER; -+ -+struct keyed_entry -+{ -+ client_ptr_t key; -+ LONG ref; -+ HANDLE handle; -+ BOOLEAN alertable; -+}; -+ -+static struct keyed_entry keyed_entries[256]; -+static size_t nb_keyed_entries; -+ -+static inline struct keyed_entry *keyed_entry_acquire( HANDLE handle, client_ptr_t key, BOOLEAN alertable ) -+{ -+ struct keyed_entry *entry; -+ DWORD i; -+ -+ mutex_lock( &keyed_mutex ); -+ for (i = 0; i < nb_keyed_entries; ++i) -+ { -+ if (!keyed_entries[i].ref) continue; -+ if (keyed_entries[i].key == key) break; -+ } -+ if (i == nb_keyed_entries) for (i = 0; i <= nb_keyed_entries; ++i) -+ { -+ if (!keyed_entries[i].ref) break; -+ } -+ assert(i < ARRAY_SIZE(keyed_entries)); -+ if (i == nb_keyed_entries) nb_keyed_entries++; -+ -+ entry = keyed_entries + i; -+ if (!entry->ref++) -+ { -+ entry->key = key; -+ entry->handle = handle; -+ entry->alertable = alertable; -+ } -+ -+ if (entry->handle != handle) WARN("inconsistent keyed event handle %p, previously %p\n", handle, entry->handle); -+ if (entry->alertable != alertable) WARN("inconsistent keyed event alertable %d, previously %d\n", alertable, entry->alertable); -+ mutex_unlock( &keyed_mutex ); -+ return entry; -+} -+ -+static inline void keyed_entry_release( struct keyed_entry *entry ) -+{ -+ mutex_lock( &keyed_mutex ); -+ if (!--entry->ref) while (nb_keyed_entries && !keyed_entries[nb_keyed_entries - 1].ref) nb_keyed_entries--; -+ mutex_unlock( &keyed_mutex ); -+} -+ - static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) - { - if (!timeout) return "(infinite)"; -@@ -3125,16 +3177,21 @@ NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJE - NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) - { -+ struct keyed_entry *entry; - select_op_t select_op; - UINT flags = SELECT_INTERRUPTIBLE; -+ NTSTATUS status; - -- if (!handle) handle = keyed_event; - if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; -+ entry = keyed_entry_acquire( handle, wine_server_client_ptr( key ), alertable ); -+ if (!handle) handle = keyed_event; - if (alertable) flags |= SELECT_ALERTABLE; - select_op.keyed_event.op = SELECT_KEYED_EVENT_WAIT; - select_op.keyed_event.handle = wine_server_obj_handle( handle ); - select_op.keyed_event.key = wine_server_client_ptr( key ); -- return server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout ); -+ status = server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout ); -+ keyed_entry_release( entry ); -+ return status; - } - - -@@ -3144,16 +3203,21 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, - NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) - { -+ struct keyed_entry *entry; - select_op_t select_op; - UINT flags = SELECT_INTERRUPTIBLE; -+ NTSTATUS status; - -- if (!handle) handle = keyed_event; - if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; -+ entry = keyed_entry_acquire( handle, wine_server_client_ptr( key ), alertable ); -+ if (!handle) handle = keyed_event; - if (alertable) flags |= SELECT_ALERTABLE; - select_op.keyed_event.op = SELECT_KEYED_EVENT_RELEASE; - select_op.keyed_event.handle = wine_server_obj_handle( handle ); - select_op.keyed_event.key = wine_server_client_ptr( key ); -- return server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout ); -+ status = server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout ); -+ keyed_entry_release( entry ); -+ return status; - } - - diff --git a/0013-server-optimization/0006-futex/0005-ntdll-Implement-client-side-keyed-events-on-top-of-f.patch b/0013-server-optimization/0006-futex/0005-ntdll-Implement-client-side-keyed-events-on-top-of-f.patch deleted file mode 100644 index da23b52..0000000 --- a/0013-server-optimization/0006-futex/0005-ntdll-Implement-client-side-keyed-events-on-top-of-f.patch +++ /dev/null @@ -1,226 +0,0 @@ -From 138338e0e03bb5781ef54e0fdf481dad1654581f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Thu, 24 Dec 2020 16:41:43 +0100 -Subject: [PATCH 5/5] ntdll: Implement client-side keyed events on top of - futexes. - -Because RtlWaitOnAddress needs a special treatment, and already has -a fast path, we only enable this keyed event fast path when keyed -event handle is 0. ---- - dlls/ntdll/unix/sync.c | 164 ++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 152 insertions(+), 12 deletions(-) - -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 -@@ -166,6 +166,9 @@ static inline ULONGLONG monotonic_counter(void) - - #include - -+#define FUTEX_WAIT_BITSET 9 -+#define FUTEX_WAKE_BITSET 10 -+ - static inline int futex_wait( const LONG *addr, int val, struct timespec *timeout ) - { - #if (defined(__i386__) || defined(__arm__)) && _TIME_BITS==64 -@@ -187,6 +190,26 @@ static inline int futex_wake_one( const LONG *addr ) - return syscall( __NR_futex, addr, FUTEX_WAKE_PRIVATE, 1, NULL, 0, 0 ); - } - -+static inline int futex_wait_abs( const int *addr, int val, struct timespec *timeout ) -+{ -+ return syscall( __NR_futex, addr, FUTEX_WAIT_BITSET | 128, val, timeout, 0, 0xffffffff ); -+} -+ -+static inline int futex_wait_bitset( const int *addr, int val, struct timespec *timeout, int mask ) -+{ -+ return syscall( __NR_futex, addr, FUTEX_WAIT_BITSET | 128, val, timeout, 0, mask ); -+} -+ -+static inline int futex_wake_bitset( const int *addr, int val, int mask ) -+{ -+ return syscall( __NR_futex, addr, FUTEX_WAKE_BITSET | 128, val, NULL, 0, mask ); -+} -+ -+static inline int use_futexes(void) -+{ -+ return 1; -+} -+ - #elif defined(__APPLE__) - - #define USE_FUTEX -@@ -2272,6 +2295,9 @@ NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJE - return ret; - } - -+static inline NTSTATUS fast_wait_for_keyed_event( struct keyed_entry *entry, const LARGE_INTEGER *timeout ); -+static inline NTSTATUS fast_release_keyed_event( struct keyed_entry *entry, const LARGE_INTEGER *timeout ); -+ - /****************************************************************************** - * NtWaitForKeyedEvent (NTDLL.@) - */ -@@ -2285,12 +2311,15 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, - - if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; - entry = keyed_entry_acquire( handle, wine_server_client_ptr( key ), alertable ); -- if (!handle) handle = keyed_event; -- if (alertable) flags |= SELECT_ALERTABLE; -- select_op.keyed_event.op = SELECT_KEYED_EVENT_WAIT; -- select_op.keyed_event.handle = wine_server_obj_handle( handle ); -- select_op.keyed_event.key = wine_server_client_ptr( key ); -- status = server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout ); -+ if ((status = fast_wait_for_keyed_event( entry, timeout )) == STATUS_NOT_IMPLEMENTED) -+ { -+ if (!handle) handle = keyed_event; -+ if (alertable) flags |= SELECT_ALERTABLE; -+ select_op.keyed_event.op = SELECT_KEYED_EVENT_WAIT; -+ select_op.keyed_event.handle = wine_server_obj_handle( handle ); -+ select_op.keyed_event.key = wine_server_client_ptr( key ); -+ status = server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout ); -+ } - keyed_entry_release( entry ); - return status; - } -@@ -2309,12 +2338,15 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, - - if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; - entry = keyed_entry_acquire( handle, wine_server_client_ptr( key ), alertable ); -- if (!handle) handle = keyed_event; -- if (alertable) flags |= SELECT_ALERTABLE; -- select_op.keyed_event.op = SELECT_KEYED_EVENT_RELEASE; -- select_op.keyed_event.handle = wine_server_obj_handle( handle ); -- select_op.keyed_event.key = wine_server_client_ptr( key ); -- status = server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout ); -+ if ((status = fast_release_keyed_event( entry, timeout )) == STATUS_NOT_IMPLEMENTED) -+ { -+ if (!handle) handle = keyed_event; -+ if (alertable) flags |= SELECT_ALERTABLE; -+ select_op.keyed_event.op = SELECT_KEYED_EVENT_RELEASE; -+ select_op.keyed_event.handle = wine_server_obj_handle( handle ); -+ select_op.keyed_event.key = wine_server_client_ptr( key ); -+ status = server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout ); -+ } - keyed_entry_release( entry ); - return status; - } -@@ -3165,3 +3197,117 @@ NTSTATUS WINAPI NtRollbackTransaction( HANDLE transaction, BOOLEAN wait ) - - return STATUS_ACCESS_VIOLATION; - } -+ -+#ifdef __linux__ -+ -+struct fast_keyed_entry -+{ -+ int wait_cs; /* 0: unlocked, 1: locked, 2: contested */ -+ int wake_cs; /* 0: unlocked, 1: locked, 2: contested */ -+ int signal; /* 0: not signaled, 1: signaled, 2: acked */ -+}; -+ -+static struct fast_keyed_entry fast_keyed_table[256]; -+ -+static int futex_cs_enter( int *futex, struct timespec *timespec ) -+{ -+ NTSTATUS status = STATUS_SUCCESS; -+ int ret; -+ if (InterlockedCompareExchange( futex, 1, 0 ) == 0) return STATUS_SUCCESS; -+ do -+ { -+ if (*futex != 2 && InterlockedCompareExchange( futex, 2, 1 ) == 0) continue; -+ if (!(ret = futex_wait_abs( futex, 2, timespec ))) continue; -+ else if (ret == -1 && errno == ETIMEDOUT) status = STATUS_TIMEOUT; -+ else if (ret == -1 && errno != EAGAIN) ERR("futex_wait_abs unexpectedly failed, errno: %d\n", errno); -+ } -+ while (!status && InterlockedCompareExchange( futex, 2, 0 ) != 0); -+ return status; -+} -+ -+static void futex_cs_leave( int *futex ) -+{ -+ if (InterlockedExchange( futex, 0 ) == 2) futex_wake_one( futex ); -+} -+ -+static struct timespec *nt_timeout_to_timespec( struct timespec *timespec, const LARGE_INTEGER *timeout ) -+{ -+ LARGE_INTEGER diff; -+ struct timespec now; -+ if (!timeout) return NULL; -+ -+ if (timeout->QuadPart > 0) -+ { -+ NtQuerySystemTime( &diff ); -+ diff.QuadPart -= timeout->QuadPart; -+ } -+ else diff = *timeout; -+ -+ clock_gettime(CLOCK_MONOTONIC, &now); -+ timespec->tv_sec = now.tv_sec + (now.tv_nsec / 100 - diff.QuadPart) / TICKSPERSEC; -+ timespec->tv_nsec = (now.tv_nsec / 100 - diff.QuadPart) % TICKSPERSEC * 100; -+ return timespec; -+} -+ -+static inline NTSTATUS fast_wait_for_keyed_event( struct keyed_entry *entry, const LARGE_INTEGER *timeout ) -+{ -+ struct fast_keyed_entry *fast = &fast_keyed_table[entry - keyed_entries]; -+ struct timespec time, *timespec = nt_timeout_to_timespec( &time, timeout ); -+ NTSTATUS status = STATUS_SUCCESS; -+ int ret; -+ -+ if (!use_futexes() || entry->handle || entry->alertable) return STATUS_NOT_IMPLEMENTED; -+ -+ if ((status = futex_cs_enter( &fast->wait_cs, timespec ))) return status; -+ /* wait for signal, and ack it */ -+ while (!status && InterlockedCompareExchange( &fast->signal, 2, 1 ) != 1) -+ { -+ if (!(ret = futex_wait_abs( &fast->signal, 0, timespec ))) continue; -+ else if (ret == -1 && errno == ETIMEDOUT) status = STATUS_TIMEOUT; -+ else if (ret == -1 && errno != EAGAIN) ERR("futex_wait_abs unexpectedly failed, errno: %d\n", errno); -+ } -+ /* if we acked, wake the signaler */ -+ if (!status) futex_wake_one( &fast->signal ); -+ futex_cs_leave( &fast->wait_cs ); -+ return status; -+} -+ -+static inline NTSTATUS fast_release_keyed_event( struct keyed_entry *entry, const LARGE_INTEGER *timeout ) -+{ -+ struct fast_keyed_entry *fast = &fast_keyed_table[entry - keyed_entries]; -+ struct timespec time, *timespec = nt_timeout_to_timespec( &time, timeout ); -+ NTSTATUS status = STATUS_SUCCESS; -+ int ret; -+ -+ if (!use_futexes() || entry->handle || entry->alertable) return STATUS_NOT_IMPLEMENTED; -+ -+ if ((status = futex_cs_enter( &fast->wake_cs, timespec ))) return status; -+ /* signal and wake waiter */ -+ InterlockedExchange( &fast->signal, 1 ); -+ futex_wake_one( &fast->signal ); -+ /* wait for ack, and reset */ -+ while (!status && InterlockedCompareExchange( &fast->signal, 0, 2 ) == 1) -+ { -+ if (!(ret = futex_wait_abs( &fast->signal, 1, timespec ))) continue; -+ else if (ret == -1 && errno == ETIMEDOUT) status = STATUS_TIMEOUT; -+ else if (ret == -1 && errno != EAGAIN) ERR("futex_wait_abs unexpectedly failed, errno: %d\n", errno); -+ } -+ /* if we timedout, reset and check ack */ -+ if (status == STATUS_TIMEOUT && InterlockedExchange( &fast->signal, 0 ) == 2) status = STATUS_SUCCESS; -+ futex_cs_leave( &fast->wake_cs ); -+ return status; -+} -+ -+#else -+ -+static inline NTSTATUS fast_wait_for_keyed_event( struct keyed_entry *entry, const LARGE_INTEGER *timeout ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static inline NTSTATUS fast_release_keyed_event( struct keyed_entry *entry, const LARGE_INTEGER *timeout ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+#endif diff --git a/9000-misc-additions/NtUserGetKeyboardState-Don-tTryThisAtHome.patch b/9000-misc-additions/NtUserGetKeyboardState-Don-tTryThisAtHome.patch deleted file mode 100644 index 470097e..0000000 --- a/9000-misc-additions/NtUserGetKeyboardState-Don-tTryThisAtHome.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 67ad4a36e1c38e8b432a4e286d676431c809f9aa Mon Sep 17 00:00:00 2001 -From: William Horvath -Date: Mon, 4 Nov 2024 03:33:59 -0800 -Subject: [PATCH] NtUserGetKeyboardState-Don'tTryThisAtHome - ---- - dlls/win32u/input.c | 39 +++++++++++++++++++++++++-------------- - dlls/win32u/message.c | 2 +- - 2 files changed, 26 insertions(+), 15 deletions(-) - -diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c -index 63c31eace27..842ce4b053c 100644 ---- a/dlls/win32u/input.c -+++ b/dlls/win32u/input.c -@@ -970,23 +970,34 @@ SHORT WINAPI NtUserGetKeyState( INT vkey ) - return retval; - } - --/********************************************************************** -- * NtUserGetKeyboardState (win32u.@) -- */ --BOOL WINAPI NtUserGetKeyboardState( BYTE *state ) --{ -- struct object_lock lock = OBJECT_LOCK_INIT; -- const input_shm_t *input_shm; -- NTSTATUS status; -- UINT i; -+#ifdef __AVX512F__ -+#include - -- TRACE("(%p)\n", state); -+static inline void mask_keystate_avx512( BYTE *state ) -+{ -+ const __m512i mask = _mm512_set1_epi8(0x81); - -- while ((status = get_shared_input( GetCurrentThreadId(), &lock, &input_shm )) == STATUS_PENDING) -- memcpy( state, (const void *)input_shm->keystate, 256 ); -- if (status) memset( state, 0, 256 ); -+ _mm512_storeu_si512((__m512i*)(state), _mm512_and_si512(_mm512_loadu_si512((__m512i*)(state)), mask)); -+ _mm512_storeu_si512((__m512i*)(state + 64), _mm512_and_si512(_mm512_loadu_si512((__m512i*)(state + 64)), mask)); -+ _mm512_storeu_si512((__m512i*)(state + 128), _mm512_and_si512(_mm512_loadu_si512((__m512i*)(state + 128)), mask)); -+ _mm512_storeu_si512((__m512i*)(state + 192), _mm512_and_si512(_mm512_loadu_si512((__m512i*)(state + 192)), mask)); -+} -+#endif - -- for (i = 0; i < 256; i++) state[i] &= 0x81; -+/********************************************************************** -+ * NtUserGetKeyboardState (win32u.@) -+ * -+ * HACKHACK: always use global async keystate and penny pinch every cycle -+ * -+ */ -+BOOL WINAPI NtUserGetKeyboardState( BYTE *state ) -+{ -+ get_async_keyboard_state( state ); -+#ifdef __AVX512F__ -+ mask_keystate_avx512( state ); -+#else -+ for (int i = 0; i < 256; i++) state[i] &= 0x81; -+#endif - return TRUE; - } - -diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c -index 625b853536e..0b74215c8bb 100644 ---- a/dlls/win32u/message.c -+++ b/dlls/win32u/message.c -@@ -4459,7 +4459,7 @@ BOOL WINAPI NtUserTranslateMessage( const MSG *msg, UINT flags ) - { - UINT message; - WCHAR wp[8]; -- BYTE state[256]; -+ BYTE state[256] __attribute__ ((aligned(64))); /* for optimal avx512 alignment */ - INT len; - - if (flags) FIXME( "unsupported flags %x\n", flags ); --- -2.47.0 - diff --git a/9000-misc-additions/add-wayland-default-driver.patch b/9000-misc-additions/add-wayland-default-driver.patch deleted file mode 100644 index 28f93aa..0000000 --- a/9000-misc-additions/add-wayland-default-driver.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c -index 945d809a55c..ad428d6bb94 100644 ---- a/programs/explorer/desktop.c -+++ b/programs/explorer/desktop.c -@@ -38,7 +38,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(explorer); - #define DESKTOP_CLASS_ATOM ((LPCWSTR)MAKEINTATOM(32769)) - #define DESKTOP_ALL_ACCESS 0x01ff - --static const WCHAR default_driver[] = {'m','a','c',',','x','1','1',0}; -+static const WCHAR default_driver[] = L"mac,x11,wayland"; - - static BOOL using_root = TRUE; - diff --git a/9000-misc-additions/cursor-clip-hack.patch b/9000-misc-additions/cursor-clip-hack.patch index b72ead5..25f1e33 100644 --- a/9000-misc-additions/cursor-clip-hack.patch +++ b/9000-misc-additions/cursor-clip-hack.patch @@ -47,7 +47,7 @@ index d94f0da56a0..12802e99af7 100644 */ BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) { -+ if (!cursor_clip_hack) return FALSE; ++ if (cursor_clip_hack) return TRUE; struct user_thread_info *thread_info = get_user_thread_info(); MONITORINFO monitor_info = {.cbSize = sizeof(MONITORINFO)}; RECT rect, virtual_rect; @@ -280,3 +280,50 @@ index 29147758979..9874f18a4b6 100644 -- 2.47.0 +From ab3b93764847712da1928be9ecda339d407ce26c Mon Sep 17 00:00:00 2001 +From: William Horvath +Date: Wed, 13 Nov 2024 03:05:16 -0800 +Subject: [PATCH] cursor-clip-hack additions + +--- + dlls/win32u/message.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c +index d398579916b..92951ce3c4a 100644 +--- a/dlls/win32u/message.c ++++ b/dlls/win32u/message.c +@@ -2116,8 +2116,8 @@ static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPAR + case WM_WINE_CLIPCURSOR: + /* non-hardware message, posted on display mode change to trigger fullscreen + clipping or to the desktop window to forcefully release the cursor grabs */ +- if (wparam & SET_CURSOR_FSCLIP) return clip_fullscreen_window( hwnd, FALSE ); +- return process_wine_clipcursor( hwnd, wparam, lparam ); ++ if (wparam & SET_CURSOR_FSCLIP) return cursor_clip_hack ? TRUE : clip_fullscreen_window( hwnd, FALSE ); ++ return cursor_clip_hack ? TRUE : process_wine_clipcursor( hwnd, wparam, lparam ); + case WM_WINE_SETCURSOR: + FIXME( "Unexpected non-hardware WM_WINE_SETCURSOR message\n" ); + return FALSE; +@@ -2661,7 +2661,9 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar + else if (msg->message >= WM_POINTERUPDATE && msg->message <= WM_POINTERLEAVE) + ret = process_pointer_message( msg, hw_id, msg_data ); + else if (msg->message == WM_WINE_CLIPCURSOR) +- process_wine_clipcursor( msg->hwnd, msg->wParam, msg->lParam ); ++ { ++ if (!cursor_clip_hack) process_wine_clipcursor( msg->hwnd, msg->wParam, msg->lParam ); ++ } + else if (msg->message == WM_WINE_SETCURSOR) + process_wine_setcursor( msg->hwnd, (HWND)msg->wParam, (HCURSOR)msg->lParam ); + else +@@ -3580,7 +3582,7 @@ NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARA + info.timeout = 0; + info.params = NULL; + +- if (input->type == INPUT_MOUSE && (input->mi.dwFlags & (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_RIGHTDOWN))) ++ if (!cursor_clip_hack && input->type == INPUT_MOUSE && (input->mi.dwFlags & (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_RIGHTDOWN))) + clip_fullscreen_window( hwnd, FALSE ); + + SERVER_START_REQ( send_hardware_message ) +-- +2.47.0 + 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 new file mode 100644 index 0000000..1de871f --- /dev/null +++ b/9500-testing/0001-WIP-rawmouse-no-raw-pthread-optimize-atomics-barely-.patch @@ -0,0 +1,607 @@ +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 new file mode 100644 index 0000000..e093d86 --- /dev/null +++ b/9500-testing/0002-WIP-rawmouse-use-SynchronizationEvent-for-motion.patch @@ -0,0 +1,63 @@ +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 38c654b..a145d78 100644 --- a/staging-commit +++ b/staging-commit @@ -1 +1 @@ -32abf9fc9756ad912b39acb93bcf60f448942a20 \ No newline at end of file +7ba8823e57e0a32c1373e5c304542c7ce578699c \ No newline at end of file diff --git a/wine-commit b/wine-commit index 83fb85e..5035c9f 100644 --- a/wine-commit +++ b/wine-commit @@ -1 +1 @@ -60ddc9613b0a48b20fd1180409bea849f02961ef \ No newline at end of file +51ccd95c49c2c61ad41960b25a01f834601d70c0 \ No newline at end of file