From ef0e88407ea60c9feed923431aee4bcc8ae71f95 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Tue, 12 Nov 2019 19:56:51 -0600 Subject: [PATCH] Rebase against 292b728908563952f56b0585d072f3d7a08e93b2. --- ...on-to-create-new-tokens-for-elevatio.patch | 10 +- ...-support-for-creating-processes-usin.patch | 265 +++++++++--------- ...r-the-working-directory-first-when-l.patch | 37 --- .../definition | 1 - ...rnel32-Implement-SetProcessDEPPolicy.patch | 38 ++- ...parse-unicode-property-storage-dicti.patch | 37 --- ...returning-a-name-in-IEnumSTATPROPSTG.patch | 135 --------- patches/ole32-STGPROP/definition | 2 - patches/patchinstall.sh | 25 +- ...-values-for-memory-accounting-on-NVI.patch | 35 +-- 10 files changed, 181 insertions(+), 404 deletions(-) delete mode 100644 patches/kernel32-NeedCurrentDirectoryForExePath/0003-kernel32-Consider-the-working-directory-first-when-l.patch delete mode 100644 patches/kernel32-NeedCurrentDirectoryForExePath/definition delete mode 100644 patches/ole32-STGPROP/0001-ole32-Correctly-parse-unicode-property-storage-dicti.patch delete mode 100644 patches/ole32-STGPROP/0003-ole32-Implement-returning-a-name-in-IEnumSTATPROPSTG.patch delete mode 100644 patches/ole32-STGPROP/definition diff --git a/patches/advapi32-Token_Integrity_Level/0006-ntdll-Add-function-to-create-new-tokens-for-elevatio.patch b/patches/advapi32-Token_Integrity_Level/0006-ntdll-Add-function-to-create-new-tokens-for-elevatio.patch index 45b79faf..4fa2200f 100644 --- a/patches/advapi32-Token_Integrity_Level/0006-ntdll-Add-function-to-create-new-tokens-for-elevatio.patch +++ b/patches/advapi32-Token_Integrity_Level/0006-ntdll-Add-function-to-create-new-tokens-for-elevatio.patch @@ -1,4 +1,4 @@ -From 220f1f666c3bab52dcb467acbbee4534acd29081 Mon Sep 17 00:00:00 2001 +From 8959c13f2be7e2a31f27c8483ee2202692f00710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Sat, 5 Aug 2017 01:45:29 +0200 Subject: [PATCH] ntdll: Add function to create new tokens for elevation @@ -28,11 +28,11 @@ index d626e0bf2..5057e2b07 100644 @ cdecl wine_get_version() NTDLL_wine_get_version @ cdecl wine_get_patches() NTDLL_wine_get_patches diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h -index 054ec10f0..fa231a462 100644 +index ac1469412..6c2345c6c 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h -@@ -88,6 +88,9 @@ extern void heap_set_debug_flags( HANDLE handle ) DECLSPEC_HIDDEN; - extern void init_user_process_params( SIZE_T data_size ) DECLSPEC_HIDDEN; +@@ -89,6 +89,9 @@ extern void init_user_process_params( SIZE_T data_size ) DECLSPEC_HIDDEN; + extern char **build_envp( const WCHAR *envW ) DECLSPEC_HIDDEN; extern NTSTATUS restart_process( RTL_USER_PROCESS_PARAMETERS *params, NTSTATUS status ) DECLSPEC_HIDDEN; +/* token */ @@ -42,7 +42,7 @@ index 054ec10f0..fa231a462 100644 extern timeout_t server_start_time DECLSPEC_HIDDEN; extern unsigned int server_cpus DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c -index 6cdbb3abd..41c6bc950 100644 +index 52d7ea429..e24691b8a 100644 --- a/dlls/ntdll/process.c +++ b/dlls/ntdll/process.c @@ -125,6 +125,24 @@ HANDLE CDECL __wine_make_process_system(void) diff --git a/patches/advapi32-Token_Integrity_Level/0010-server-Implement-support-for-creating-processes-usin.patch b/patches/advapi32-Token_Integrity_Level/0010-server-Implement-support-for-creating-processes-usin.patch index 8ed86c84..c07d426c 100644 --- a/patches/advapi32-Token_Integrity_Level/0010-server-Implement-support-for-creating-processes-usin.patch +++ b/patches/advapi32-Token_Integrity_Level/0010-server-Implement-support-for-creating-processes-usin.patch @@ -1,130 +1,145 @@ -From 9f35230848f29e79b65c8e340221d7eb81382a43 Mon Sep 17 00:00:00 2001 +From b052f3aa98d77d3ab68cdb2622b8e77478abeb6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Sun, 6 Aug 2017 02:08:05 +0200 Subject: [PATCH] server: Implement support for creating processes using a token. --- - dlls/kernel32/process.c | 27 +++++++++++++++------------ - server/process.c | 39 +++++++++++++++++++++++++++++++++++---- - server/process.h | 2 +- - server/protocol.def | 1 + - server/request.c | 2 +- - server/security.h | 2 ++ - server/token.c | 11 +++++++++++ - 7 files changed, 66 insertions(+), 18 deletions(-) + dlls/kernelbase/process.c | 24 +++++++++++++----------- + dlls/ntdll/process.c | 3 ++- + server/process.c | 39 +++++++++++++++++++++++++++++++++++---- + server/process.h | 2 +- + server/protocol.def | 1 + + server/request.c | 2 +- + server/security.h | 2 ++ + server/token.c | 11 +++++++++++ + 8 files changed, 66 insertions(+), 18 deletions(-) -diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c -index 802d99f2a12..03c0588d59a 100644 ---- a/dlls/kernel32/process.c -+++ b/dlls/kernel32/process.c -@@ -2341,7 +2341,7 @@ static BOOL replace_process( HANDLE handle, const RTL_USER_PROCESS_PARAMETERS *p - * Create a new process. If hFile is a valid handle we have an exe - * file, otherwise it is a Winelib app. +diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c +index 51b75470c..16396cb73 100644 +--- a/dlls/kernelbase/process.c ++++ b/dlls/kernelbase/process.c +@@ -235,7 +235,7 @@ static RTL_USER_PROCESS_PARAMETERS *create_process_params( const WCHAR *filename + /*********************************************************************** + * create_nt_process */ --static BOOL create_process( HANDLE hFile, LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa, -+static BOOL create_process( HANDLE token, HANDLE hFile, LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa, - BOOL inherit, DWORD flags, const RTL_USER_PROCESS_PARAMETERS *params, - LPPROCESS_INFORMATION info, LPCSTR unixdir, const pe_image_info_t *pe_info ) +-static NTSTATUS create_nt_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, ++static NTSTATUS create_nt_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, + BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params, + RTL_USER_PROCESS_INFORMATION *info ) { -@@ -2408,6 +2408,7 @@ static BOOL create_process( HANDLE hFile, LPSECURITY_ATTRIBUTES psa, LPSECURITY_ +@@ -250,7 +250,7 @@ static NTSTATUS create_nt_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES + status = RtlCreateUserProcess( &nameW, OBJ_CASE_INSENSITIVE, params, + psa ? psa->lpSecurityDescriptor : NULL, + tsa ? tsa->lpSecurityDescriptor : NULL, +- 0, inherit, 0, 0, info ); ++ 0, inherit, 0, token, info ); + RtlFreeUnicodeString( &nameW ); + } + return status; +@@ -260,7 +260,7 @@ static NTSTATUS create_nt_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES + /*********************************************************************** + * create_vdm_process + */ +-static NTSTATUS create_vdm_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, ++static NTSTATUS create_vdm_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, + BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params, + RTL_USER_PROCESS_INFORMATION *info ) + { +@@ -281,7 +281,7 @@ static NTSTATUS create_vdm_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTE + winevdm, params->ImagePathName.Buffer, params->CommandLine.Buffer ); + RtlInitUnicodeString( ¶ms->ImagePathName, winevdm ); + RtlInitUnicodeString( ¶ms->CommandLine, newcmdline ); +- status = create_nt_process( psa, tsa, inherit, flags, params, info ); ++ status = create_nt_process( token, psa, tsa, inherit, flags, params, info ); + HeapFree( GetProcessHeap(), 0, newcmdline ); + return status; + } +@@ -290,7 +290,7 @@ static NTSTATUS create_vdm_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTE + /*********************************************************************** + * create_cmd_process + */ +-static NTSTATUS create_cmd_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, ++static NTSTATUS create_cmd_process( HANDLE token, SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, + BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params, + RTL_USER_PROCESS_INFORMATION *info ) + { +@@ -309,7 +309,7 @@ static NTSTATUS create_cmd_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTE + swprintf( newcmdline, len, L"%s /s/c \"%s\"", comspec, params->CommandLine.Buffer ); + RtlInitUnicodeString( ¶ms->ImagePathName, comspec ); + RtlInitUnicodeString( ¶ms->CommandLine, newcmdline ); +- status = create_nt_process( psa, tsa, inherit, flags, params, info ); ++ status = create_nt_process( token, psa, tsa, inherit, flags, params, info ); + RtlFreeHeap( GetProcessHeap(), 0, newcmdline ); + return status; + } +@@ -422,7 +422,9 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR + + TRACE( "app %s cmdline %s\n", debugstr_w(app_name), debugstr_w(cmd_line) ); + +- if (token) FIXME( "Creating a process with a token is not yet implemented\n" ); ++ /* FIXME: Starting a process which requires admin rights should fail ++ * with ERROR_ELEVATION_REQUIRED when no token is passed. */ ++ + if (new_token) FIXME( "No support for returning created process token\n" ); + + if (app_name) +@@ -466,7 +468,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR + goto done; + } + +- status = create_nt_process( process_attr, thread_attr, inherit, flags, params, &rtl_info ); ++ status = create_nt_process( token, process_attr, thread_attr, inherit, flags, params, &rtl_info ); + switch (status) + { + case STATUS_SUCCESS: +@@ -475,7 +477,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR + case STATUS_INVALID_IMAGE_NE_FORMAT: + case STATUS_INVALID_IMAGE_PROTECT: + TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(app_name) ); +- status = create_vdm_process( process_attr, thread_attr, inherit, flags, params, &rtl_info ); ++ status = create_vdm_process( token, process_attr, thread_attr, inherit, flags, params, &rtl_info ); + break; + case STATUS_INVALID_IMAGE_NOT_MZ: + /* check for .com or .bat extension */ +@@ -483,12 +485,12 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR + if (!wcsicmp( p, L".com" ) || !wcsicmp( p, L".pif" )) + { + TRACE( "starting %s as DOS binary\n", debugstr_w(app_name) ); +- status = create_vdm_process( process_attr, thread_attr, inherit, flags, params, &rtl_info ); ++ status = create_vdm_process( token, process_attr, thread_attr, inherit, flags, params, &rtl_info ); + } + else if (!wcsicmp( p, L".bat" ) || !wcsicmp( p, L".cmd" )) + { + TRACE( "starting %s as batch binary\n", debugstr_w(app_name) ); +- status = create_cmd_process( process_attr, thread_attr, inherit, flags, params, &rtl_info ); ++ status = create_cmd_process( token, process_attr, thread_attr, inherit, flags, params, &rtl_info ); + } + break; + } +diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c +index e24691b8a..89403167b 100644 +--- a/dlls/ntdll/process.c ++++ b/dlls/ntdll/process.c +@@ -1667,7 +1667,7 @@ NTSTATUS WINAPI RtlCreateUserProcess( UNICODE_STRING *path, ULONG attributes, + RTL_USER_PROCESS_PARAMETERS *params, + SECURITY_DESCRIPTOR *process_descr, + SECURITY_DESCRIPTOR *thread_descr, +- HANDLE parent, BOOLEAN inherit, HANDLE debug, HANDLE exception, ++ HANDLE parent, BOOLEAN inherit, HANDLE debug, HANDLE token, + RTL_USER_PROCESS_INFORMATION *info ) + { + NTSTATUS status; +@@ -1734,6 +1734,7 @@ NTSTATUS WINAPI RtlCreateUserProcess( UNICODE_STRING *path, ULONG attributes, req->access = PROCESS_ALL_ACCESS; - req->cpu = pe_info->cpu; + req->cpu = pe_info.cpu; req->info_size = startup_info_size; + req->token = wine_server_obj_handle( token ); wine_server_add_data( req, objattr, attr_len ); wine_server_add_data( req, startup_info, startup_info_size ); - wine_server_add_data( req, params->Environment, (env_end - params->Environment) * sizeof(WCHAR) ); -@@ -2567,7 +2568,7 @@ static RTL_USER_PROCESS_PARAMETERS *get_vdm_params( const RTL_USER_PROCESS_PARAM - * - * Create a new VDM process for a 16-bit or DOS application. - */ --static BOOL create_vdm_process( LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa, -+static BOOL create_vdm_process( HANDLE token, LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa, - BOOL inherit, DWORD flags, const RTL_USER_PROCESS_PARAMETERS *params, - LPPROCESS_INFORMATION info, LPCSTR unixdir ) - { -@@ -2577,7 +2578,7 @@ static BOOL create_vdm_process( LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES - - if (!(new_params = get_vdm_params( params, &pe_info ))) return FALSE; - -- ret = create_process( 0, psa, tsa, inherit, flags, new_params, info, unixdir, &pe_info ); -+ ret = create_process( token, 0, psa, tsa, inherit, flags, new_params, info, unixdir, &pe_info ); - RtlDestroyProcessParameters( new_params ); - return ret; - } -@@ -2588,7 +2589,7 @@ static BOOL create_vdm_process( LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES - * - * Create a new cmd shell process for a .BAT file. - */ --static BOOL create_cmd_process( LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa, -+static BOOL create_cmd_process( HANDLE token, LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa, - BOOL inherit, DWORD flags, LPSTARTUPINFOW startup, - const RTL_USER_PROCESS_PARAMETERS *params, - LPPROCESS_INFORMATION info ) -@@ -2618,9 +2619,9 @@ static BOOL create_cmd_process( LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES - strcatW( newcmdline, params->CommandLine.Buffer ); - strcatW( newcmdline, quotW ); - if (params->CurrentDirectory.DosPath.Length) cur_dir = params->CurrentDirectory.DosPath.Buffer; -- ret = CreateProcessW( comspec, newcmdline, psa, tsa, inherit, -+ ret = CreateProcessInternalW( token, comspec, newcmdline, psa, tsa, inherit, - flags | CREATE_UNICODE_ENVIRONMENT, params->Environment, cur_dir, -- startup, info ); -+ startup, info, NULL ); - HeapFree( GetProcessHeap(), 0, newcmdline ); - return ret; - } -@@ -2734,7 +2735,9 @@ BOOL WINAPI CreateProcessInternalW( HANDLE token, LPCWSTR app_name, LPWSTR cmd_l - - TRACE("app %s cmdline %s\n", debugstr_w(app_name), debugstr_w(cmd_line) ); - -- if (token) FIXME("Creating a process with a token is not yet implemented\n"); -+ /* FIXME: Starting a process which requires admin rights should fail -+ * with ERROR_ELEVATION_REQUIRED when no token is passed. */ -+ - if (new_token) FIXME("No support for returning created process token\n"); - - if (!(tidy_cmdline = get_file_name( app_name, cmd_line, name, ARRAY_SIZE( name ), &hFile, &is_64bit ))) -@@ -2802,17 +2805,17 @@ BOOL WINAPI CreateProcessInternalW( HANDLE token, LPCWSTR app_name, LPWSTR cmd_l - debugstr_w(name), is_64bit_arch(pe_info.cpu) ? 64 : 32, - wine_dbgstr_longlong(pe_info.base), wine_dbgstr_longlong(pe_info.base + pe_info.map_size), - cpu_names[pe_info.cpu] ); -- retv = create_process( hFile, process_attr, thread_attr, -+ retv = create_process( token, hFile, process_attr, thread_attr, - inherit, flags, params, info, unixdir, &pe_info ); - break; - case BINARY_WIN16: - TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(name) ); -- retv = create_vdm_process( process_attr, thread_attr, inherit, flags, params, info, unixdir ); -+ retv = create_vdm_process( token, process_attr, thread_attr, inherit, flags, params, info, unixdir ); - break; - case BINARY_UNIX_LIB: - TRACE( "starting %s as %d-bit Winelib app\n", - debugstr_w(name), is_64bit_arch(pe_info.cpu) ? 64 : 32 ); -- retv = create_process( hFile, process_attr, thread_attr, -+ retv = create_process( token, hFile, process_attr, thread_attr, - inherit, flags, params, info, unixdir, &pe_info ); - break; - case BINARY_UNKNOWN: -@@ -2822,14 +2825,14 @@ BOOL WINAPI CreateProcessInternalW( HANDLE token, LPCWSTR app_name, LPWSTR cmd_l - if (!strcmpiW( p, comW ) || !strcmpiW( p, pifW )) - { - TRACE( "starting %s as DOS binary\n", debugstr_w(name) ); -- retv = create_vdm_process( process_attr, thread_attr, -+ retv = create_vdm_process( token, process_attr, thread_attr, - inherit, flags, params, info, unixdir ); - break; - } - if (!strcmpiW( p, batW ) || !strcmpiW( p, cmdW ) ) - { - TRACE( "starting %s as batch binary\n", debugstr_w(name) ); -- retv = create_cmd_process( process_attr, thread_attr, -+ retv = create_cmd_process( token, process_attr, thread_attr, - inherit, flags, startup_info, params, info ); - break; - } + wine_server_add_data( req, params->Environment, env_size ); diff --git a/server/process.c b/server/process.c -index 30832f474da..028ffa1b454 100644 +index 3cfc6f88f..b4466cf43 100644 --- a/server/process.c +++ b/server/process.c @@ -491,7 +491,7 @@ static void start_sigkill_timer( struct process *process ) @@ -136,7 +151,7 @@ index 30832f474da..028ffa1b454 100644 { struct process *process; -@@ -567,7 +567,7 @@ struct process *create_process( int fd, struct process *parent, int inherit_all, +@@ -568,7 +568,7 @@ struct process *create_process( int fd, struct process *parent, int inherit_all, : alloc_handle_table( process, 0 ); /* Note: for security reasons, starting a new process does not attempt * to use the current impersonation token for the new process */ @@ -145,7 +160,7 @@ index 30832f474da..028ffa1b454 100644 process->affinity = parent->affinity; } if (!process->handles || !process->token) goto error; -@@ -1123,6 +1123,7 @@ DECL_HANDLER(new_process) +@@ -1124,6 +1124,7 @@ DECL_HANDLER(new_process) const struct security_descriptor *sd; const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); struct process *process = NULL; @@ -153,7 +168,7 @@ index 30832f474da..028ffa1b454 100644 struct process *parent = current->process; int socket_fd = thread_get_inflight_fd( current, req->socket_fd ); -@@ -1163,10 +1164,39 @@ DECL_HANDLER(new_process) +@@ -1164,10 +1165,39 @@ DECL_HANDLER(new_process) return; } @@ -193,7 +208,7 @@ index 30832f474da..028ffa1b454 100644 return; } info->process = NULL; -@@ -1213,7 +1243,7 @@ DECL_HANDLER(new_process) +@@ -1214,7 +1244,7 @@ DECL_HANDLER(new_process) #undef FIXUP_LEN } @@ -202,7 +217,7 @@ index 30832f474da..028ffa1b454 100644 process->startup_info = (struct startup_info *)grab_object( info ); -@@ -1275,6 +1305,7 @@ DECL_HANDLER(new_process) +@@ -1276,6 +1306,7 @@ DECL_HANDLER(new_process) reply->handle = alloc_handle_no_access_check( parent, process, req->access, objattr->attributes ); done: @@ -210,7 +225,7 @@ index 30832f474da..028ffa1b454 100644 if (process) release_object( process ); release_object( info ); } -@@ -1307,7 +1338,7 @@ DECL_HANDLER(exec_process) +@@ -1308,7 +1339,7 @@ DECL_HANDLER(exec_process) close( socket_fd ); return; } @@ -220,10 +235,10 @@ index 30832f474da..028ffa1b454 100644 release_object( process ); } diff --git a/server/process.h b/server/process.h -index f21ab7722a9..774c147e783 100644 +index e072a35ba..9cf757cec 100644 --- a/server/process.h +++ b/server/process.h -@@ -117,7 +117,7 @@ extern unsigned int alloc_ptid( void *ptr ); +@@ -118,7 +118,7 @@ extern unsigned int alloc_ptid( void *ptr ); extern void free_ptid( unsigned int id ); extern void *get_ptid_entry( unsigned int id ); extern struct process *create_process( int fd, struct process *parent, int inherit_all, @@ -233,7 +248,7 @@ index f21ab7722a9..774c147e783 100644 extern struct thread *get_process_first_thread( struct process *process ); extern struct process *get_process_from_id( process_id_t id ); diff --git a/server/protocol.def b/server/protocol.def -index fcca1d255ba..4b01c6d1904 100644 +index 81a90f7d4..aa68ceedb 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -790,6 +790,7 @@ struct rawinput_device @@ -245,7 +260,7 @@ index fcca1d255ba..4b01c6d1904 100644 VARARG(info,startup_info,info_size); /* startup information */ VARARG(env,unicode_str); /* environment for new process */ diff --git a/server/request.c b/server/request.c -index d2adb08a183..139d643e8c8 100644 +index d2adb08a1..139d643e8 100644 --- a/server/request.c +++ b/server/request.c @@ -578,7 +578,7 @@ static void master_socket_poll_event( struct fd *fd, int event ) @@ -258,7 +273,7 @@ index d2adb08a183..139d643e8c8 100644 create_thread( -1, process, NULL ); release_object( process ); diff --git a/server/security.h b/server/security.h -index 21e90ccf23f..32dfe5f8db9 100644 +index 21e90ccf2..32dfe5f8d 100644 --- a/server/security.h +++ b/server/security.h @@ -67,6 +67,8 @@ extern const ACL *token_get_default_dacl( struct token *token ); @@ -271,7 +286,7 @@ index 21e90ccf23f..32dfe5f8db9 100644 static inline const ACE_HEADER *ace_next( const ACE_HEADER *ace ) { diff --git a/server/token.c b/server/token.c -index 181219d2179..858ec25d792 100644 +index 181219d21..858ec25d7 100644 --- a/server/token.c +++ b/server/token.c @@ -845,6 +845,12 @@ int token_assign_label( struct token *token, PSID label ) @@ -300,5 +315,5 @@ index 181219d2179..858ec25d792 100644 { GENERIC_MAPPING mapping; -- -2.20.1 +2.23.0 diff --git a/patches/kernel32-NeedCurrentDirectoryForExePath/0003-kernel32-Consider-the-working-directory-first-when-l.patch b/patches/kernel32-NeedCurrentDirectoryForExePath/0003-kernel32-Consider-the-working-directory-first-when-l.patch deleted file mode 100644 index 0063cbf2..00000000 --- a/patches/kernel32-NeedCurrentDirectoryForExePath/0003-kernel32-Consider-the-working-directory-first-when-l.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 495a42ea564348e860c036803c89ce3650dd0a27 Mon Sep 17 00:00:00 2001 -From: "Erich E. Hoover" -Date: Sat, 3 Jan 2015 20:55:43 -0700 -Subject: [PATCH] kernel32: Consider the working directory first when launching - executables with CreateProcess. - ---- - dlls/kernel32/process.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c -index 0a2192b246..ed78c0a01b 100644 ---- a/dlls/kernel32/process.c -+++ b/dlls/kernel32/process.c -@@ -439,6 +439,7 @@ static HANDLE open_exe_file( const WCHAR *name, BOOL *is_64bit ) - */ - static BOOL find_exe_file( const WCHAR *name, WCHAR *buffer, int buflen, HANDLE *handle ) - { -+ WCHAR cur_dir[MAX_PATH]; - WCHAR *load_path; - BOOL ret; - -@@ -446,7 +447,10 @@ static BOOL find_exe_file( const WCHAR *name, WCHAR *buffer, int buflen, HANDLE - - TRACE("looking for %s in %s\n", debugstr_w(name), debugstr_w(load_path) ); - -- ret = (SearchPathW( load_path, name, exeW, buflen, buffer, NULL ) || -+ ret = (NeedCurrentDirectoryForExePathW( name ) && GetCurrentDirectoryW( MAX_PATH, cur_dir) && -+ SearchPathW( cur_dir, name, exeW, buflen, buffer, NULL )) || -+ /* not found in the working directory, try the system search path */ -+ (SearchPathW( load_path, name, exeW, buflen, buffer, NULL ) || - /* no builtin found, try native without extension in case it is a Unix app */ - SearchPathW( load_path, name, NULL, buflen, buffer, NULL )); - RtlReleasePath( load_path ); --- -2.21.0 - diff --git a/patches/kernel32-NeedCurrentDirectoryForExePath/definition b/patches/kernel32-NeedCurrentDirectoryForExePath/definition deleted file mode 100644 index eb7205da..00000000 --- a/patches/kernel32-NeedCurrentDirectoryForExePath/definition +++ /dev/null @@ -1 +0,0 @@ -Fixes: [23934] CreateProcess does not prioritize the working directory over the system search path diff --git a/patches/kernel32-SetProcessDEPPolicy/0001-kernel32-Implement-SetProcessDEPPolicy.patch b/patches/kernel32-SetProcessDEPPolicy/0001-kernel32-Implement-SetProcessDEPPolicy.patch index 9bce7ce6..4975e6e6 100644 --- a/patches/kernel32-SetProcessDEPPolicy/0001-kernel32-Implement-SetProcessDEPPolicy.patch +++ b/patches/kernel32-SetProcessDEPPolicy/0001-kernel32-Implement-SetProcessDEPPolicy.patch @@ -1,26 +1,42 @@ -From 31df1334957af47dd6e3049ad10c63a0e2210005 Mon Sep 17 00:00:00 2001 +From 8ba5167f0ade2bd789e0a1b97263cfe5daad98d7 Mon Sep 17 00:00:00 2001 From: "Olivier F. R. Dierick" Date: Tue, 19 Apr 2016 07:25:39 +0200 Subject: [PATCH] kernel32: Implement SetProcessDEPPolicy(). --- - dlls/kernel32/process.c | 34 +++++++++++++++++++++++++++++++--- - 1 file changed, 31 insertions(+), 3 deletions(-) + dlls/kernel32/process.c | 36 +++++++++++++++++++++++++++++++++--- + 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c -index b9c277aac..1255732eb 100644 +index f68193c93..ae894c29d 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c -@@ -104,6 +104,8 @@ static WCHAR winevdm[] = {'C',':','\\','w','i','n','d','o','w','s', +@@ -70,6 +70,8 @@ typedef struct + DWORD dwReserved; + } LOADPARMS32; - static const char * const cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64" }; ++static BOOL is_wow64; ++ + HMODULE kernel32_handle = 0; + SYSTEM_BASIC_INFORMATION system_info = { 0 }; + +@@ -85,6 +87,7 @@ const WCHAR DIR_System[] = {'C',':','\\','w','i','n','d','o','w','s', + #define PDB32_FILE_APIS_OEM 0x0040 /* File APIs are OEM */ + #define PDB32_WIN32S_PROC 0x8000 /* Win32s process */ +static DEP_SYSTEM_POLICY_TYPE system_DEP_policy = OptIn; -+ - /* return values for get_binary_info */ - enum binary_type - { -@@ -2595,9 +2597,35 @@ DEP_SYSTEM_POLICY_TYPE WINAPI GetSystemDEPPolicy(void) + + /*********************************************************************** + * set_library_argv +@@ -211,6 +214,7 @@ void * CDECL __wine_kernel_init(void) + setbuf(stdout,NULL); + setbuf(stderr,NULL); + kernel32_handle = GetModuleHandleW(kernel32W); ++ IsWow64Process( GetCurrentProcess(), &is_wow64 ); + RtlSetUnhandledExceptionFilter( UnhandledExceptionFilter ); + + LOCALE_Init(); +@@ -917,9 +921,35 @@ DEP_SYSTEM_POLICY_TYPE WINAPI GetSystemDEPPolicy(void) */ BOOL WINAPI SetProcessDEPPolicy(DWORD newDEP) { diff --git a/patches/ole32-STGPROP/0001-ole32-Correctly-parse-unicode-property-storage-dicti.patch b/patches/ole32-STGPROP/0001-ole32-Correctly-parse-unicode-property-storage-dicti.patch deleted file mode 100644 index ecae05cd..00000000 --- a/patches/ole32-STGPROP/0001-ole32-Correctly-parse-unicode-property-storage-dicti.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 9a73838c005c3bdb74a449bb7afb269112d6ae34 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Fri, 20 Jan 2017 01:35:05 +0100 -Subject: ole32: Correctly parse unicode property storage dictionaries. - ---- - dlls/ole32/stg_prop.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/dlls/ole32/stg_prop.c b/dlls/ole32/stg_prop.c -index a2598832bf1..f952704c7cd 100644 ---- a/dlls/ole32/stg_prop.c -+++ b/dlls/ole32/stg_prop.c -@@ -1020,15 +1020,18 @@ static HRESULT PropertyStorage_ReadDictionary(PropertyStorage_impl *This, - if (This->codePage != CP_UNICODE) - ptr[cbEntry - 1] = '\0'; - else -- *((LPWSTR)ptr + cbEntry / sizeof(WCHAR)) = '\0'; -+ ((LPWSTR)ptr)[cbEntry - 1] = 0; - hr = PropertyStorage_StoreNameWithId(This, (char*)ptr, This->codePage, propid); - if (This->codePage == CP_UNICODE) - { -+ /* cbEntry is the number of characters */ -+ cbEntry *= 2; -+ - /* Unicode entries are padded to DWORD boundaries */ - if (cbEntry % sizeof(DWORD)) - ptr += sizeof(DWORD) - (cbEntry % sizeof(DWORD)); - } -- ptr += sizeof(DWORD) + cbEntry; -+ ptr += cbEntry; - } - return hr; - } --- -2.11.0 - diff --git a/patches/ole32-STGPROP/0003-ole32-Implement-returning-a-name-in-IEnumSTATPROPSTG.patch b/patches/ole32-STGPROP/0003-ole32-Implement-returning-a-name-in-IEnumSTATPROPSTG.patch deleted file mode 100644 index b1904f9e..00000000 --- a/patches/ole32-STGPROP/0003-ole32-Implement-returning-a-name-in-IEnumSTATPROPSTG.patch +++ /dev/null @@ -1,135 +0,0 @@ -From d56a94164cbe82bd3760a921e6eff029b62af63e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Fri, 20 Jan 2017 01:42:07 +0100 -Subject: [PATCH] ole32: Implement returning a name in IEnumSTATPROPSTG. - ---- - dlls/ole32/enumx.c | 16 ++++++++++++++-- - dlls/ole32/enumx.h | 5 ++++- - dlls/ole32/stg_prop.c | 25 ++++++++++++++++++++++++- - 3 files changed, 42 insertions(+), 4 deletions(-) - -diff --git a/dlls/ole32/enumx.c b/dlls/ole32/enumx.c -index 4279ca81fa9..2b53810dad9 100644 ---- a/dlls/ole32/enumx.c -+++ b/dlls/ole32/enumx.c -@@ -41,6 +41,8 @@ struct tagEnumSTATPROPSETSTG_impl - struct list *current; - ULONG elem_size; - GUID riid; -+ IUnknown *parent; -+ enumx_copy_cb copy_cb; - }; - - /************************************************************************ -@@ -91,6 +93,7 @@ ULONG WINAPI enumx_Release(enumx_impl *This) - list_remove(x); - HeapFree(GetProcessHeap(), 0, x); - } -+ IUnknown_Release(This->parent); - HeapFree(GetProcessHeap(), 0, This); - } - return ref; -@@ -112,7 +115,10 @@ HRESULT WINAPI enumx_Next(enumx_impl *This, ULONG celt, - p = rgelt; - while (count < celt && This->current && This->current != &This->elements) - { -- memcpy(p, &This->current[1], This->elem_size); -+ if (This->copy_cb) -+ This->copy_cb(This->parent, &This->current[1], p); -+ else -+ memcpy(p, &This->current[1], This->elem_size); - p += This->elem_size; - This->current = This->current->next; - count++; -@@ -169,7 +175,8 @@ HRESULT WINAPI enumx_Clone( - * - * Allocate a generic enumerator - */ --enumx_impl *enumx_allocate(REFIID riid, const void *vtbl, ULONG elem_size) -+enumx_impl *enumx_allocate(REFIID riid, const void *vtbl, ULONG elem_size, -+ IUnknown *parent, enumx_copy_cb copy_cb) - { - enumx_impl *enumx; - -@@ -181,6 +188,11 @@ enumx_impl *enumx_allocate(REFIID riid, const void *vtbl, ULONG elem_size) - enumx->current = NULL; - enumx->elem_size = elem_size; - enumx->riid = *riid; -+ enumx->parent = parent; -+ enumx->copy_cb = copy_cb; -+ -+ IUnknown_AddRef(parent); -+ - list_init(&enumx->elements); - } - -diff --git a/dlls/ole32/enumx.h b/dlls/ole32/enumx.h -index da76e13769b..8a2a2b354d8 100644 ---- a/dlls/ole32/enumx.h -+++ b/dlls/ole32/enumx.h -@@ -21,6 +21,8 @@ - - typedef struct tagEnumSTATPROPSETSTG_impl enumx_impl; - -+typedef void (*enumx_copy_cb)(IUnknown *parent, void *orig, void *dest); -+ - extern HRESULT WINAPI enumx_QueryInterface(enumx_impl *, REFIID, void**) DECLSPEC_HIDDEN; - extern ULONG WINAPI enumx_AddRef(enumx_impl *) DECLSPEC_HIDDEN; - extern ULONG WINAPI enumx_Release(enumx_impl *) DECLSPEC_HIDDEN; -@@ -28,7 +30,8 @@ extern HRESULT WINAPI enumx_Next(enumx_impl *, ULONG, void *, ULONG *) DECLSPEC_ - extern HRESULT WINAPI enumx_Skip(enumx_impl *, ULONG) DECLSPEC_HIDDEN; - extern HRESULT WINAPI enumx_Reset(enumx_impl *) DECLSPEC_HIDDEN; - extern HRESULT WINAPI enumx_Clone(enumx_impl *, enumx_impl **) DECLSPEC_HIDDEN; --extern enumx_impl *enumx_allocate(REFIID, const void *, ULONG) DECLSPEC_HIDDEN; -+extern enumx_impl *enumx_allocate(REFIID, const void *, ULONG, -+ IUnknown *, enumx_copy_cb) DECLSPEC_HIDDEN; - extern void *enumx_add_element(enumx_impl *, const void *) DECLSPEC_HIDDEN; - - #endif -diff --git a/dlls/ole32/stg_prop.c b/dlls/ole32/stg_prop.c -index 989e68b830d..eb98a7d2516 100644 ---- a/dlls/ole32/stg_prop.c -+++ b/dlls/ole32/stg_prop.c -@@ -2571,6 +2571,27 @@ static HRESULT WINAPI IEnumSTATPROPSTG_fnClone( - return enumx_Clone((enumx_impl*)iface, (enumx_impl**)ppenum); - } - -+static void prop_enum_copy_cb(IUnknown *parent, void *orig, void *dest) -+{ -+ PropertyStorage_impl *storage = impl_from_IPropertyStorage((IPropertyStorage*)parent); -+ STATPROPSTG *src_prop = orig; -+ STATPROPSTG *dest_prop = dest; -+ LPWSTR name; -+ -+ dest_prop->propid = src_prop->propid; -+ dest_prop->vt = src_prop->vt; -+ dest_prop->lpwstrName = NULL; -+ -+ if (dictionary_find(storage->propid_to_name, UlongToPtr(src_prop->propid), (void**)&name)) -+ { -+ DWORD size = (lstrlenW(name) + 1) * sizeof(WCHAR); -+ -+ dest_prop->lpwstrName = CoTaskMemAlloc(size); -+ if (!dest_prop->lpwstrName) return; -+ memcpy(dest_prop->lpwstrName, name, size); -+ } -+} -+ - static BOOL prop_enum_stat(const void *k, const void *v, void *extra, void *arg) - { - enumx_impl *enumx = arg; -@@ -2597,7 +2618,9 @@ static HRESULT create_EnumSTATPROPSTG( - - enumx = enumx_allocate(&IID_IEnumSTATPROPSTG, - &IEnumSTATPROPSTG_Vtbl, -- sizeof (STATPROPSTG)); -+ sizeof (STATPROPSTG), -+ (IUnknown*)&This->IPropertyStorage_iface, -+ prop_enum_copy_cb); - - dictionary_enumerate(This->propid_to_prop, prop_enum_stat, enumx); - --- -2.24.0.rc1 - diff --git a/patches/ole32-STGPROP/definition b/patches/ole32-STGPROP/definition deleted file mode 100644 index cc01c5bb..00000000 --- a/patches/ole32-STGPROP/definition +++ /dev/null @@ -1,2 +0,0 @@ -Fixes: [42046] Multiple fixes for ole32 property storage -Disabled: true diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 2f173148..55b031a8 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -52,7 +52,7 @@ usage() # Get the upstream commit sha upstream_commit() { - echo "34ed1e37da1e1c1cfd641f1f16b0e00030cbb357" + echo "292b728908563952f56b0585d072f3d7a08e93b2" } # Show version information @@ -158,7 +158,6 @@ patch_enable_all () enable_kernel32_FindFirstFile="$1" enable_kernel32_Job_Tests="$1" enable_kernel32_K32GetPerformanceInfo="$1" - enable_kernel32_NeedCurrentDirectoryForExePath="$1" enable_kernel32_PE_Loader_Fixes="$1" enable_kernel32_Processor_Group="$1" enable_kernel32_SCSI_Sysfs="$1" @@ -595,9 +594,6 @@ patch_enable () kernel32-K32GetPerformanceInfo) enable_kernel32_K32GetPerformanceInfo="$2" ;; - kernel32-NeedCurrentDirectoryForExePath) - enable_kernel32_NeedCurrentDirectoryForExePath="$2" - ;; kernel32-PE_Loader_Fixes) enable_kernel32_PE_Loader_Fixes="$2" ;; @@ -2141,7 +2137,7 @@ fi # | * [#39262] Run explorer.exe as unevaluated process # | # | Modified files: -# | * configure.ac, dlls/advapi32/tests/Makefile.in, dlls/advapi32/tests/security.c, dlls/kernel32/process.c, +# | * configure.ac, dlls/advapi32/tests/Makefile.in, dlls/advapi32/tests/security.c, dlls/kernelbase/process.c, # | dlls/ntdll/loader.c, dlls/ntdll/nt.c, dlls/ntdll/ntdll.spec, dlls/ntdll/ntdll_misc.h, dlls/ntdll/process.c, # | dlls/shell32/shlexec.c, dlls/user32/win.c, programs/runas/Makefile.in, programs/runas/runas.c, programs/runas/runas.h, # | programs/runas/runas.rc, server/process.c, server/process.h, server/protocol.def, server/request.c, server/security.h, @@ -4196,21 +4192,6 @@ if test "$enable_kernel32_Job_Tests" -eq 1; then ) >> "$patchlist" fi -# Patchset kernel32-NeedCurrentDirectoryForExePath -# | -# | This patchset fixes the following Wine bugs: -# | * [#23934] CreateProcess does not prioritize the working directory over the system search path -# | -# | Modified files: -# | * dlls/kernel32/process.c -# | -if test "$enable_kernel32_NeedCurrentDirectoryForExePath" -eq 1; then - patch_apply kernel32-NeedCurrentDirectoryForExePath/0003-kernel32-Consider-the-working-directory-first-when-l.patch - ( - printf '%s\n' '+ { "Erich E. Hoover", "kernel32: Consider the working directory first when launching executables with CreateProcess.", 1 },'; - ) >> "$patchlist" -fi - # Patchset kernel32-PE_Loader_Fixes # | # | This patchset fixes the following Wine bugs: @@ -6574,7 +6555,7 @@ fi # Patchset wined3d-Accounting # | # | Modified files: -# | * dlls/d3d9/tests/device.c, dlls/wined3d/adapter_gl.c, dlls/wined3d/device.c, dlls/wined3d/wined3d_gl.h +# | * dlls/wined3d/adapter_gl.c, dlls/wined3d/device.c, dlls/wined3d/wined3d_gl.h # | if test "$enable_wined3d_Accounting" -eq 1; then patch_apply wined3d-Accounting/0001-wined3d-Use-real-values-for-memory-accounting-on-NVI.patch diff --git a/patches/wined3d-Accounting/0001-wined3d-Use-real-values-for-memory-accounting-on-NVI.patch b/patches/wined3d-Accounting/0001-wined3d-Use-real-values-for-memory-accounting-on-NVI.patch index 185c34f8..6fbe8168 100644 --- a/patches/wined3d-Accounting/0001-wined3d-Use-real-values-for-memory-accounting-on-NVI.patch +++ b/patches/wined3d-Accounting/0001-wined3d-Use-real-values-for-memory-accounting-on-NVI.patch @@ -1,4 +1,4 @@ -From 1eb53d1e30aeadbf77bf6d9285a3c9cdd6dcc612 Mon Sep 17 00:00:00 2001 +From 55f1d67826fdb5619da6fd8d081836076fdaee28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Sat, 6 Jun 2015 06:53:34 +0200 Subject: [PATCH] wined3d: Use real values for memory accounting on NVIDIA @@ -7,36 +7,13 @@ Subject: [PATCH] wined3d: Use real values for memory accounting on NVIDIA FIXME: Reimplement wined3d_device_get_available_texture_mem without using the context on the main thread. --- - dlls/d3d9/tests/device.c | 11 +++++++---- dlls/wined3d/adapter_gl.c | 12 ++++++++++++ dlls/wined3d/device.c | 23 +++++++++++++++++++++++ dlls/wined3d/wined3d_gl.h | 1 + - 4 files changed, 43 insertions(+), 4 deletions(-) + 3 files changed, 36 insertions(+) -diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c -index 3d42dcbcc56..617fc94970b 100644 ---- a/dlls/d3d9/tests/device.c -+++ b/dlls/d3d9/tests/device.c -@@ -9548,10 +9548,13 @@ static void test_vidmem_accounting(void) - } - vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device); - -- ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n"); -- diff = vidmem_start - vidmem_end; -- ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n", -- 2 * i, diff / 1024 / 1024); -+ todo_wine_if(vidmem_start == vidmem_end) -+ { -+ ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n"); -+ diff = vidmem_start - vidmem_end; -+ ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n", -+ 2 * i, diff / 1024 / 1024); -+ } - - for (i = 0; i < ARRAY_SIZE(textures); i++) - { diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c -index e83aebfa56f..6499fcf3aef 100644 +index 7018c6da1..cf43628af 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -230,6 +230,7 @@ static const struct wined3d_extension_map gl_extension_map[] = @@ -66,7 +43,7 @@ index e83aebfa56f..6499fcf3aef 100644 if ((gpu_description_override = wined3d_get_user_override_gpu_description(vendor, device))) gpu_description = gpu_description_override; diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index b2aa33af41f..e67391737d9 100644 +index 2a4d37784..7bfbde51f 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1200,6 +1200,29 @@ UINT CDECL wined3d_device_get_available_texture_mem(const struct wined3d_device @@ -100,7 +77,7 @@ index b2aa33af41f..e67391737d9 100644 wine_dbgstr_longlong(driver_info->vram_bytes), wine_dbgstr_longlong(device->adapter->vram_bytes_used), diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h -index 3372b4b6be3..7995404901b 100644 +index 3372b4b6b..799540490 100644 --- a/dlls/wined3d/wined3d_gl.h +++ b/dlls/wined3d/wined3d_gl.h @@ -206,6 +206,7 @@ enum wined3d_gl_extension @@ -112,5 +89,5 @@ index 3372b4b6be3..7995404901b 100644 WGL_ARB_PIXEL_FORMAT, WGL_EXT_SWAP_CONTROL, -- -2.17.1 +2.23.0