diff --git a/dlls/winecrt0/delay_load.c b/dlls/winecrt0/delay_load.c index 4ba840479d8..af14fce3668 100644 --- a/dlls/winecrt0/delay_load.c +++ b/dlls/winecrt0/delay_load.c @@ -24,49 +24,37 @@ #include "delayloadhandler.h" WINBASEAPI void *WINAPI DelayLoadFailureHook( LPCSTR name, LPCSTR function ); - -#ifdef __WINE_PE_BUILD - -extern IMAGE_DOS_HEADER __ImageBase; - WINBASEAPI void *WINAPI ResolveDelayLoadedAPI( void* base, const IMAGE_DELAYLOAD_DESCRIPTOR* desc, PDELAYLOAD_FAILURE_DLL_CALLBACK dllhook, PDELAYLOAD_FAILURE_SYSTEM_ROUTINE syshook, IMAGE_THUNK_DATA* addr, ULONG flags ); -FARPROC WINAPI __delayLoadHelper2( const IMAGE_DELAYLOAD_DESCRIPTOR *descr, IMAGE_THUNK_DATA *addr ) +static inline void *image_base(void) { - return ResolveDelayLoadedAPI( &__ImageBase, descr, NULL, DelayLoadFailureHook, addr, 0 ); +#ifdef __WINE_PE_BUILD + extern IMAGE_DOS_HEADER __ImageBase; + return (void *)&__ImageBase; +#else + extern IMAGE_NT_HEADERS __wine_spec_nt_header; + return (void *)((__wine_spec_nt_header.OptionalHeader.ImageBase + 0xffff) & ~0xffff); +#endif } -#else /* __WINE_PE_BUILD */ - -struct ImgDelayDescr +FARPROC WINAPI __delayLoadHelper2( const IMAGE_DELAYLOAD_DESCRIPTOR *descr, IMAGE_THUNK_DATA *addr ) { - DWORD_PTR grAttrs; - LPCSTR szName; - HMODULE *phmod; - IMAGE_THUNK_DATA *pIAT; - const IMAGE_THUNK_DATA *pINT; - const IMAGE_THUNK_DATA *pBoundIAT; - const IMAGE_THUNK_DATA *pUnloadIAT; - DWORD_PTR dwTimeStamp; -}; + return ResolveDelayLoadedAPI( image_base(), descr, NULL, DelayLoadFailureHook, addr, 0 ); +} -extern struct ImgDelayDescr __wine_spec_delay_imports[]; +#ifndef __WINE_PE_BUILD + +extern IMAGE_DELAYLOAD_DESCRIPTOR __wine_spec_delay_imports[]; FARPROC WINAPI DECLSPEC_HIDDEN __wine_spec_delay_load( unsigned int id ) { - struct ImgDelayDescr *descr = __wine_spec_delay_imports + HIWORD(id); - WORD func = LOWORD(id); - FARPROC proc; + const IMAGE_DELAYLOAD_DESCRIPTOR *descr = __wine_spec_delay_imports + HIWORD(id); + IMAGE_THUNK_DATA *thunk = (IMAGE_THUNK_DATA *)((char *)image_base() + descr->ImportAddressTableRVA); - if (!*descr->phmod) *descr->phmod = LoadLibraryA( descr->szName ); - if (!*descr->phmod || - !(proc = GetProcAddress( *descr->phmod, (LPCSTR)descr->pINT[func].u1.Function ))) - proc = DelayLoadFailureHook( descr->szName, (LPCSTR)descr->pINT[func].u1.Function ); - descr->pIAT[func].u1.Function = (ULONG_PTR)proc; - return proc; + return __delayLoadHelper2( descr, thunk + LOWORD(id) ); } #endif /* __WINE_PE_BUILD */ diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index f501cca8f84..3b5ba0fff2a 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -303,6 +303,7 @@ extern void read_undef_symbols( DLLSPEC *spec, struct strarray files ); extern void resolve_imports( DLLSPEC *spec ); extern int is_undefined( const char *name ); extern int has_imports(void); +extern int has_delay_imports(void); extern void output_get_pc_thunk(void); extern void output_module( DLLSPEC *spec ); extern void output_stubs( DLLSPEC *spec ); diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 57adbef0d23..4c77c6cc60e 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -821,6 +821,12 @@ int has_imports(void) return !list_empty( &dll_imports ); } +/* check if we need a delayed import directory */ +int has_delay_imports(void) +{ + return !list_empty( &dll_delayed ); +} + /* output the import table of a Win32 module */ static void output_immediate_imports(void) { @@ -928,7 +934,7 @@ static void output_immediate_import_thunks(void) /* output the delayed import table of a Win32 module */ static void output_delayed_imports( const DLLSPEC *spec ) { - int j, mod; + int j, iat_pos, int_pos, mod_pos; struct import *import; if (list_empty( &dll_delayed )) return; @@ -936,36 +942,28 @@ static void output_delayed_imports( const DLLSPEC *spec ) output( "\n/* delayed imports */\n\n" ); output( "\t.data\n" ); output( "\t.align %d\n", get_alignment(get_ptr_size()) ); + output( ".L__wine_spec_delay_imports:\n" ); output( "%s\n", asm_globl("__wine_spec_delay_imports") ); /* list of dlls */ - j = mod = 0; + iat_pos = int_pos = mod_pos = 0; LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry ) { - output( "\t%s 0\n", get_asm_ptr_keyword() ); /* grAttrs */ - output( "\t%s .L__wine_delay_name_%s\n", /* szName */ - get_asm_ptr_keyword(), import->c_name ); - output( "\t%s .L__wine_delay_modules+%d\n", /* phmod */ - get_asm_ptr_keyword(), mod * get_ptr_size() ); - output( "\t%s .L__wine_delay_IAT+%d\n", /* pIAT */ - get_asm_ptr_keyword(), j * get_ptr_size() ); - output( "\t%s .L__wine_delay_INT+%d\n", /* pINT */ - get_asm_ptr_keyword(), j * get_ptr_size() ); - output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pBoundIAT */ - output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pUnloadIAT */ - output( "\t%s 0\n", get_asm_ptr_keyword() ); /* dwTimeStamp */ - j += import->nb_imports; - mod++; + output( "\t.long 1\n" ); /* Attributes */ + output_rva( ".L__wine_delay_name_%s", import->c_name ); /* DllNameRVA */ + output_rva( ".L__wine_delay_modules+%d", mod_pos ); /* ModuleHandleRVA */ + output_rva( ".L__wine_delay_IAT+%d", iat_pos ); /* ImportAddressTableRVA */ + output_rva( ".L__wine_delay_INT+%d", int_pos ); /* ImportNameTableRVA */ + output( "\t.long 0\n" ); /* BoundImportAddressTableRVA */ + output( "\t.long 0\n" ); /* UnloadInformationTableRVA */ + output( "\t.long 0\n" ); /* TimeDateStamp */ + iat_pos += import->nb_imports * get_ptr_size(); + int_pos += (import->nb_imports + 1) * get_ptr_size(); + mod_pos += get_ptr_size(); } - output( "\t%s 0\n", get_asm_ptr_keyword() ); /* grAttrs */ - output( "\t%s 0\n", get_asm_ptr_keyword() ); /* szName */ - output( "\t%s 0\n", get_asm_ptr_keyword() ); /* phmod */ - output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pIAT */ - output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pINT */ - output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pBoundIAT */ - output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pUnloadIAT */ - output( "\t%s 0\n", get_asm_ptr_keyword() ); /* dwTimeStamp */ + output( "\t.long 0,0,0,0,0,0,0,0\n" ); + output( ".L__wine_spec_delay_imports_end:\n" ); output( "\n.L__wine_delay_IAT:\n" ); LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry ) @@ -986,12 +984,10 @@ static void output_delayed_imports( const DLLSPEC *spec ) for (j = 0; j < import->nb_imports; j++) { struct import_func *func = &import->imports[j]; - if (!func->name) - output( "\t%s %d\n", get_asm_ptr_keyword(), func->ordinal ); - else - output( "\t%s .L__wine_delay_data_%s_%s\n", - get_asm_ptr_keyword(), import->c_name, func->name ); + output_thunk_rva( func->name ? -1 : func->ordinal, + ".L__wine_delay_data_%s_%s", import->c_name, func->name ); } + output( "\t%s 0\n", get_asm_ptr_keyword() ); } output( "\n.L__wine_delay_modules:\n" ); @@ -1012,7 +1008,9 @@ static void output_delayed_imports( const DLLSPEC *spec ) { struct import_func *func = &import->imports[j]; if (!func->name) continue; + output( "\t.align %d\n", get_alignment(2) ); output( ".L__wine_delay_data_%s_%s:\n", import->c_name, func->name ); + output( "\t.short %d\n", func->hint ); output( "\t%s \"%s\"\n", get_asm_string_keyword(), func->name ); } } diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index a4a95f09c43..296d15c5d3b 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -735,6 +735,8 @@ void output_module( DLLSPEC *spec ) data_dirs[1] = ".L__wine_spec_imports"; /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */ if (spec->nb_resources) data_dirs[2] = ".L__wine_spec_resources"; /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */ + if (has_delay_imports()) + data_dirs[13] = ".L__wine_spec_delay_imports"; /* DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT] */ output_data_directories( data_dirs );