[v3] ntdll: Read entry point in LdrInitializeThunk.
Andrew Wesie
awesie at gmail.com
Sun Feb 5 04:27:27 CST 2017
Overwatch overwrites the PE header contents in a TLS callback. This results in
a crash on wine, because the entry point will be incorrect in start_process.
Fix the issue by reading the entry point in LdrInitializeThunk before any TLS
callbacks are executed. Use this cached value by passing it into start_process
instead of PEB.
Signed-off-by: Andrew Wesie <awesie at gmail.com>
---
dlls/kernel32/process.c | 12 +++---------
dlls/ntdll/loader.c | 23 ++++++++++++++++++++---
2 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 5a9fea2..4dfb421 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -1083,16 +1083,10 @@ static inline DWORD call_process_entry( PEB *peb, LPTHREAD_START_ROUTINE entry )
*
* Startup routine of a new process. Runs on the new process stack.
*/
-static DWORD WINAPI start_process( PEB *peb )
+static DWORD WINAPI start_process( LPTHREAD_START_ROUTINE entry )
{
- IMAGE_NT_HEADERS *nt;
- LPTHREAD_START_ROUTINE entry;
-
- nt = RtlImageNtHeader( peb->ImageBaseAddress );
- entry = (LPTHREAD_START_ROUTINE)((char *)peb->ImageBaseAddress +
- nt->OptionalHeader.AddressOfEntryPoint);
-
- if (!nt->OptionalHeader.AddressOfEntryPoint)
+ PEB *peb = NtCurrentTeb()->Peb;
+ if (!entry)
{
ERR( "%s doesn't have an entry point, it cannot be executed\n",
debugstr_w(peb->ProcessParameters->ImagePathName.Buffer) );
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index f1ef7ab..daae9ff 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -99,6 +99,12 @@ struct builtin_load_info
static struct builtin_load_info default_load_info;
static struct builtin_load_info *builtin_load_info = &default_load_info;
+struct start_params
+{
+ void *kernel_start;
+ LPTHREAD_START_ROUTINE entry;
+};
+
static HANDLE main_exe_file;
static UINT tls_module_count; /* number of modules with TLS directory */
static IMAGE_TLS_DIRECTORY *tls_dirs; /* array of TLS directories */
@@ -3042,9 +3048,10 @@ static void load_global_options(void)
/***********************************************************************
* start_process
*/
-static void start_process( void *kernel_start )
+static void start_process( void *arg )
{
- call_thread_entry_point( kernel_start, NtCurrentTeb()->Peb );
+ struct start_params *start_params = (struct start_params *)arg;
+ call_thread_entry_point( start_params->kernel_start, start_params->entry );
}
/******************************************************************
@@ -3059,9 +3066,19 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2,
WINE_MODREF *wm;
LPCWSTR load_path;
PEB *peb = NtCurrentTeb()->Peb;
+ IMAGE_NT_HEADERS *nt;
+ struct start_params start_params;
if (main_exe_file) NtClose( main_exe_file ); /* at this point the main module is created */
+ nt = RtlImageNtHeader( peb->ImageBaseAddress );
+ if (nt->OptionalHeader.AddressOfEntryPoint)
+ start_params.entry = (LPTHREAD_START_ROUTINE)((char *)peb->ImageBaseAddress +
+ nt->OptionalHeader.AddressOfEntryPoint);
+ else
+ start_params.entry = NULL;
+ start_params.kernel_start = kernel_start;
+
/* allocate the modref for the main exe (if not already done) */
wm = get_modref( peb->ImageBaseAddress );
assert( wm );
@@ -3100,7 +3117,7 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2,
virtual_release_address_space();
virtual_clear_thread_stack();
- wine_switch_to_stack( start_process, kernel_start, NtCurrentTeb()->Tib.StackBase );
+ wine_switch_to_stack( start_process, &start_params, NtCurrentTeb()->Tib.StackBase );
error:
ERR( "Main exe initialization for %s failed, status %x\n",
--
2.7.4
More information about the wine-patches
mailing list