Commit 3a32ea8e authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Add support for LdrSystemDllInitBlock.

parent 390d71b0
......@@ -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
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment