ntdll: Add support for LdrSystemDllInitBlock.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
390d71b091
commit
3a32ea8e91
|
@ -74,6 +74,8 @@ void (FASTCALL *pBaseThreadInitThunk)(DWORD,LPTHREAD_START_ROUTINE,void *) = NUL
|
|||
|
||||
static DWORD (WINAPI *pCtrlRoutine)(void *);
|
||||
|
||||
SYSTEM_DLL_INIT_BLOCK LdrSystemDllInitBlock = { 0xf0 };
|
||||
|
||||
const struct unix_funcs *unix_funcs = NULL;
|
||||
|
||||
/* windows directory */
|
||||
|
@ -3722,6 +3724,18 @@ static void init_wow64(void)
|
|||
peb64->OSBuildNumber = peb->OSBuildNumber;
|
||||
peb64->OSPlatformId = peb->OSPlatformId;
|
||||
|
||||
#define SET_INIT_BLOCK(func) LdrSystemDllInitBlock.p ## func = PtrToUlong( &func )
|
||||
SET_INIT_BLOCK( KiUserApcDispatcher );
|
||||
SET_INIT_BLOCK( KiUserExceptionDispatcher );
|
||||
SET_INIT_BLOCK( LdrInitializeThunk );
|
||||
SET_INIT_BLOCK( LdrSystemDllInitBlock );
|
||||
SET_INIT_BLOCK( RtlUserThreadStart );
|
||||
/* SET_INIT_BLOCK( KiUserCallbackDispatcher ); */
|
||||
/* SET_INIT_BLOCK( RtlpQueryProcessDebugInformationRemote ); */
|
||||
/* SET_INIT_BLOCK( RtlpFreezeTimeBias ); */
|
||||
/* LdrSystemDllInitBlock.ntdll_handle */
|
||||
#undef SET_INIT_BLOCK
|
||||
|
||||
map_wow64cpu();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -109,6 +109,7 @@
|
|||
@ stub LdrSetDllManifestProber
|
||||
@ stdcall LdrShutdownProcess()
|
||||
@ stdcall LdrShutdownThread()
|
||||
@ extern LdrSystemDllInitBlock
|
||||
@ stub LdrUnloadAlternateResourceModule
|
||||
@ stdcall LdrUnloadDll(ptr)
|
||||
@ stdcall LdrUnlockLoaderLock(long long)
|
||||
|
|
|
@ -48,6 +48,10 @@ extern LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) DE
|
|||
extern void DECLSPEC_NORETURN raise_status( NTSTATUS status, EXCEPTION_RECORD *rec ) DECLSPEC_HIDDEN;
|
||||
extern LONG WINAPI call_unhandled_exception_filter( PEXCEPTION_POINTERS eptr ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern void WINAPI LdrInitializeThunk(CONTEXT*,ULONG_PTR,ULONG_PTR,ULONG_PTR) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS WINAPI KiUserExceptionDispatcher(EXCEPTION_RECORD*,CONTEXT*) DECLSPEC_HIDDEN;
|
||||
extern void WINAPI KiUserApcDispatcher(CONTEXT*,ULONG_PTR,ULONG_PTR,ULONG_PTR,PNTAPCFUNC) DECLSPEC_HIDDEN;
|
||||
|
||||
#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
|
||||
extern RUNTIME_FUNCTION *lookup_function_info( ULONG_PTR pc, ULONG_PTR *base, LDR_DATA_TABLE_ENTRY **module ) DECLSPEC_HIDDEN;
|
||||
#endif
|
||||
|
|
|
@ -557,8 +557,9 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte
|
|||
* KiUserApcDispatcher (NTDLL.@)
|
||||
*/
|
||||
void WINAPI KiUserApcDispatcher( CONTEXT *context, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3,
|
||||
void (CALLBACK *func)(ULONG_PTR,ULONG_PTR,ULONG_PTR,CONTEXT*) )
|
||||
PNTAPCFUNC apc )
|
||||
{
|
||||
void (CALLBACK *func)(ULONG_PTR,ULONG_PTR,ULONG_PTR,CONTEXT*) = (void *)apc;
|
||||
func( arg1, arg2, arg3, context );
|
||||
NtContinue( context, TRUE );
|
||||
}
|
||||
|
|
|
@ -956,6 +956,121 @@ static void test_nt_wow64(void)
|
|||
NtClose( process );
|
||||
}
|
||||
|
||||
static void test_init_block(void)
|
||||
{
|
||||
HMODULE ntdll = GetModuleHandleA( "ntdll.dll" );
|
||||
ULONG i, size = 0, *init_block;
|
||||
ULONG64 ptr64, *block64;
|
||||
void *ptr;
|
||||
|
||||
if (!is_wow64) return;
|
||||
if ((ptr = GetProcAddress( ntdll, "LdrSystemDllInitBlock" )))
|
||||
{
|
||||
init_block = ptr;
|
||||
trace( "got init block %08x\n", init_block[0] );
|
||||
#define CHECK_FUNC(val,func) \
|
||||
ok( (val) == (ULONG_PTR)GetProcAddress( ntdll, func ), \
|
||||
"got %p for %s %p\n", (void *)(ULONG_PTR)(val), func, GetProcAddress( ntdll, func ))
|
||||
switch (init_block[0])
|
||||
{
|
||||
case 0x44: /* vistau64 */
|
||||
CHECK_FUNC( init_block[1], "LdrInitializeThunk" );
|
||||
CHECK_FUNC( init_block[2], "KiUserExceptionDispatcher" );
|
||||
CHECK_FUNC( init_block[3], "KiUserApcDispatcher" );
|
||||
CHECK_FUNC( init_block[4], "KiUserCallbackDispatcher" );
|
||||
CHECK_FUNC( init_block[5], "LdrHotPatchRoutine" );
|
||||
CHECK_FUNC( init_block[6], "ExpInterlockedPopEntrySListFault" );
|
||||
CHECK_FUNC( init_block[7], "ExpInterlockedPopEntrySListResume" );
|
||||
CHECK_FUNC( init_block[8], "ExpInterlockedPopEntrySListEnd" );
|
||||
CHECK_FUNC( init_block[9], "RtlUserThreadStart" );
|
||||
CHECK_FUNC( init_block[10], "RtlpQueryProcessDebugInformationRemote" );
|
||||
CHECK_FUNC( init_block[11], "EtwpNotificationThread" );
|
||||
ok( init_block[12] == (ULONG_PTR)ntdll, "got %p for ntdll %p\n",
|
||||
(void *)(ULONG_PTR)init_block[12], ntdll );
|
||||
size = 13 * sizeof(*init_block);
|
||||
break;
|
||||
case 0x50: /* win7 */
|
||||
CHECK_FUNC( init_block[4], "LdrInitializeThunk" );
|
||||
CHECK_FUNC( init_block[5], "KiUserExceptionDispatcher" );
|
||||
CHECK_FUNC( init_block[6], "KiUserApcDispatcher" );
|
||||
CHECK_FUNC( init_block[7], "KiUserCallbackDispatcher" );
|
||||
CHECK_FUNC( init_block[8], "LdrHotPatchRoutine" );
|
||||
CHECK_FUNC( init_block[9], "ExpInterlockedPopEntrySListFault" );
|
||||
CHECK_FUNC( init_block[10], "ExpInterlockedPopEntrySListResume" );
|
||||
CHECK_FUNC( init_block[11], "ExpInterlockedPopEntrySListEnd" );
|
||||
CHECK_FUNC( init_block[12], "RtlUserThreadStart" );
|
||||
CHECK_FUNC( init_block[13], "RtlpQueryProcessDebugInformationRemote" );
|
||||
CHECK_FUNC( init_block[14], "EtwpNotificationThread" );
|
||||
ok( init_block[15] == (ULONG_PTR)ntdll, "got %p for ntdll %p\n",
|
||||
(void *)(ULONG_PTR)init_block[15], ntdll );
|
||||
CHECK_FUNC( init_block[16], "LdrSystemDllInitBlock" );
|
||||
size = 17 * sizeof(*init_block);
|
||||
break;
|
||||
case 0x70: /* win8 */
|
||||
CHECK_FUNC( init_block[4], "LdrInitializeThunk" );
|
||||
CHECK_FUNC( init_block[5], "KiUserExceptionDispatcher" );
|
||||
CHECK_FUNC( init_block[6], "KiUserApcDispatcher" );
|
||||
CHECK_FUNC( init_block[7], "KiUserCallbackDispatcher" );
|
||||
CHECK_FUNC( init_block[8], "ExpInterlockedPopEntrySListFault" );
|
||||
CHECK_FUNC( init_block[9], "ExpInterlockedPopEntrySListResume" );
|
||||
CHECK_FUNC( init_block[10], "ExpInterlockedPopEntrySListEnd" );
|
||||
CHECK_FUNC( init_block[11], "RtlUserThreadStart" );
|
||||
CHECK_FUNC( init_block[12], "RtlpQueryProcessDebugInformationRemote" );
|
||||
ok( init_block[13] == (ULONG_PTR)ntdll, "got %p for ntdll %p\n",
|
||||
(void *)(ULONG_PTR)init_block[13], ntdll );
|
||||
CHECK_FUNC( init_block[14], "LdrSystemDllInitBlock" );
|
||||
size = 15 * sizeof(*init_block);
|
||||
break;
|
||||
case 0x80: /* win10 1507 */
|
||||
CHECK_FUNC( init_block[4], "LdrInitializeThunk" );
|
||||
CHECK_FUNC( init_block[5], "KiUserExceptionDispatcher" );
|
||||
CHECK_FUNC( init_block[6], "KiUserApcDispatcher" );
|
||||
CHECK_FUNC( init_block[7], "KiUserCallbackDispatcher" );
|
||||
CHECK_FUNC( init_block[8], "ExpInterlockedPopEntrySListFault" );
|
||||
CHECK_FUNC( init_block[9], "ExpInterlockedPopEntrySListResume" );
|
||||
CHECK_FUNC( init_block[10], "ExpInterlockedPopEntrySListEnd" );
|
||||
CHECK_FUNC( init_block[11], "RtlUserThreadStart" );
|
||||
CHECK_FUNC( init_block[12], "RtlpQueryProcessDebugInformationRemote" );
|
||||
ok( init_block[13] == (ULONG_PTR)ntdll, "got %p for ntdll %p\n",
|
||||
(void *)(ULONG_PTR)init_block[13], ntdll );
|
||||
CHECK_FUNC( init_block[14], "LdrSystemDllInitBlock" );
|
||||
size = 15 * sizeof(*init_block);
|
||||
break;
|
||||
case 0xe0: /* win10 1809 */
|
||||
case 0xf0: /* win10 2004 */
|
||||
block64 = ptr;
|
||||
CHECK_FUNC( block64[3], "LdrInitializeThunk" );
|
||||
CHECK_FUNC( block64[4], "KiUserExceptionDispatcher" );
|
||||
CHECK_FUNC( block64[5], "KiUserApcDispatcher" );
|
||||
todo_wine CHECK_FUNC( block64[6], "KiUserCallbackDispatcher" );
|
||||
CHECK_FUNC( block64[7], "RtlUserThreadStart" );
|
||||
CHECK_FUNC( block64[8], "RtlpQueryProcessDebugInformationRemote" );
|
||||
todo_wine ok( block64[9] == (ULONG_PTR)ntdll, "got %p for ntdll %p\n",
|
||||
(void *)(ULONG_PTR)block64[9], ntdll );
|
||||
CHECK_FUNC( block64[10], "LdrSystemDllInitBlock" );
|
||||
CHECK_FUNC( block64[11], "RtlpFreezeTimeBias" );
|
||||
size = 12 * sizeof(*block64);
|
||||
break;
|
||||
default:
|
||||
ok( 0, "unknown init block %08x\n", init_block[0] );
|
||||
for (i = 0; i < 32; i++) trace("%04x: %08x\n", i, init_block[i]);
|
||||
break;
|
||||
}
|
||||
#undef CHECK_FUNC
|
||||
|
||||
if (size && (ptr64 = get_proc_address64( ntdll_module, "LdrSystemDllInitBlock" )))
|
||||
{
|
||||
DWORD buffer[64];
|
||||
HANDLE process = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() );
|
||||
NTSTATUS status = pNtWow64ReadVirtualMemory64( process, ptr64, buffer, size, NULL );
|
||||
ok( !status, "NtWow64ReadVirtualMemory64 failed %x\n", status );
|
||||
ok( !memcmp( buffer, init_block, size ), "wrong 64-bit init block\n" );
|
||||
NtClose( process );
|
||||
}
|
||||
}
|
||||
else todo_wine win_skip( "LdrSystemDllInitBlock not supported\n" );
|
||||
}
|
||||
|
||||
static void test_cpu_area(void)
|
||||
{
|
||||
TEB64 *teb64 = (TEB64 *)NtCurrentTeb()->GdiBatchCount;
|
||||
|
@ -997,6 +1112,7 @@ START_TEST(wow64)
|
|||
#ifndef _WIN64
|
||||
test_nt_wow64();
|
||||
test_modules();
|
||||
test_init_block();
|
||||
#endif
|
||||
test_cpu_area();
|
||||
}
|
||||
|
|
|
@ -110,6 +110,7 @@ NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) = NULL
|
|||
void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) = NULL;
|
||||
void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) = NULL;
|
||||
void (WINAPI *p__wine_ctrl_routine)(void*);
|
||||
SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock = NULL;
|
||||
|
||||
static NTSTATUS (CDECL *p__wine_set_unix_funcs)( int version, const struct unix_funcs *funcs );
|
||||
|
||||
|
@ -832,6 +833,7 @@ static void load_ntdll_functions( HMODULE module )
|
|||
GET_FUNC( KiUserExceptionDispatcher );
|
||||
GET_FUNC( KiUserApcDispatcher );
|
||||
GET_FUNC( LdrInitializeThunk );
|
||||
GET_FUNC( LdrSystemDllInitBlock );
|
||||
GET_FUNC( RtlUserThreadStart );
|
||||
GET_FUNC( __wine_ctrl_routine );
|
||||
GET_FUNC( __wine_set_unix_funcs );
|
||||
|
@ -847,6 +849,31 @@ static void load_ntdll_functions( HMODULE module )
|
|||
#undef SET_PTR
|
||||
}
|
||||
|
||||
static void load_ntdll_wow64_functions( HMODULE module )
|
||||
{
|
||||
const IMAGE_EXPORT_DIRECTORY *exports;
|
||||
|
||||
exports = get_module_data_dir( module, IMAGE_FILE_EXPORT_DIRECTORY, NULL );
|
||||
assert( exports );
|
||||
|
||||
pLdrSystemDllInitBlock->ntdll_handle = (ULONG_PTR)module;
|
||||
|
||||
#define GET_FUNC(name) pLdrSystemDllInitBlock->p##name = find_named_export( module, exports, #name )
|
||||
GET_FUNC( KiUserApcDispatcher );
|
||||
GET_FUNC( KiUserCallbackDispatcher );
|
||||
GET_FUNC( KiUserExceptionDispatcher );
|
||||
GET_FUNC( LdrInitializeThunk );
|
||||
GET_FUNC( LdrSystemDllInitBlock );
|
||||
GET_FUNC( RtlUserThreadStart );
|
||||
GET_FUNC( RtlpFreezeTimeBias );
|
||||
GET_FUNC( RtlpQueryProcessDebugInformationRemote );
|
||||
#undef GET_FUNC
|
||||
|
||||
/* also set the 32-bit LdrSystemDllInitBlock */
|
||||
memcpy( (void *)(ULONG_PTR)pLdrSystemDllInitBlock->pLdrSystemDllInitBlock,
|
||||
pLdrSystemDllInitBlock, sizeof(*pLdrSystemDllInitBlock) );
|
||||
}
|
||||
|
||||
/* reimplementation of LdrProcessRelocationBlock */
|
||||
static const IMAGE_BASE_RELOCATION *process_relocation_block( void *module, const IMAGE_BASE_RELOCATION *rel,
|
||||
INT_PTR delta )
|
||||
|
@ -1781,6 +1808,7 @@ static void load_wow64_ntdll( USHORT machine )
|
|||
relocate_ntdll( module );
|
||||
/* fall through */
|
||||
case STATUS_SUCCESS:
|
||||
load_ntdll_wow64_functions( module );
|
||||
TRACE("loaded %s at %p\n", debugstr_w(path), module );
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -93,6 +93,8 @@ extern NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*)
|
|||
extern void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *p__wine_ctrl_routine)(void *) DECLSPEC_HIDDEN;
|
||||
extern SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock DECLSPEC_HIDDEN;
|
||||
|
||||
extern NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -3713,6 +3713,26 @@ typedef struct _WOW64_CPU_AREA_INFO
|
|||
USHORT Machine;
|
||||
} WOW64_CPU_AREA_INFO, *PWOW64_CPU_AREA_INFO;
|
||||
|
||||
#ifdef __WINESRC__
|
||||
/* undocumented layout of LdrSystemDllInitBlock */
|
||||
/* this varies across Windows version; we are using the win10-2004 layout */
|
||||
typedef struct
|
||||
{
|
||||
ULONG version;
|
||||
ULONG unknown1[3];
|
||||
ULONG64 unknown2;
|
||||
ULONG64 pLdrInitializeThunk;
|
||||
ULONG64 pKiUserExceptionDispatcher;
|
||||
ULONG64 pKiUserApcDispatcher;
|
||||
ULONG64 pKiUserCallbackDispatcher;
|
||||
ULONG64 pRtlUserThreadStart;
|
||||
ULONG64 pRtlpQueryProcessDebugInformationRemote;
|
||||
ULONG64 ntdll_handle;
|
||||
ULONG64 pLdrSystemDllInitBlock;
|
||||
ULONG64 pRtlpFreezeTimeBias;
|
||||
} SYSTEM_DLL_INIT_BLOCK;
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
* Function declarations
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue