[PATCH 1/3] winebuild: Added support for entry points generated in runtime.
Jacek Caban
jacek at codeweavers.com
Thu Jan 21 09:58:31 CST 2016
On 01/21/16 16:04, Sebastian Lackner wrote:
> On 21.01.2016 15:43, Jacek Caban wrote:
>> On 01/19/16 17:06, Alexandre Julliard wrote:
>>> Jacek Caban <jacek at codeweavers.com> writes:
>>>
>>>> All such solutions require changes in both Chrome and Wine, which makes
>>>> it tricky to decide on a solution. What's your opinion?
>>> My concern is not just about hooking the system calls, it's what happens
>>> once they are hooked. Sebastian said that hooks inside the Ldr*
>>> functions don't work right. I'm worried that supporting this properly
>>> would require that our internal code paths follow the Windows ones
>>> closely, which is neither feasible nor desirable.
>>>
>>> This could of course also be changed in Chrome so that it could deal
>>> with the way Wine's ntdll is implemented, but that would probably be
>>> more intrusive.
>> It's hard to discuss what Sebastian reports without understanding the
>> problem. For what I know, his variant of patches exposes way more
>> hookable calls than it should. It's not a secret that on Windows Nt*
>> functions will not call any other exported functions. This is an
>> implementation detail that I don't consider too internal to follow. The
>> fact that those hooks may be called recursively with Sebastian's patches
>> makes me think that it's the most likely reason of the problems.
> Could you please point out where you think my patchset doesn't match
> Windows behavior / leads to recursive calls which should not occur?
I looked deeper in your patchset and the one occur that I thought was
there was my mistake.
> Or, have you already tried improving your patchset, to implement forwarding
> of Ldr* and Rtl* functions through the thunks, like it is supposed to work
> on Windows? I would guess you encounter exactly the same problem.
Yes, I tried that. See the attached patch (note that SYSCALL macro has
an opposite meaning comparing to your patches) on top of my patchset. I
couldn't reproduce the problem with Steam. It still works for me 100% of
time.
I tried to compare it with your version, but, as I wrote you, it didn't
work for me at all. I assume I'm missing something.
>> For other internal behaviour, we already have cases where they do
>> matter. My recent example is Office 2013 online installer (which has
>> sandbox-like code that among others merges some special dirs, sometimes
>> containing DLLs, into file system). It's obvious that we need
>> NtOpenFile-alike in loader to open a file in loader and all changes that
>> it required was to pass SYNCHRONIZE flag. For all I know native may use
>> different APIs there, but all is fine using this call as long as we pass
>> an argument that is sane and makes sense anyway.
>>
>> That said, I fully agree that we don't want to follow Windows too
>> closely, but I don't think we're at this point yet. Also, my variant of
>> the patch (others could be reworked to follow that as well) exposes even
>> less internal behaviour than existing code, because we need to
>> explicitly mark parts that would go through exported thunks.
>>
>> Here is my proposal for fixing the situation:
>>
>> Short term we use one of variants of patches for syscall thunks. This
>> will give an immediate fix for at lest some (most common?) Wine configs.
> If the issues with Ldr* functions can be solved I'm fine with that. However,
> I wouldn't necessarily recommend the JIT approach if we have only one supported
> config. Lets assume we would use winebuild statically generated thunks (like my
> patch based on Erichs work), the additional logic for JIT could be implemented
> at any time later.
Sure, in that case we won't need the flexibility of JIT, so static
thunks should be fine. I still think we could avoid text relocations,
but that's a different topic.
Thanks,
Jacek
-------------- next part --------------
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 6529105..10360e2 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -620,7 +620,7 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d
while (import_list[protect_size].u1.Ordinal) protect_size++;
protect_base = thunk_list;
protect_size *= sizeof(*thunk_list);
- NtProtectVirtualMemory( NtCurrentProcess(), &protect_base,
+ SYSCALL(NtProtectVirtualMemory)( NtCurrentProcess(), &protect_base,
&protect_size, PAGE_READWRITE, &protect_old );
imp_mod = wmImp->ldr.BaseAddress;
@@ -692,7 +692,7 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d
done:
/* restore old protection of the import address table */
- NtProtectVirtualMemory( NtCurrentProcess(), &protect_base, &protect_size, protect_old, &protect_old );
+ SYSCALL(NtProtectVirtualMemory)( NtCurrentProcess(), &protect_base, &protect_size, protect_old, &protect_old );
return wmImp;
}
@@ -1475,7 +1475,7 @@ static BOOL is_fake_dll( HANDLE handle )
LARGE_INTEGER offset;
offset.QuadPart = 0;
- if (NtReadFile( handle, 0, NULL, 0, &io, buffer, sizeof(buffer), &offset, NULL )) return FALSE;
+ if (SYSCALL(NtReadFile)( handle, 0, NULL, 0, &io, buffer, sizeof(buffer), &offset, NULL )) return FALSE;
if (io.Information < sizeof(buffer)) return FALSE;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) return FALSE;
if (dos->e_lfanew >= sizeof(*dos) + sizeof(fakedll_signature) &&
@@ -1774,12 +1774,12 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
TRACE("Trying native dll %s\n", debugstr_w(name));
size.QuadPart = 0;
- status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
+ status = SYSCALL(NtCreateSection)( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
NULL, &size, PAGE_EXECUTE_READ, SEC_IMAGE, file );
if (status != STATUS_SUCCESS) return status;
module = NULL;
- status = NtMapViewOfSection( mapping, NtCurrentProcess(),
+ status = SYSCALL(NtMapViewOfSection)( mapping, NtCurrentProcess(),
&module, 0, 0, &size, &len, ViewShare, 0, PAGE_EXECUTE_READ );
/* perform base relocation, if necessary */
@@ -1789,7 +1789,7 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
if (status != STATUS_SUCCESS)
{
- if (module) NtUnmapViewOfSection( NtCurrentProcess(), module );
+ if (module) SYSCALL(NtUnmapViewOfSection)( NtCurrentProcess(), module );
goto done;
}
@@ -1851,7 +1851,7 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
*pwm = wm;
status = STATUS_SUCCESS;
done:
- NtClose( mapping );
+ SYSCALL(NtClose)( mapping );
return status;
}
@@ -2247,7 +2247,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
if (handle && is_fake_dll( handle ))
{
TRACE( "%s is a fake Wine dll\n", debugstr_w(filename) );
- NtClose( handle );
+ SYSCALL(NtClose)( handle );
handle = 0;
}
@@ -2299,13 +2299,13 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
TRACE("Loaded module %s (%s) at %p\n", debugstr_w(filename),
((*pwm)->ldr.Flags & LDR_WINE_INTERNAL) ? "builtin" : "native",
(*pwm)->ldr.BaseAddress);
- if (handle) NtClose( handle );
+ if (handle) SYSCALL(NtClose)( handle );
if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
return nts;
}
WARN("Failed to load module %s; status=%x\n", debugstr_w(libname), nts);
- if (handle) NtClose( handle );
+ if (handle) SYSCALL(NtClose)( handle );
if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
return nts;
}
@@ -2579,7 +2579,7 @@ static NTSTATUS query_string_option( HANDLE hkey, LPCWSTR name, ULONG type,
size = info_size + in_size;
if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return STATUS_NO_MEMORY;
info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
- status = NtQueryValueKey( hkey, &str, KeyValuePartialInformation, buffer, size, &size );
+ status = SYSCALL(NtQueryValueKey)( hkey, &str, KeyValuePartialInformation, buffer, size, &size );
if (!status || status == STATUS_BUFFER_OVERFLOW)
{
if (out_size) *out_size = info->DataLength;
@@ -2626,7 +2626,7 @@ NTSTATUS WINAPI LdrQueryImageFileExecutionOptions( const UNICODE_STRING *key, LP
name_str.MaximumLength = name_str.Length;
memcpy( path, optionsW, sizeof(optionsW) );
memcpy( path + sizeof(optionsW)/sizeof(WCHAR), p, len );
- if ((status = NtOpenKey( &hkey, KEY_QUERY_VALUE, &attr ))) return status;
+ if ((status = SYSCALL(NtOpenKey)( &hkey, KEY_QUERY_VALUE, &attr ))) return status;
if (type == REG_DWORD)
{
@@ -2636,7 +2636,7 @@ NTSTATUS WINAPI LdrQueryImageFileExecutionOptions( const UNICODE_STRING *key, LP
}
else status = query_string_option( hkey, value, type, data, in_size, out_size );
- NtClose( hkey );
+ SYSCALL(NtClose)( hkey );
return status;
}
@@ -2733,9 +2733,9 @@ void WINAPI RtlExitUserProcess( DWORD status )
{
RtlEnterCriticalSection( &loader_section );
RtlAcquirePebLock();
- NtTerminateProcess( 0, status );
+ SYSCALL(NtTerminateProcess)( 0, status );
LdrShutdownProcess();
- NtTerminateProcess( GetCurrentProcess(), status );
+ SYSCALL(NtTerminateProcess)( GetCurrentProcess(), status );
exit( status );
}
@@ -2813,7 +2813,7 @@ static void free_modref( WINE_MODREF *wm )
free_tls_slot( &wm->ldr );
RtlReleaseActivationContext( wm->ldr.ActivationContext );
if (wm->ldr.Flags & LDR_WINE_INTERNAL) wine_dll_unload( wm->ldr.SectionHandle );
- NtUnmapViewOfSection( NtCurrentProcess(), wm->ldr.BaseAddress );
+ SYSCALL(NtUnmapViewOfSection)( NtCurrentProcess(), wm->ldr.BaseAddress );
if (cached_modref == wm) cached_modref = NULL;
RtlFreeUnicodeString( &wm->ldr.FullDllName );
RtlFreeHeap( GetProcessHeap(), 0, wm->deps );
@@ -3053,7 +3053,7 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2,
LPCWSTR load_path;
PEB *peb = NtCurrentTeb()->Peb;
- if (main_exe_file) NtClose( main_exe_file ); /* at this point the main module is created */
+ if (main_exe_file) SYSCALL(NtClose)( main_exe_file ); /* at this point the main module is created */
/* allocate the modref for the main exe (if not already done) */
wm = get_modref( peb->ImageBaseAddress );
@@ -3096,7 +3096,7 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2,
error:
ERR( "Main exe initialization for %s failed, status %x\n",
debugstr_w(peb->ProcessParameters->ImagePathName.Buffer), status );
- NtTerminateProcess( GetCurrentProcess(), status );
+ SYSCALL(NtTerminateProcess)( GetCurrentProcess(), status );
}
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index f185eb9..254e527 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -273,6 +273,16 @@ NTSTATUS WINAPI RtlHashUnicodeString(PCUNICODE_STRING,BOOLEAN,ULONG,ULONG*);
extern typeof( name ) __jit_ ## name
DECLARE_SYSCALL_ENTRYPOINT( NtOpenFile );
+DECLARE_SYSCALL_ENTRYPOINT( NtAllocateVirtualMemory );
+DECLARE_SYSCALL_ENTRYPOINT( NtProtectVirtualMemory );
+DECLARE_SYSCALL_ENTRYPOINT( NtReadFile );
+DECLARE_SYSCALL_ENTRYPOINT( NtCreateSection );
+DECLARE_SYSCALL_ENTRYPOINT( NtMapViewOfSection );
+DECLARE_SYSCALL_ENTRYPOINT( NtUnmapViewOfSection );
+DECLARE_SYSCALL_ENTRYPOINT( NtClose );
+DECLARE_SYSCALL_ENTRYPOINT( NtQueryValueKey );
+DECLARE_SYSCALL_ENTRYPOINT( NtOpenKey );
+DECLARE_SYSCALL_ENTRYPOINT( NtTerminateProcess );
#else /* defined(__i386__) */
More information about the wine-devel
mailing list