- implementation of LdrLoadDll out of loader/module.c
- in impacted functions, ensure that we only use ntdll functions - for internal loading, start using NTDLL style for error reporting - making use of new LdrLoadDll
This commit is contained in:
parent
4550b8b7cf
commit
32872b1a57
|
@ -44,6 +44,48 @@ static WINE_EXCEPTION_FILTER(page_fault)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* MODULE_AllocModRef
|
||||||
|
*
|
||||||
|
* Allocate a WINE_MODREF structure and add it to the process list
|
||||||
|
* NOTE: Assumes that the process critical section is held!
|
||||||
|
*/
|
||||||
|
WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename )
|
||||||
|
{
|
||||||
|
WINE_MODREF *wm;
|
||||||
|
|
||||||
|
DWORD long_len = strlen( filename );
|
||||||
|
DWORD short_len = GetShortPathNameA( filename, NULL, 0 );
|
||||||
|
|
||||||
|
if ((wm = RtlAllocateHeap( ntdll_get_process_heap(), HEAP_ZERO_MEMORY,
|
||||||
|
sizeof(*wm) + long_len + short_len + 1 )))
|
||||||
|
{
|
||||||
|
wm->module = hModule;
|
||||||
|
wm->tlsindex = -1;
|
||||||
|
|
||||||
|
wm->filename = wm->data;
|
||||||
|
memcpy( wm->filename, filename, long_len + 1 );
|
||||||
|
if ((wm->modname = strrchr( wm->filename, '\\' ))) wm->modname++;
|
||||||
|
else wm->modname = wm->filename;
|
||||||
|
|
||||||
|
wm->short_filename = wm->filename + long_len + 1;
|
||||||
|
GetShortPathNameA( wm->filename, wm->short_filename, short_len + 1 );
|
||||||
|
if ((wm->short_modname = strrchr( wm->short_filename, '\\' ))) wm->short_modname++;
|
||||||
|
else wm->short_modname = wm->short_filename;
|
||||||
|
|
||||||
|
wm->next = MODULE_modref_list;
|
||||||
|
if (wm->next) wm->next->prev = wm;
|
||||||
|
MODULE_modref_list = wm;
|
||||||
|
|
||||||
|
if (!(RtlImageNtHeader(hModule)->FileHeader.Characteristics & IMAGE_FILE_DLL))
|
||||||
|
{
|
||||||
|
if (!exe_modref) exe_modref = wm;
|
||||||
|
else FIXME( "Trying to load second .EXE file: %s\n", filename );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wm;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* LdrDisableThreadCalloutsForDll (NTDLL.@)
|
* LdrDisableThreadCalloutsForDll (NTDLL.@)
|
||||||
*
|
*
|
||||||
|
@ -182,6 +224,245 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE base, PANSI_STRING name, ULONG or
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* allocate_lib_dir
|
||||||
|
*
|
||||||
|
* helper for MODULE_LoadLibraryExA. Allocate space to hold the directory
|
||||||
|
* portion of the provided name and put the name in it.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static LPCSTR allocate_lib_dir(LPCSTR libname)
|
||||||
|
{
|
||||||
|
LPCSTR p, pmax;
|
||||||
|
LPSTR result;
|
||||||
|
int length;
|
||||||
|
|
||||||
|
pmax = libname;
|
||||||
|
if ((p = strrchr( pmax, '\\' ))) pmax = p + 1;
|
||||||
|
if ((p = strrchr( pmax, '/' ))) pmax = p + 1; /* Naughty. MSDN says don't */
|
||||||
|
if (pmax == libname && pmax[0] && pmax[1] == ':') pmax += 2;
|
||||||
|
|
||||||
|
length = pmax - libname;
|
||||||
|
|
||||||
|
result = RtlAllocateHeap (ntdll_get_process_heap(), 0, length+1);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
strncpy (result, libname, length);
|
||||||
|
result [length] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* MODULE_LoadLibraryExA (internal)
|
||||||
|
*
|
||||||
|
* Load a PE style module according to the load order.
|
||||||
|
*
|
||||||
|
* libdir is used to support LOAD_WITH_ALTERED_SEARCH_PATH during the recursion
|
||||||
|
* on this function. When first called from LoadLibraryExA it will be
|
||||||
|
* NULL but thereafter it may point to a buffer containing the path
|
||||||
|
* portion of the library name. Note that the recursion all occurs
|
||||||
|
* within a Critical section (see LoadLibraryExA) so the use of a
|
||||||
|
* static is acceptable.
|
||||||
|
* (We have to use a static variable at some point anyway, to pass the
|
||||||
|
* information from BUILTIN32_dlopen through dlopen and the builtin's
|
||||||
|
* init function into load_library).
|
||||||
|
* allocated_libdir is TRUE in the stack frame that allocated libdir
|
||||||
|
*/
|
||||||
|
NTSTATUS MODULE_LoadLibraryExA( LPCSTR libname, DWORD flags, WINE_MODREF** pwm)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
enum loadorder_type loadorder[LOADORDER_NTYPES];
|
||||||
|
LPSTR filename;
|
||||||
|
const char *filetype = "";
|
||||||
|
DWORD found;
|
||||||
|
BOOL allocated_libdir = FALSE;
|
||||||
|
static LPCSTR libdir = NULL; /* See above */
|
||||||
|
NTSTATUS nts = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
*pwm = NULL;
|
||||||
|
if ( !libname ) return STATUS_DLL_NOT_FOUND; /* FIXME ? */
|
||||||
|
|
||||||
|
filename = RtlAllocateHeap ( ntdll_get_process_heap(), 0, MAX_PATH + 1 );
|
||||||
|
if ( !filename ) return STATUS_NO_MEMORY;
|
||||||
|
*filename = 0; /* Just in case we don't set it before goto error */
|
||||||
|
|
||||||
|
RtlEnterCriticalSection( &loader_section );
|
||||||
|
|
||||||
|
if ((flags & LOAD_WITH_ALTERED_SEARCH_PATH) && FILE_contains_path(libname))
|
||||||
|
{
|
||||||
|
if (!(libdir = allocate_lib_dir(libname)))
|
||||||
|
{
|
||||||
|
nts = STATUS_NO_MEMORY;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
allocated_libdir = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!libdir || allocated_libdir)
|
||||||
|
found = SearchPathA(NULL, libname, ".dll", MAX_PATH, filename, NULL);
|
||||||
|
else
|
||||||
|
found = DIR_SearchAlternatePath(libdir, libname, ".dll", MAX_PATH, filename, NULL);
|
||||||
|
|
||||||
|
/* build the modules filename */
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
if (!MODULE_GetBuiltinPath( libname, ".dll", filename, MAX_PATH ))
|
||||||
|
{
|
||||||
|
nts = STATUS_INTERNAL_ERROR;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for already loaded module */
|
||||||
|
if (!(*pwm = MODULE_FindModule(filename)) && !FILE_contains_path(libname))
|
||||||
|
{
|
||||||
|
LPSTR fn = RtlAllocateHeap ( ntdll_get_process_heap(), 0, MAX_PATH + 1 );
|
||||||
|
if (fn)
|
||||||
|
{
|
||||||
|
/* since the default loading mechanism uses a more detailed algorithm
|
||||||
|
* than SearchPath (like using PATH, which can even be modified between
|
||||||
|
* two attempts of loading the same DLL), the look-up above (with
|
||||||
|
* SearchPath) can have put the file in system directory, whereas it
|
||||||
|
* has already been loaded but with a different path. So do a specific
|
||||||
|
* look-up with filename (without any path)
|
||||||
|
*/
|
||||||
|
strcpy ( fn, libname );
|
||||||
|
/* if the filename doesn't have an extension append .DLL */
|
||||||
|
if (!strrchr( fn, '.')) strcat( fn, ".dll" );
|
||||||
|
if ((*pwm = MODULE_FindModule( fn )) != NULL)
|
||||||
|
strcpy( filename, fn );
|
||||||
|
RtlFreeHeap( ntdll_get_process_heap(), 0, fn );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*pwm)
|
||||||
|
{
|
||||||
|
(*pwm)->refCount++;
|
||||||
|
|
||||||
|
if (((*pwm)->flags & WINE_MODREF_DONT_RESOLVE_REFS) &&
|
||||||
|
!(flags & DONT_RESOLVE_DLL_REFERENCES))
|
||||||
|
{
|
||||||
|
(*pwm)->flags &= ~WINE_MODREF_DONT_RESOLVE_REFS;
|
||||||
|
PE_fixup_imports( *pwm );
|
||||||
|
}
|
||||||
|
TRACE("Already loaded module '%s' at %p, count=%d\n", filename, (*pwm)->module, (*pwm)->refCount);
|
||||||
|
if (allocated_libdir)
|
||||||
|
{
|
||||||
|
RtlFreeHeap( ntdll_get_process_heap(), 0, (LPSTR)libdir );
|
||||||
|
libdir = NULL;
|
||||||
|
}
|
||||||
|
RtlLeaveCriticalSection( &loader_section );
|
||||||
|
RtlFreeHeap( ntdll_get_process_heap(), 0, filename );
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_GetLoadOrder( loadorder, filename, TRUE);
|
||||||
|
|
||||||
|
for (i = 0; i < LOADORDER_NTYPES; i++)
|
||||||
|
{
|
||||||
|
if (loadorder[i] == LOADORDER_INVALID) break;
|
||||||
|
|
||||||
|
switch (loadorder[i])
|
||||||
|
{
|
||||||
|
case LOADORDER_DLL:
|
||||||
|
TRACE("Trying native dll '%s'\n", filename);
|
||||||
|
nts = PE_LoadLibraryExA(filename, flags, pwm);
|
||||||
|
filetype = "native";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOADORDER_BI:
|
||||||
|
TRACE("Trying built-in '%s'\n", filename);
|
||||||
|
nts = BUILTIN32_LoadLibraryExA(filename, flags, pwm);
|
||||||
|
filetype = "builtin";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
nts = STATUS_INTERNAL_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nts == STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Initialize DLL just loaded */
|
||||||
|
TRACE("Loaded module '%s' at %p\n", filename, (*pwm)->module);
|
||||||
|
if (!TRACE_ON(module))
|
||||||
|
TRACE_(loaddll)("Loaded module '%s' : %s\n", filename, filetype);
|
||||||
|
/* Set the refCount here so that an attach failure will */
|
||||||
|
/* decrement the dependencies through the MODULE_FreeLibrary call. */
|
||||||
|
(*pwm)->refCount = 1;
|
||||||
|
|
||||||
|
if (allocated_libdir)
|
||||||
|
{
|
||||||
|
RtlFreeHeap( ntdll_get_process_heap(), 0, (LPSTR)libdir );
|
||||||
|
libdir = NULL;
|
||||||
|
}
|
||||||
|
RtlLeaveCriticalSection( &loader_section );
|
||||||
|
RtlFreeHeap( ntdll_get_process_heap(), 0, filename );
|
||||||
|
return nts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nts != STATUS_NO_SUCH_FILE)
|
||||||
|
{
|
||||||
|
WARN("Loading of %s DLL %s failed (status %ld).\n",
|
||||||
|
filetype, filename, nts);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (allocated_libdir)
|
||||||
|
{
|
||||||
|
RtlFreeHeap( ntdll_get_process_heap(), 0, (LPSTR)libdir );
|
||||||
|
libdir = NULL;
|
||||||
|
}
|
||||||
|
RtlLeaveCriticalSection( &loader_section );
|
||||||
|
WARN("Failed to load module '%s'; status=%ld\n", filename, nts);
|
||||||
|
RtlFreeHeap( ntdll_get_process_heap(), 0, filename );
|
||||||
|
return nts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* LdrLoadDll (NTDLL.@)
|
||||||
|
*/
|
||||||
|
NTSTATUS WINAPI LdrLoadDll(LPCWSTR path_name, DWORD flags, PUNICODE_STRING libname, HMODULE* hModule)
|
||||||
|
{
|
||||||
|
WINE_MODREF *wm;
|
||||||
|
NTSTATUS nts = STATUS_SUCCESS;
|
||||||
|
STRING str;
|
||||||
|
|
||||||
|
RtlUnicodeStringToAnsiString(&str, libname, TRUE);
|
||||||
|
|
||||||
|
RtlEnterCriticalSection( &loader_section );
|
||||||
|
|
||||||
|
switch (nts = MODULE_LoadLibraryExA( str.Buffer, flags, &wm ))
|
||||||
|
{
|
||||||
|
case STATUS_SUCCESS:
|
||||||
|
if ( !MODULE_DllProcessAttach( wm, NULL ) )
|
||||||
|
{
|
||||||
|
WARN_(module)("Attach failed for module '%s'.\n", str.Buffer);
|
||||||
|
LdrUnloadDll(wm->module);
|
||||||
|
nts = STATUS_DLL_INIT_FAILED;
|
||||||
|
wm = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STATUS_NO_SUCH_FILE:
|
||||||
|
nts = STATUS_DLL_NOT_FOUND;
|
||||||
|
break;
|
||||||
|
default: /* keep error code as it is (memory...) */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*hModule = (wm) ? wm->module : NULL;
|
||||||
|
|
||||||
|
RtlLeaveCriticalSection( &loader_section );
|
||||||
|
|
||||||
|
RtlFreeAnsiString(&str);
|
||||||
|
|
||||||
|
return nts;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* LdrShutdownProcess (NTDLL.@)
|
* LdrShutdownProcess (NTDLL.@)
|
||||||
*
|
*
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
@ stdcall LdrGetDllHandle(long long ptr ptr) LdrGetDllHandle
|
@ stdcall LdrGetDllHandle(long long ptr ptr) LdrGetDllHandle
|
||||||
@ stdcall LdrGetProcedureAddress(ptr ptr long ptr) LdrGetProcedureAddress
|
@ stdcall LdrGetProcedureAddress(ptr ptr long ptr) LdrGetProcedureAddress
|
||||||
@ stub LdrInitializeThunk
|
@ stub LdrInitializeThunk
|
||||||
@ stub LdrLoadDll
|
@ stdcall LdrLoadDll(wstr long ptr ptr) LdrLoadDll
|
||||||
@ stub LdrProcessRelocationBlock
|
@ stub LdrProcessRelocationBlock
|
||||||
@ stub LdrQueryImageFileExecutionOptions
|
@ stub LdrQueryImageFileExecutionOptions
|
||||||
@ stub LdrQueryProcessModuleInformation
|
@ stub LdrQueryProcessModuleInformation
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "winnt.h"
|
#include "winnt.h"
|
||||||
#include "winternl.h"
|
#include "winternl.h"
|
||||||
|
#include "module.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
|
||||||
/* debug helper */
|
/* debug helper */
|
||||||
|
@ -29,11 +30,12 @@ extern void dump_ObjectAttributes (const OBJECT_ATTRIBUTES *ObjectAttributes);
|
||||||
|
|
||||||
/* module handling */
|
/* module handling */
|
||||||
extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, int hint, BOOL snoop );
|
extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, int hint, BOOL snoop );
|
||||||
|
extern WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename );
|
||||||
|
extern NTSTATUS MODULE_LoadLibraryExA( LPCSTR libname, DWORD flags, WINE_MODREF** );
|
||||||
|
|
||||||
static inline HANDLE ntdll_get_process_heap(void)
|
static inline HANDLE ntdll_get_process_heap(void)
|
||||||
{
|
{
|
||||||
HANDLE *pdb = (HANDLE *)NtCurrentTeb()->process;
|
HANDLE *pdb = (HANDLE *)NtCurrentTeb()->process;
|
||||||
return pdb[0x18 / sizeof(HANDLE)]; /* get dword at offset 0x18 in pdb */
|
return pdb[0x18 / sizeof(HANDLE)]; /* get dword at offset 0x18 in pdb */
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "wine/windef16.h"
|
#include "wine/windef16.h"
|
||||||
#include "wine/winbase16.h"
|
#include "wine/winbase16.h"
|
||||||
|
#include "winternl.h"
|
||||||
|
|
||||||
/* In-memory module structure. See 'Windows Internals' p. 219 */
|
/* In-memory module structure. See 'Windows Internals' p. 219 */
|
||||||
typedef struct _NE_MODULE
|
typedef struct _NE_MODULE
|
||||||
|
@ -193,11 +194,9 @@ enum binary_type
|
||||||
};
|
};
|
||||||
|
|
||||||
/* module.c */
|
/* module.c */
|
||||||
extern WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename );
|
|
||||||
extern BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved );
|
extern BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved );
|
||||||
extern void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved );
|
extern void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved );
|
||||||
extern void MODULE_DllThreadAttach( LPVOID lpReserved );
|
extern void MODULE_DllThreadAttach( LPVOID lpReserved );
|
||||||
extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HANDLE hfile, DWORD flags );
|
|
||||||
extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
|
extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
|
||||||
extern HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
|
extern HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
|
||||||
extern enum binary_type MODULE_GetBinaryType( HANDLE hfile );
|
extern enum binary_type MODULE_GetBinaryType( HANDLE hfile );
|
||||||
|
@ -254,7 +253,7 @@ extern DWORD PE_SizeofResource(HRSRC);
|
||||||
extern HGLOBAL PE_LoadResource(HMODULE,HRSRC);
|
extern HGLOBAL PE_LoadResource(HMODULE,HRSRC);
|
||||||
|
|
||||||
/* loader/pe_image.c */
|
/* loader/pe_image.c */
|
||||||
extern WINE_MODREF *PE_LoadLibraryExA(LPCSTR, DWORD);
|
extern NTSTATUS PE_LoadLibraryExA(LPCSTR, DWORD, WINE_MODREF**);
|
||||||
extern HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename, DWORD flags );
|
extern HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename, DWORD flags );
|
||||||
extern WINE_MODREF *PE_CreateModule( HMODULE hModule, LPCSTR filename,
|
extern WINE_MODREF *PE_CreateModule( HMODULE hModule, LPCSTR filename,
|
||||||
DWORD flags, HANDLE hFile, BOOL builtin );
|
DWORD flags, HANDLE hFile, BOOL builtin );
|
||||||
|
@ -268,7 +267,7 @@ extern void MODULE_GetLoadOrder( enum loadorder_type plo[], const char *path, BO
|
||||||
extern void MODULE_AddLoadOrderOption( const char *option );
|
extern void MODULE_AddLoadOrderOption( const char *option );
|
||||||
|
|
||||||
/* relay32/builtin.c */
|
/* relay32/builtin.c */
|
||||||
extern WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR name, DWORD flags);
|
extern NTSTATUS BUILTIN32_LoadLibraryExA(LPCSTR name, DWORD flags, WINE_MODREF**);
|
||||||
extern HMODULE BUILTIN32_LoadExeModule( HMODULE main );
|
extern HMODULE BUILTIN32_LoadExeModule( HMODULE main );
|
||||||
extern void *BUILTIN32_dlopen( const char *name );
|
extern void *BUILTIN32_dlopen( const char *name );
|
||||||
extern int BUILTIN32_dlclose( void *handle );
|
extern int BUILTIN32_dlclose( void *handle );
|
||||||
|
|
|
@ -1141,7 +1141,7 @@ typedef struct _LDR_MODULE
|
||||||
LIST_ENTRY InMemoryOrderModuleList;
|
LIST_ENTRY InMemoryOrderModuleList;
|
||||||
LIST_ENTRY InInitializationOrderModuleList;
|
LIST_ENTRY InInitializationOrderModuleList;
|
||||||
void* BaseAddress;
|
void* BaseAddress;
|
||||||
ULONG EntryPoint;
|
void* EntryPoint;
|
||||||
ULONG SizeOfImage;
|
ULONG SizeOfImage;
|
||||||
UNICODE_STRING FullDllName;
|
UNICODE_STRING FullDllName;
|
||||||
UNICODE_STRING BaseDllName;
|
UNICODE_STRING BaseDllName;
|
||||||
|
@ -1187,7 +1187,7 @@ NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE);
|
||||||
NTSTATUS WINAPI LdrFindEntryForAddress(void*, PLDR_MODULE*);
|
NTSTATUS WINAPI LdrFindEntryForAddress(void*, PLDR_MODULE*);
|
||||||
NTSTATUS WINAPI LdrGetDllHandle(ULONG, ULONG, PUNICODE_STRING, HMODULE*);
|
NTSTATUS WINAPI LdrGetDllHandle(ULONG, ULONG, PUNICODE_STRING, HMODULE*);
|
||||||
NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, PANSI_STRING, ULONG, void**);
|
NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, PANSI_STRING, ULONG, void**);
|
||||||
NTSTATUS WINAPI LdrLoadDll(LPCSTR, DWORD, PUNICODE_STRING, HMODULE*);
|
NTSTATUS WINAPI LdrLoadDll(LPCWSTR, DWORD, PUNICODE_STRING, HMODULE*);
|
||||||
NTSTATUS WINAPI LdrShutdownThread(void);
|
NTSTATUS WINAPI LdrShutdownThread(void);
|
||||||
NTSTATUS WINAPI LdrShutdownProcess(void);
|
NTSTATUS WINAPI LdrShutdownProcess(void);
|
||||||
NTSTATUS WINAPI LdrUnloadDll(HMODULE);
|
NTSTATUS WINAPI LdrUnloadDll(HMODULE);
|
||||||
|
|
418
loader/module.c
418
loader/module.c
|
@ -95,48 +95,6 @@ WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod )
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* MODULE_AllocModRef
|
|
||||||
*
|
|
||||||
* Allocate a WINE_MODREF structure and add it to the process list
|
|
||||||
* NOTE: Assumes that the process critical section is held!
|
|
||||||
*/
|
|
||||||
WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename )
|
|
||||||
{
|
|
||||||
WINE_MODREF *wm;
|
|
||||||
|
|
||||||
DWORD long_len = strlen( filename );
|
|
||||||
DWORD short_len = GetShortPathNameA( filename, NULL, 0 );
|
|
||||||
|
|
||||||
if ((wm = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
||||||
sizeof(*wm) + long_len + short_len + 1 )))
|
|
||||||
{
|
|
||||||
wm->module = hModule;
|
|
||||||
wm->tlsindex = -1;
|
|
||||||
|
|
||||||
wm->filename = wm->data;
|
|
||||||
memcpy( wm->filename, filename, long_len + 1 );
|
|
||||||
if ((wm->modname = strrchr( wm->filename, '\\' ))) wm->modname++;
|
|
||||||
else wm->modname = wm->filename;
|
|
||||||
|
|
||||||
wm->short_filename = wm->filename + long_len + 1;
|
|
||||||
GetShortPathNameA( wm->filename, wm->short_filename, short_len + 1 );
|
|
||||||
if ((wm->short_modname = strrchr( wm->short_filename, '\\' ))) wm->short_modname++;
|
|
||||||
else wm->short_modname = wm->short_filename;
|
|
||||||
|
|
||||||
wm->next = MODULE_modref_list;
|
|
||||||
if (wm->next) wm->next->prev = wm;
|
|
||||||
MODULE_modref_list = wm;
|
|
||||||
|
|
||||||
if (!(RtlImageNtHeader(hModule)->FileHeader.Characteristics & IMAGE_FILE_DLL))
|
|
||||||
{
|
|
||||||
if (!exe_modref) exe_modref = wm;
|
|
||||||
else FIXME( "Trying to load second .EXE file: %s\n", filename );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return wm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* MODULE_InitDLL
|
* MODULE_InitDLL
|
||||||
*/
|
*/
|
||||||
|
@ -1024,277 +982,146 @@ DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName, DWORD size
|
||||||
return strlenW(lpFileName);
|
return strlenW(lpFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
/***********************************************************************
|
* load_library_as_datafile
|
||||||
* LoadLibraryExA (KERNEL32.@)
|
|
||||||
*/
|
|
||||||
HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
|
|
||||||
{
|
|
||||||
WINE_MODREF *wm;
|
|
||||||
|
|
||||||
if(!libname)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & LOAD_LIBRARY_AS_DATAFILE)
|
|
||||||
{
|
|
||||||
char filename[256];
|
|
||||||
HMODULE hmod = 0;
|
|
||||||
|
|
||||||
/* This method allows searching for the 'native' libraries only */
|
|
||||||
if (SearchPathA( NULL, libname, ".dll", sizeof(filename), filename, NULL ))
|
|
||||||
{
|
|
||||||
/* FIXME: maybe we should use the hfile parameter instead */
|
|
||||||
HANDLE hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ,
|
|
||||||
NULL, OPEN_EXISTING, 0, 0 );
|
|
||||||
if (hFile != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
HANDLE mapping;
|
|
||||||
switch (MODULE_GetBinaryType( hFile ))
|
|
||||||
{
|
|
||||||
case BINARY_PE_EXE:
|
|
||||||
case BINARY_PE_DLL:
|
|
||||||
mapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
|
|
||||||
if (mapping)
|
|
||||||
{
|
|
||||||
hmod = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
|
|
||||||
CloseHandle( mapping );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
CloseHandle( hFile );
|
|
||||||
}
|
|
||||||
if (hmod) return (HMODULE)((ULONG_PTR)hmod + 1);
|
|
||||||
}
|
|
||||||
flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
|
|
||||||
/* Fallback to normal behaviour */
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlEnterCriticalSection( &loader_section );
|
|
||||||
|
|
||||||
wm = MODULE_LoadLibraryExA( libname, hfile, flags );
|
|
||||||
if ( wm )
|
|
||||||
{
|
|
||||||
if ( !MODULE_DllProcessAttach( wm, NULL ) )
|
|
||||||
{
|
|
||||||
WARN_(module)("Attach failed for module '%s'.\n", libname);
|
|
||||||
LdrUnloadDll(wm->module);
|
|
||||||
SetLastError(ERROR_DLL_INIT_FAILED);
|
|
||||||
wm = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlLeaveCriticalSection( &loader_section );
|
|
||||||
return wm ? wm->module : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* allocate_lib_dir
|
|
||||||
*
|
*
|
||||||
* helper for MODULE_LoadLibraryExA. Allocate space to hold the directory
|
|
||||||
* portion of the provided name and put the name in it.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static LPCSTR allocate_lib_dir(LPCSTR libname)
|
static BOOL load_library_as_datafile(const void* name, BOOL unicode, HMODULE* hmod)
|
||||||
{
|
{
|
||||||
LPCSTR p, pmax;
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||||||
LPSTR result;
|
HANDLE mapping;
|
||||||
int length;
|
|
||||||
|
|
||||||
pmax = libname;
|
*hmod = 0;
|
||||||
if ((p = strrchr( pmax, '\\' ))) pmax = p + 1;
|
|
||||||
if ((p = strrchr( pmax, '/' ))) pmax = p + 1; /* Naughty. MSDN says don't */
|
|
||||||
if (pmax == libname && pmax[0] && pmax[1] == ':') pmax += 2;
|
|
||||||
|
|
||||||
length = pmax - libname;
|
if (unicode)
|
||||||
|
|
||||||
result = HeapAlloc (GetProcessHeap(), 0, length+1);
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
{
|
||||||
strncpy (result, libname, length);
|
WCHAR filenameW[MAX_PATH];
|
||||||
result [length] = '\0';
|
static WCHAR dotDLL[] = {'.','d','l','l',0};
|
||||||
|
|
||||||
|
if (SearchPathW( NULL, (LPCWSTR)name, dotDLL, sizeof(filenameW) / sizeof(filenameW[0]), filenameW, NULL ))
|
||||||
|
{
|
||||||
|
hFile = CreateFileW( filenameW, GENERIC_READ, FILE_SHARE_READ,
|
||||||
|
NULL, OPEN_EXISTING, 0, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char filenameA[MAX_PATH];
|
||||||
|
|
||||||
|
if (SearchPathA( NULL, (const char*)name, ".dll", sizeof(filenameA), filenameA, NULL ))
|
||||||
|
{
|
||||||
|
hFile = CreateFileA( filenameA, GENERIC_READ, FILE_SHARE_READ,
|
||||||
|
NULL, OPEN_EXISTING, 0, 0 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
if (hFile == INVALID_HANDLE_VALUE) return FALSE;
|
||||||
|
switch (MODULE_GetBinaryType( hFile ))
|
||||||
|
{
|
||||||
|
case BINARY_PE_EXE:
|
||||||
|
case BINARY_PE_DLL:
|
||||||
|
mapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
|
||||||
|
if (mapping)
|
||||||
|
{
|
||||||
|
*hmod = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
|
||||||
|
CloseHandle( mapping );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CloseHandle( hFile );
|
||||||
|
|
||||||
|
return *hmod != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/******************************************************************
|
||||||
* MODULE_LoadLibraryExA (internal)
|
* LoadLibraryExA (KERNEL32.@)
|
||||||
*
|
|
||||||
* Load a PE style module according to the load order.
|
|
||||||
*
|
*
|
||||||
* The HFILE parameter is not used and marked reserved in the SDK. I can
|
* The HFILE parameter is not used and marked reserved in the SDK. I can
|
||||||
* only guess that it should force a file to be mapped, but I rather
|
* only guess that it should force a file to be mapped, but I rather
|
||||||
* ignore the parameter because it would be extremely difficult to
|
* ignore the parameter because it would be extremely difficult to
|
||||||
* integrate this with different types of module representations.
|
* integrate this with different types of module representations.
|
||||||
*
|
*
|
||||||
* libdir is used to support LOAD_WITH_ALTERED_SEARCH_PATH during the recursion
|
|
||||||
* on this function. When first called from LoadLibraryExA it will be
|
|
||||||
* NULL but thereafter it may point to a buffer containing the path
|
|
||||||
* portion of the library name. Note that the recursion all occurs
|
|
||||||
* within a Critical section (see LoadLibraryExA) so the use of a
|
|
||||||
* static is acceptable.
|
|
||||||
* (We have to use a static variable at some point anyway, to pass the
|
|
||||||
* information from BUILTIN32_dlopen through dlopen and the builtin's
|
|
||||||
* init function into load_library).
|
|
||||||
* allocated_libdir is TRUE in the stack frame that allocated libdir
|
|
||||||
*/
|
*/
|
||||||
WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HANDLE hfile, DWORD flags )
|
HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
|
||||||
{
|
{
|
||||||
DWORD err = GetLastError();
|
UNICODE_STRING wstr;
|
||||||
WINE_MODREF *pwm;
|
NTSTATUS nts;
|
||||||
int i;
|
HMODULE hModule;
|
||||||
enum loadorder_type loadorder[LOADORDER_NTYPES];
|
|
||||||
LPSTR filename;
|
|
||||||
const char *filetype = "";
|
|
||||||
DWORD found;
|
|
||||||
BOOL allocated_libdir = FALSE;
|
|
||||||
static LPCSTR libdir = NULL; /* See above */
|
|
||||||
|
|
||||||
if ( !libname ) return NULL;
|
if (!libname)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
filename = HeapAlloc ( GetProcessHeap(), 0, MAX_PATH + 1 );
|
if (flags & LOAD_LIBRARY_AS_DATAFILE)
|
||||||
if ( !filename ) return NULL;
|
{
|
||||||
*filename = 0; /* Just in case we don't set it before goto error */
|
/* The method in load_library_as_datafile allows searching for the
|
||||||
|
* 'native' libraries only
|
||||||
|
*/
|
||||||
|
if (load_library_as_datafile(libname, FALSE, &hModule))
|
||||||
|
return (HMODULE)((ULONG_PTR)hModule + 1);
|
||||||
|
flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
|
||||||
|
/* Fallback to normal behaviour */
|
||||||
|
}
|
||||||
|
|
||||||
RtlEnterCriticalSection( &loader_section );
|
RtlCreateUnicodeStringFromAsciiz( &wstr, libname );
|
||||||
|
nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
|
||||||
|
if (nts != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
hModule = 0;
|
||||||
|
SetLastError( RtlNtStatusToDosError( nts ) );
|
||||||
|
}
|
||||||
|
RtlFreeUnicodeString( &wstr );
|
||||||
|
|
||||||
if ((flags & LOAD_WITH_ALTERED_SEARCH_PATH) && FILE_contains_path(libname))
|
return hModule;
|
||||||
{
|
}
|
||||||
if (!(libdir = allocate_lib_dir(libname))) goto error;
|
|
||||||
allocated_libdir = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!libdir || allocated_libdir)
|
/***********************************************************************
|
||||||
found = SearchPathA(NULL, libname, ".dll", MAX_PATH, filename, NULL);
|
* LoadLibraryExW (KERNEL32.@)
|
||||||
else
|
*/
|
||||||
found = DIR_SearchAlternatePath(libdir, libname, ".dll", MAX_PATH, filename, NULL);
|
HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW, HANDLE hfile, DWORD flags)
|
||||||
|
{
|
||||||
|
UNICODE_STRING wstr;
|
||||||
|
NTSTATUS nts;
|
||||||
|
HMODULE hModule;
|
||||||
|
|
||||||
/* build the modules filename */
|
if (!libnameW)
|
||||||
if (!found)
|
{
|
||||||
{
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
if (!MODULE_GetBuiltinPath( libname, ".dll", filename, MAX_PATH )) goto error;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for already loaded module */
|
if (flags & LOAD_LIBRARY_AS_DATAFILE)
|
||||||
if (!(pwm = MODULE_FindModule(filename)) && !FILE_contains_path(libname))
|
{
|
||||||
{
|
/* The method in load_library_as_datafile allows searching for the
|
||||||
LPSTR fn = HeapAlloc ( GetProcessHeap(), 0, MAX_PATH + 1 );
|
* 'native' libraries only
|
||||||
if (fn)
|
*/
|
||||||
{
|
if (load_library_as_datafile(libnameW, TRUE, &hModule))
|
||||||
/* since the default loading mechanism uses a more detailed algorithm
|
return (HMODULE)((ULONG_PTR)hModule + 1);
|
||||||
* than SearchPath (like using PATH, which can even be modified between
|
flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
|
||||||
* two attempts of loading the same DLL), the look-up above (with
|
/* Fallback to normal behaviour */
|
||||||
* SearchPath) can have put the file in system directory, whereas it
|
}
|
||||||
* has already been loaded but with a different path. So do a specific
|
|
||||||
* look-up with filename (without any path)
|
|
||||||
*/
|
|
||||||
strcpy ( fn, libname );
|
|
||||||
/* if the filename doesn't have an extension append .DLL */
|
|
||||||
if (!strrchr( fn, '.')) strcat( fn, ".dll" );
|
|
||||||
if ((pwm = MODULE_FindModule( fn )) != NULL)
|
|
||||||
strcpy( filename, fn );
|
|
||||||
HeapFree( GetProcessHeap(), 0, fn );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pwm)
|
|
||||||
{
|
|
||||||
pwm->refCount++;
|
|
||||||
|
|
||||||
if ((pwm->flags & WINE_MODREF_DONT_RESOLVE_REFS) &&
|
RtlInitUnicodeString( &wstr, libnameW );
|
||||||
!(flags & DONT_RESOLVE_DLL_REFERENCES))
|
nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
|
||||||
{
|
if (nts != STATUS_SUCCESS)
|
||||||
pwm->flags &= ~WINE_MODREF_DONT_RESOLVE_REFS;
|
{
|
||||||
PE_fixup_imports( pwm );
|
hModule = 0;
|
||||||
}
|
SetLastError( RtlNtStatusToDosError( nts ) );
|
||||||
TRACE("Already loaded module '%s' at %p, count=%d\n", filename, pwm->module, pwm->refCount);
|
}
|
||||||
if (allocated_libdir)
|
return hModule;
|
||||||
{
|
|
||||||
HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir );
|
|
||||||
libdir = NULL;
|
|
||||||
}
|
|
||||||
RtlLeaveCriticalSection( &loader_section );
|
|
||||||
HeapFree ( GetProcessHeap(), 0, filename );
|
|
||||||
return pwm;
|
|
||||||
}
|
|
||||||
|
|
||||||
MODULE_GetLoadOrder( loadorder, filename, TRUE);
|
|
||||||
|
|
||||||
for(i = 0; i < LOADORDER_NTYPES; i++)
|
|
||||||
{
|
|
||||||
if (loadorder[i] == LOADORDER_INVALID) break;
|
|
||||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
|
||||||
|
|
||||||
switch(loadorder[i])
|
|
||||||
{
|
|
||||||
case LOADORDER_DLL:
|
|
||||||
TRACE("Trying native dll '%s'\n", filename);
|
|
||||||
pwm = PE_LoadLibraryExA(filename, flags);
|
|
||||||
filetype = "native";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LOADORDER_BI:
|
|
||||||
TRACE("Trying built-in '%s'\n", filename);
|
|
||||||
pwm = BUILTIN32_LoadLibraryExA(filename, flags);
|
|
||||||
filetype = "builtin";
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
pwm = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pwm)
|
|
||||||
{
|
|
||||||
/* Initialize DLL just loaded */
|
|
||||||
TRACE("Loaded module '%s' at %p\n", filename, pwm->module);
|
|
||||||
if (!TRACE_ON(module))
|
|
||||||
TRACE_(loaddll)("Loaded module '%s' : %s\n", filename, filetype);
|
|
||||||
/* Set the refCount here so that an attach failure will */
|
|
||||||
/* decrement the dependencies through the MODULE_FreeLibrary call. */
|
|
||||||
pwm->refCount = 1;
|
|
||||||
|
|
||||||
if (allocated_libdir)
|
|
||||||
{
|
|
||||||
HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir );
|
|
||||||
libdir = NULL;
|
|
||||||
}
|
|
||||||
RtlLeaveCriticalSection( &loader_section );
|
|
||||||
SetLastError( err ); /* restore last error */
|
|
||||||
HeapFree ( GetProcessHeap(), 0, filename );
|
|
||||||
return pwm;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(GetLastError() != ERROR_FILE_NOT_FOUND)
|
|
||||||
{
|
|
||||||
WARN("Loading of %s DLL %s failed (error %ld).\n",
|
|
||||||
filetype, filename, GetLastError());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (allocated_libdir)
|
|
||||||
{
|
|
||||||
HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir );
|
|
||||||
libdir = NULL;
|
|
||||||
}
|
|
||||||
RtlLeaveCriticalSection( &loader_section );
|
|
||||||
WARN("Failed to load module '%s'; error=%ld\n", filename, GetLastError());
|
|
||||||
HeapFree ( GetProcessHeap(), 0, filename );
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* LoadLibraryA (KERNEL32.@)
|
* LoadLibraryA (KERNEL32.@)
|
||||||
*/
|
*/
|
||||||
HMODULE WINAPI LoadLibraryA(LPCSTR libname) {
|
HMODULE WINAPI LoadLibraryA(LPCSTR libname)
|
||||||
return LoadLibraryExA(libname,0,0);
|
{
|
||||||
|
return LoadLibraryExA(libname, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -1302,7 +1129,7 @@ HMODULE WINAPI LoadLibraryA(LPCSTR libname) {
|
||||||
*/
|
*/
|
||||||
HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
|
HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
|
||||||
{
|
{
|
||||||
return LoadLibraryExW(libnameW,0,0);
|
return LoadLibraryExW(libnameW, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -1320,18 +1147,6 @@ HMODULE WINAPI LoadLibrary32_16( LPCSTR libname )
|
||||||
return hModule;
|
return hModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* LoadLibraryExW (KERNEL32.@)
|
|
||||||
*/
|
|
||||||
HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW,HANDLE hfile,DWORD flags)
|
|
||||||
{
|
|
||||||
LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
|
|
||||||
HMODULE ret = LoadLibraryExA( libnameA , hfile, flags );
|
|
||||||
|
|
||||||
HeapFree( GetProcessHeap(), 0, libnameA );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* FreeLibrary (KERNEL32.@)
|
* FreeLibrary (KERNEL32.@)
|
||||||
* FreeLibrary32 (KERNEL.486)
|
* FreeLibrary32 (KERNEL.486)
|
||||||
|
@ -1341,6 +1156,12 @@ BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
|
||||||
BOOL retv = FALSE;
|
BOOL retv = FALSE;
|
||||||
NTSTATUS nts;
|
NTSTATUS nts;
|
||||||
|
|
||||||
|
if (!hLibModule)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_INVALID_HANDLE );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if ((ULONG_PTR)hLibModule & 1)
|
if ((ULONG_PTR)hLibModule & 1)
|
||||||
{
|
{
|
||||||
/* this is a LOAD_LIBRARY_AS_DATAFILE module */
|
/* this is a LOAD_LIBRARY_AS_DATAFILE module */
|
||||||
|
@ -1349,13 +1170,6 @@ BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hLibModule)
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_INVALID_HANDLE );
|
|
||||||
RtlLeaveCriticalSection( &loader_section );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((nts = LdrUnloadDll( hLibModule )) == STATUS_SUCCESS) retv = TRUE;
|
if ((nts = LdrUnloadDll( hLibModule )) == STATUS_SUCCESS) retv = TRUE;
|
||||||
else SetLastError( RtlNtStatusToDosError( nts ) );
|
else SetLastError( RtlNtStatusToDosError( nts ) );
|
||||||
|
|
||||||
|
@ -1381,8 +1195,6 @@ HINSTANCE16 WINAPI PrivateLoadLibrary(LPCSTR libname)
|
||||||
return LoadLibrary16(libname);
|
return LoadLibrary16(libname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* PrivateFreeLibrary (KERNEL32.@)
|
* PrivateFreeLibrary (KERNEL32.@)
|
||||||
*
|
*
|
||||||
|
|
|
@ -257,7 +257,7 @@ DWORD PE_fixup_imports( WINE_MODREF *wm )
|
||||||
|
|
||||||
/* Allocate module dependency list */
|
/* Allocate module dependency list */
|
||||||
wm->nDeps = i;
|
wm->nDeps = i;
|
||||||
wm->deps = HeapAlloc( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) );
|
wm->deps = RtlAllocateHeap( ntdll_get_process_heap(), 0, i*sizeof(WINE_MODREF *) );
|
||||||
|
|
||||||
/* load the imported modules. They are automatically
|
/* load the imported modules. They are automatically
|
||||||
* added to the modref list of the process.
|
* added to the modref list of the process.
|
||||||
|
@ -268,19 +268,24 @@ DWORD PE_fixup_imports( WINE_MODREF *wm )
|
||||||
IMAGE_IMPORT_BY_NAME *pe_name;
|
IMAGE_IMPORT_BY_NAME *pe_name;
|
||||||
PIMAGE_THUNK_DATA import_list,thunk_list;
|
PIMAGE_THUNK_DATA import_list,thunk_list;
|
||||||
char *name = get_rva(wm->module, pe_imp->Name);
|
char *name = get_rva(wm->module, pe_imp->Name);
|
||||||
|
NTSTATUS nts;
|
||||||
|
|
||||||
if (characteristics_detection && !pe_imp->u.Characteristics)
|
if (characteristics_detection && !pe_imp->u.Characteristics)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
wmImp = MODULE_LoadLibraryExA( name, 0, 0 );
|
nts = MODULE_LoadLibraryExA( name, 0, &wmImp );
|
||||||
if (!wmImp) {
|
switch (nts)
|
||||||
if(GetLastError() == ERROR_FILE_NOT_FOUND)
|
{
|
||||||
ERR_(module)("Module (file) %s (which is needed by %s) not found\n", name, wm->filename);
|
case STATUS_SUCCESS:
|
||||||
else
|
break;
|
||||||
ERR_(module)("Loading module (file) %s (which is needed by %s) failed (error %ld).\n",
|
case STATUS_NO_SUCH_FILE:
|
||||||
name, wm->filename, GetLastError());
|
ERR_(module)("Module (file) %s (which is needed by %s) not found\n", name, wm->filename);
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
ERR_(module)("Loading module (file) %s (which is needed by %s) failed (error %ld).\n",
|
||||||
|
name, wm->filename, GetLastError());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
wm->deps[i++] = wmImp;
|
wm->deps[i++] = wmImp;
|
||||||
|
|
||||||
/* FIXME: forwarder entries ... */
|
/* FIXME: forwarder entries ... */
|
||||||
|
@ -575,35 +580,38 @@ WINE_MODREF *PE_CreateModule( HMODULE hModule, LPCSTR filename, DWORD flags,
|
||||||
* The PE Library Loader frontend.
|
* The PE Library Loader frontend.
|
||||||
* FIXME: handle the flags.
|
* FIXME: handle the flags.
|
||||||
*/
|
*/
|
||||||
WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags)
|
NTSTATUS PE_LoadLibraryExA (LPCSTR name, DWORD flags, WINE_MODREF** pwm)
|
||||||
{
|
{
|
||||||
HMODULE hModule32;
|
HMODULE hModule32;
|
||||||
WINE_MODREF *wm;
|
|
||||||
HANDLE hFile;
|
HANDLE hFile;
|
||||||
|
|
||||||
hFile = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ,
|
hFile = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ,
|
||||||
NULL, OPEN_EXISTING, 0, 0 );
|
NULL, OPEN_EXISTING, 0, 0 );
|
||||||
if ( hFile == INVALID_HANDLE_VALUE ) return NULL;
|
if ( hFile == INVALID_HANDLE_VALUE )
|
||||||
|
{
|
||||||
|
/* keep it that way until we transform CreateFile into NtCreateFile */
|
||||||
|
return (GetLastError() == ERROR_FILE_NOT_FOUND) ?
|
||||||
|
STATUS_NO_SUCH_FILE : STATUS_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Load PE module */
|
/* Load PE module */
|
||||||
hModule32 = PE_LoadImage( hFile, name, flags );
|
hModule32 = PE_LoadImage( hFile, name, flags );
|
||||||
if (!hModule32)
|
if (!hModule32)
|
||||||
{
|
{
|
||||||
CloseHandle( hFile );
|
CloseHandle( hFile );
|
||||||
return NULL;
|
return STATUS_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create 32-bit MODREF */
|
/* Create 32-bit MODREF */
|
||||||
if ( !(wm = PE_CreateModule( hModule32, name, flags, hFile, FALSE )) )
|
if ( !(*pwm = PE_CreateModule( hModule32, name, flags, hFile, FALSE )) )
|
||||||
{
|
{
|
||||||
ERR( "can't load %s\n", name );
|
ERR( "can't load %s\n", name );
|
||||||
CloseHandle( hFile );
|
CloseHandle( hFile );
|
||||||
SetLastError( ERROR_OUTOFMEMORY );
|
return STATUS_NO_MEMORY; /* FIXME */
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle( hFile );
|
CloseHandle( hFile );
|
||||||
return wm;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -147,9 +147,8 @@ static void load_library( void *base, const char *filename )
|
||||||
* Partly copied from the original PE_ version.
|
* Partly copied from the original PE_ version.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
|
NTSTATUS BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags, WINE_MODREF** pwm)
|
||||||
{
|
{
|
||||||
WINE_MODREF *wm;
|
|
||||||
char dllname[20], *p;
|
char dllname[20], *p;
|
||||||
LPCSTR name;
|
LPCSTR name;
|
||||||
void *handle;
|
void *handle;
|
||||||
|
@ -159,29 +158,24 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
|
||||||
if ((p = strrchr( name, '\\' ))) name = p + 1;
|
if ((p = strrchr( name, '\\' ))) name = p + 1;
|
||||||
if ((p = strrchr( name, '/' ))) name = p + 1;
|
if ((p = strrchr( name, '/' ))) name = p + 1;
|
||||||
|
|
||||||
if (strlen(name) >= sizeof(dllname)-4) goto error;
|
if (strlen(name) >= sizeof(dllname)-4) return STATUS_NO_SUCH_FILE;
|
||||||
|
|
||||||
strcpy( dllname, name );
|
strcpy( dllname, name );
|
||||||
p = strrchr( dllname, '.' );
|
p = strrchr( dllname, '.' );
|
||||||
if (!p) strcat( dllname, ".dll" );
|
if (!p) strcat( dllname, ".dll" );
|
||||||
for (p = dllname; *p; p++) *p = FILE_tolower(*p);
|
for (p = dllname; *p; p++) *p = FILE_tolower(*p);
|
||||||
|
|
||||||
if (!(handle = BUILTIN32_dlopen( dllname ))) goto error;
|
if (!(handle = BUILTIN32_dlopen( dllname ))) return STATUS_NO_SUCH_FILE;
|
||||||
|
|
||||||
if (!(wm = MODULE_FindModule( path ))) wm = MODULE_FindModule( dllname );
|
if (!((*pwm) = MODULE_FindModule( path ))) *pwm = MODULE_FindModule( dllname );
|
||||||
if (!wm)
|
if (!*pwm)
|
||||||
{
|
{
|
||||||
ERR( "loaded .so but dll %s still not found - 16-bit dll or version conflict.\n", dllname );
|
ERR( "loaded .so but dll %s still not found - 16-bit dll or version conflict.\n", dllname );
|
||||||
/* wine_dll_unload( handle );*/
|
/* wine_dll_unload( handle );*/
|
||||||
SetLastError( ERROR_BAD_EXE_FORMAT );
|
return STATUS_INVALID_IMAGE_FORMAT;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
wm->dlhandle = handle;
|
(*pwm)->dlhandle = handle;
|
||||||
return wm;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
error:
|
|
||||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
Loading…
Reference in New Issue