kernel32: Move LoadLibrary functions to kernelbase.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
a5d45e9ae5
commit
c5dc41e980
|
@ -528,7 +528,7 @@
|
||||||
@ stdcall -import FreeEnvironmentStringsA(ptr)
|
@ stdcall -import FreeEnvironmentStringsA(ptr)
|
||||||
@ stdcall -import FreeEnvironmentStringsW(ptr)
|
@ stdcall -import FreeEnvironmentStringsW(ptr)
|
||||||
@ stub -i386 FreeLSCallback
|
@ stub -i386 FreeLSCallback
|
||||||
@ stdcall FreeLibrary(long)
|
@ stdcall -import FreeLibrary(long)
|
||||||
@ stdcall FreeLibraryAndExitThread(long long)
|
@ stdcall FreeLibraryAndExitThread(long long)
|
||||||
@ stdcall FreeLibraryWhenCallbackReturns(ptr ptr) ntdll.TpCallbackUnloadDllOnCompletion
|
@ stdcall FreeLibraryWhenCallbackReturns(ptr ptr) ntdll.TpCallbackUnloadDllOnCompletion
|
||||||
@ stdcall -import FreeResource(long)
|
@ stdcall -import FreeResource(long)
|
||||||
|
@ -1042,10 +1042,10 @@
|
||||||
@ stdcall LeaveCriticalSection(ptr) ntdll.RtlLeaveCriticalSection
|
@ stdcall LeaveCriticalSection(ptr) ntdll.RtlLeaveCriticalSection
|
||||||
@ stdcall LeaveCriticalSectionWhenCallbackReturns(ptr ptr) ntdll.TpCallbackLeaveCriticalSectionOnCompletion
|
@ stdcall LeaveCriticalSectionWhenCallbackReturns(ptr ptr) ntdll.TpCallbackLeaveCriticalSectionOnCompletion
|
||||||
# @ stub LoadAppInitDlls
|
# @ stub LoadAppInitDlls
|
||||||
@ stdcall LoadLibraryA(str)
|
@ stdcall -import LoadLibraryA(str)
|
||||||
@ stdcall LoadLibraryExA( str long long)
|
@ stdcall -import LoadLibraryExA( str long long)
|
||||||
@ stdcall LoadLibraryExW(wstr long long)
|
@ stdcall -import LoadLibraryExW(wstr long long)
|
||||||
@ stdcall LoadLibraryW(wstr)
|
@ stdcall -import LoadLibraryW(wstr)
|
||||||
@ stdcall LoadModule(str ptr)
|
@ stdcall LoadModule(str ptr)
|
||||||
@ stdcall -import LoadResource(long long)
|
@ stdcall -import LoadResource(long long)
|
||||||
# @ stub LoadStringBaseExW
|
# @ stub LoadStringBaseExW
|
||||||
|
|
|
@ -47,16 +47,6 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(module);
|
WINE_DEFAULT_DEBUG_CHANNEL(module);
|
||||||
|
|
||||||
#define NE_FFLAGS_LIBMODULE 0x8000
|
|
||||||
|
|
||||||
/* to keep track of LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE file handles */
|
|
||||||
struct exclusive_datafile
|
|
||||||
{
|
|
||||||
struct list entry;
|
|
||||||
HMODULE module;
|
|
||||||
HANDLE file;
|
|
||||||
};
|
|
||||||
static struct list exclusive_datafile_list = LIST_INIT( exclusive_datafile_list );
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* GetDllDirectoryA (KERNEL32.@)
|
* GetDllDirectoryA (KERNEL32.@)
|
||||||
|
@ -283,261 +273,6 @@ BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
|
||||||
return GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType);
|
return GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* load_library_as_datafile
|
|
||||||
*/
|
|
||||||
static BOOL load_library_as_datafile( LPCWSTR load_path, DWORD flags, LPCWSTR name, HMODULE *hmod )
|
|
||||||
{
|
|
||||||
static const WCHAR dotDLL[] = {'.','d','l','l',0};
|
|
||||||
|
|
||||||
WCHAR filenameW[MAX_PATH];
|
|
||||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
||||||
HANDLE mapping;
|
|
||||||
HMODULE module = 0;
|
|
||||||
DWORD protect = PAGE_READONLY;
|
|
||||||
DWORD sharing = FILE_SHARE_READ | FILE_SHARE_DELETE;
|
|
||||||
|
|
||||||
*hmod = 0;
|
|
||||||
|
|
||||||
if (flags & LOAD_LIBRARY_AS_IMAGE_RESOURCE) protect |= SEC_IMAGE;
|
|
||||||
|
|
||||||
if (SearchPathW( load_path, name, dotDLL, ARRAY_SIZE( filenameW ), filenameW, NULL ))
|
|
||||||
{
|
|
||||||
hFile = CreateFileW( filenameW, GENERIC_READ, sharing, NULL, OPEN_EXISTING, 0, 0 );
|
|
||||||
}
|
|
||||||
if (hFile == INVALID_HANDLE_VALUE) return FALSE;
|
|
||||||
|
|
||||||
mapping = CreateFileMappingW( hFile, NULL, protect, 0, 0, NULL );
|
|
||||||
if (!mapping) goto failed;
|
|
||||||
|
|
||||||
module = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
|
|
||||||
CloseHandle( mapping );
|
|
||||||
if (!module) goto failed;
|
|
||||||
|
|
||||||
if (!(flags & LOAD_LIBRARY_AS_IMAGE_RESOURCE))
|
|
||||||
{
|
|
||||||
/* make sure it's a valid PE file */
|
|
||||||
if (!RtlImageNtHeader( module )) goto failed;
|
|
||||||
*hmod = (HMODULE)((char *)module + 1); /* set bit 0 for data file module */
|
|
||||||
|
|
||||||
if (flags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
|
|
||||||
{
|
|
||||||
struct exclusive_datafile *file = HeapAlloc( GetProcessHeap(), 0, sizeof(*file) );
|
|
||||||
if (!file) goto failed;
|
|
||||||
file->module = *hmod;
|
|
||||||
file->file = hFile;
|
|
||||||
list_add_head( &exclusive_datafile_list, &file->entry );
|
|
||||||
TRACE( "delaying close %p for module %p\n", file->file, file->module );
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else *hmod = (HMODULE)((char *)module + 2); /* set bit 1 for image resource module */
|
|
||||||
|
|
||||||
CloseHandle( hFile );
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
failed:
|
|
||||||
if (module) UnmapViewOfFile( module );
|
|
||||||
CloseHandle( hFile );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* load_library
|
|
||||||
*
|
|
||||||
* Helper for LoadLibraryExA/W.
|
|
||||||
*/
|
|
||||||
static HMODULE load_library( const UNICODE_STRING *libname, DWORD flags )
|
|
||||||
{
|
|
||||||
NTSTATUS nts;
|
|
||||||
HMODULE hModule;
|
|
||||||
WCHAR *load_path, *dummy;
|
|
||||||
const DWORD unsupported_flags = (LOAD_IGNORE_CODE_AUTHZ_LEVEL |
|
|
||||||
LOAD_LIBRARY_REQUIRE_SIGNED_TARGET);
|
|
||||||
|
|
||||||
if( flags & unsupported_flags)
|
|
||||||
FIXME("unsupported flag(s) used (flags: 0x%08x)\n", flags);
|
|
||||||
|
|
||||||
if (!set_ntstatus( LdrGetDllPath( libname->Buffer, flags, &load_path, &dummy ))) return 0;
|
|
||||||
|
|
||||||
if (flags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
|
|
||||||
{
|
|
||||||
ULONG_PTR magic;
|
|
||||||
|
|
||||||
LdrLockLoaderLock( 0, NULL, &magic );
|
|
||||||
if (!LdrGetDllHandle( load_path, flags, libname, &hModule ))
|
|
||||||
{
|
|
||||||
LdrAddRefDll( 0, hModule );
|
|
||||||
LdrUnlockLoaderLock( 0, magic );
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (load_library_as_datafile( load_path, flags, libname->Buffer, &hModule ))
|
|
||||||
{
|
|
||||||
LdrUnlockLoaderLock( 0, magic );
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
LdrUnlockLoaderLock( 0, magic );
|
|
||||||
flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
|
|
||||||
/* Fallback to normal behaviour */
|
|
||||||
}
|
|
||||||
|
|
||||||
nts = LdrLoadDll( load_path, flags, libname, &hModule );
|
|
||||||
if (nts != STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
hModule = 0;
|
|
||||||
if (nts == STATUS_DLL_NOT_FOUND && (GetVersion() & 0x80000000))
|
|
||||||
SetLastError( ERROR_DLL_NOT_FOUND );
|
|
||||||
else
|
|
||||||
SetLastError( RtlNtStatusToDosError( nts ) );
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
RtlReleasePath( load_path );
|
|
||||||
return hModule;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* LoadLibraryExA (KERNEL32.@)
|
|
||||||
*
|
|
||||||
* Load a dll file into the process address space.
|
|
||||||
*
|
|
||||||
* PARAMS
|
|
||||||
* libname [I] Name of the file to load
|
|
||||||
* hfile [I] Reserved, must be 0.
|
|
||||||
* flags [I] Flags for loading the dll
|
|
||||||
*
|
|
||||||
* RETURNS
|
|
||||||
* Success: A handle to the loaded dll.
|
|
||||||
* Failure: A NULL handle. Use GetLastError() to determine the cause.
|
|
||||||
*
|
|
||||||
* NOTES
|
|
||||||
* 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
|
|
||||||
* ignore the parameter because it would be extremely difficult to
|
|
||||||
* integrate this with different types of module representations.
|
|
||||||
*/
|
|
||||||
HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
|
|
||||||
{
|
|
||||||
WCHAR *libnameW;
|
|
||||||
|
|
||||||
if (!(libnameW = FILE_name_AtoW( libname, FALSE ))) return 0;
|
|
||||||
return LoadLibraryExW( libnameW, hfile, flags );
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* LoadLibraryExW (KERNEL32.@)
|
|
||||||
*
|
|
||||||
* Unicode version of LoadLibraryExA.
|
|
||||||
*/
|
|
||||||
HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW(LPCWSTR libnameW, HANDLE hfile, DWORD flags)
|
|
||||||
{
|
|
||||||
UNICODE_STRING wstr;
|
|
||||||
HMODULE res;
|
|
||||||
|
|
||||||
if (!libnameW)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
RtlInitUnicodeString( &wstr, libnameW );
|
|
||||||
if (wstr.Buffer[wstr.Length/sizeof(WCHAR) - 1] != ' ')
|
|
||||||
return load_library( &wstr, flags );
|
|
||||||
|
|
||||||
/* Library name has trailing spaces */
|
|
||||||
RtlCreateUnicodeString( &wstr, libnameW );
|
|
||||||
while (wstr.Length > sizeof(WCHAR) &&
|
|
||||||
wstr.Buffer[wstr.Length/sizeof(WCHAR) - 1] == ' ')
|
|
||||||
{
|
|
||||||
wstr.Length -= sizeof(WCHAR);
|
|
||||||
}
|
|
||||||
wstr.Buffer[wstr.Length/sizeof(WCHAR)] = '\0';
|
|
||||||
res = load_library( &wstr, flags );
|
|
||||||
RtlFreeUnicodeString( &wstr );
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* LoadLibraryA (KERNEL32.@)
|
|
||||||
*
|
|
||||||
* Load a dll file into the process address space.
|
|
||||||
*
|
|
||||||
* PARAMS
|
|
||||||
* libname [I] Name of the file to load
|
|
||||||
*
|
|
||||||
* RETURNS
|
|
||||||
* Success: A handle to the loaded dll.
|
|
||||||
* Failure: A NULL handle. Use GetLastError() to determine the cause.
|
|
||||||
*
|
|
||||||
* NOTES
|
|
||||||
* See LoadLibraryExA().
|
|
||||||
*/
|
|
||||||
HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR libname)
|
|
||||||
{
|
|
||||||
return LoadLibraryExA(libname, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* LoadLibraryW (KERNEL32.@)
|
|
||||||
*
|
|
||||||
* Unicode version of LoadLibraryA.
|
|
||||||
*/
|
|
||||||
HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryW(LPCWSTR libnameW)
|
|
||||||
{
|
|
||||||
return LoadLibraryExW(libnameW, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* FreeLibrary (KERNEL32.@)
|
|
||||||
*
|
|
||||||
* Free a dll loaded into the process address space.
|
|
||||||
*
|
|
||||||
* PARAMS
|
|
||||||
* hLibModule [I] Handle to the dll returned by LoadLibraryA().
|
|
||||||
*
|
|
||||||
* RETURNS
|
|
||||||
* Success: TRUE. The dll is removed if it is not still in use.
|
|
||||||
* Failure: FALSE. Use GetLastError() to determine the cause.
|
|
||||||
*/
|
|
||||||
BOOL WINAPI DECLSPEC_HOTPATCH FreeLibrary(HINSTANCE hLibModule)
|
|
||||||
{
|
|
||||||
if (!hLibModule)
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_INVALID_HANDLE );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ULONG_PTR)hLibModule & 3) /* this is a datafile module */
|
|
||||||
{
|
|
||||||
void *ptr = (void *)((ULONG_PTR)hLibModule & ~3);
|
|
||||||
if (!RtlImageNtHeader( ptr ))
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_BAD_EXE_FORMAT );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if ((ULONG_PTR)hLibModule & 1)
|
|
||||||
{
|
|
||||||
struct exclusive_datafile *file;
|
|
||||||
ULONG_PTR magic;
|
|
||||||
|
|
||||||
LdrLockLoaderLock( 0, NULL, &magic );
|
|
||||||
LIST_FOR_EACH_ENTRY( file, &exclusive_datafile_list, struct exclusive_datafile, entry )
|
|
||||||
{
|
|
||||||
if (file->module != hLibModule) continue;
|
|
||||||
TRACE( "closing %p for module %p\n", file->file, file->module );
|
|
||||||
CloseHandle( file->file );
|
|
||||||
list_remove( &file->entry );
|
|
||||||
HeapFree( GetProcessHeap(), 0, file );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LdrUnlockLoaderLock( 0, magic );
|
|
||||||
}
|
|
||||||
return UnmapViewOfFile( ptr );
|
|
||||||
}
|
|
||||||
|
|
||||||
return set_ntstatus( LdrUnloadDll( hLibModule ));
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* GetProcAddress (KERNEL32.@)
|
* GetProcAddress (KERNEL32.@)
|
||||||
*
|
*
|
||||||
|
|
|
@ -394,7 +394,7 @@
|
||||||
@ stdcall FreeEnvironmentStringsW(ptr)
|
@ stdcall FreeEnvironmentStringsW(ptr)
|
||||||
# @ stub FreeGPOListInternalA
|
# @ stub FreeGPOListInternalA
|
||||||
# @ stub FreeGPOListInternalW
|
# @ stub FreeGPOListInternalW
|
||||||
@ stdcall FreeLibrary(long) kernel32.FreeLibrary
|
@ stdcall FreeLibrary(long)
|
||||||
@ stdcall FreeLibraryAndExitThread(long long)
|
@ stdcall FreeLibraryAndExitThread(long long)
|
||||||
@ stdcall FreeLibraryWhenCallbackReturns(ptr ptr) ntdll.TpCallbackUnloadDllOnCompletion
|
@ stdcall FreeLibraryWhenCallbackReturns(ptr ptr) ntdll.TpCallbackUnloadDllOnCompletion
|
||||||
@ stdcall FreeResource(long)
|
@ stdcall FreeResource(long)
|
||||||
|
@ -618,7 +618,7 @@
|
||||||
# @ stub GetPreviousFgPolicyRefreshInfoInternal
|
# @ stub GetPreviousFgPolicyRefreshInfoInternal
|
||||||
@ stdcall GetPriorityClass(long)
|
@ stdcall GetPriorityClass(long)
|
||||||
@ stdcall GetPrivateObjectSecurity(ptr long ptr long ptr)
|
@ stdcall GetPrivateObjectSecurity(ptr long ptr long ptr)
|
||||||
@ stdcall GetProcAddress(long str) kernel32.GetProcAddress
|
@ stdcall GetProcAddress(long str)
|
||||||
# @ stub GetProcAddressForCaller
|
# @ stub GetProcAddressForCaller
|
||||||
# @ stub GetProcessDefaultCpuSets
|
# @ stub GetProcessDefaultCpuSets
|
||||||
# @ stub GetProcessGroupAffinity
|
# @ stub GetProcessGroupAffinity
|
||||||
|
@ -922,10 +922,10 @@
|
||||||
@ stdcall LeaveCriticalSectionWhenCallbackReturns(ptr ptr) ntdll.TpCallbackLeaveCriticalSectionOnCompletion
|
@ stdcall LeaveCriticalSectionWhenCallbackReturns(ptr ptr) ntdll.TpCallbackLeaveCriticalSectionOnCompletion
|
||||||
# @ stub LoadAppInitDlls
|
# @ stub LoadAppInitDlls
|
||||||
# @ stub LoadEnclaveData
|
# @ stub LoadEnclaveData
|
||||||
@ stdcall LoadLibraryA(str) kernel32.LoadLibraryA
|
@ stdcall LoadLibraryA(str)
|
||||||
@ stdcall LoadLibraryExA( str long long) kernel32.LoadLibraryExA
|
@ stdcall LoadLibraryExA( str long long)
|
||||||
@ stdcall LoadLibraryExW(wstr long long) kernel32.LoadLibraryExW
|
@ stdcall LoadLibraryExW(wstr long long)
|
||||||
@ stdcall LoadLibraryW(wstr) kernel32.LoadLibraryW
|
@ stdcall LoadLibraryW(wstr)
|
||||||
# @ stub LoadPackagedLibrary
|
# @ stub LoadPackagedLibrary
|
||||||
@ stdcall LoadResource(long long)
|
@ stdcall LoadResource(long long)
|
||||||
@ stdcall LoadStringA(long long ptr long)
|
@ stdcall LoadStringA(long long ptr long)
|
||||||
|
|
|
@ -31,17 +31,161 @@
|
||||||
#include "winnls.h"
|
#include "winnls.h"
|
||||||
#include "winternl.h"
|
#include "winternl.h"
|
||||||
#include "kernelbase.h"
|
#include "kernelbase.h"
|
||||||
|
#include "wine/list.h"
|
||||||
|
#include "wine/asm.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "wine/exception.h"
|
#include "wine/exception.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(module);
|
WINE_DEFAULT_DEBUG_CHANNEL(module);
|
||||||
|
|
||||||
|
|
||||||
|
/* to keep track of LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE file handles */
|
||||||
|
struct exclusive_datafile
|
||||||
|
{
|
||||||
|
struct list entry;
|
||||||
|
HMODULE module;
|
||||||
|
HANDLE file;
|
||||||
|
};
|
||||||
|
static struct list exclusive_datafile_list = LIST_INIT( exclusive_datafile_list );
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Modules
|
* Modules
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* get_proc_address
|
||||||
|
*/
|
||||||
|
FARPROC WINAPI get_proc_address( HMODULE module, LPCSTR function )
|
||||||
|
{
|
||||||
|
FARPROC proc;
|
||||||
|
ANSI_STRING str;
|
||||||
|
|
||||||
|
if (!module) module = NtCurrentTeb()->Peb->ImageBaseAddress;
|
||||||
|
|
||||||
|
if ((ULONG_PTR)function >> 16)
|
||||||
|
{
|
||||||
|
RtlInitAnsiString( &str, function );
|
||||||
|
if (!set_ntstatus( LdrGetProcedureAddress( module, &str, 0, (void**)&proc ))) return NULL;
|
||||||
|
}
|
||||||
|
else if (!set_ntstatus( LdrGetProcedureAddress( module, NULL, LOWORD(function), (void**)&proc )))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* load_library_as_datafile
|
||||||
|
*/
|
||||||
|
static BOOL load_library_as_datafile( LPCWSTR load_path, DWORD flags, LPCWSTR name, HMODULE *mod_ret )
|
||||||
|
{
|
||||||
|
static const WCHAR dotDLL[] = {'.','d','l','l',0};
|
||||||
|
|
||||||
|
WCHAR filenameW[MAX_PATH];
|
||||||
|
HANDLE mapping, file = INVALID_HANDLE_VALUE;
|
||||||
|
HMODULE module = 0;
|
||||||
|
DWORD protect = PAGE_READONLY;
|
||||||
|
|
||||||
|
*mod_ret = 0;
|
||||||
|
|
||||||
|
if (flags & LOAD_LIBRARY_AS_IMAGE_RESOURCE) protect |= SEC_IMAGE;
|
||||||
|
|
||||||
|
if (SearchPathW( load_path, name, dotDLL, ARRAY_SIZE( filenameW ), filenameW, NULL ))
|
||||||
|
{
|
||||||
|
file = CreateFileW( filenameW, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||||
|
NULL, OPEN_EXISTING, 0, 0 );
|
||||||
|
}
|
||||||
|
if (file == INVALID_HANDLE_VALUE) return FALSE;
|
||||||
|
|
||||||
|
mapping = CreateFileMappingW( file, NULL, protect, 0, 0, NULL );
|
||||||
|
if (!mapping) goto failed;
|
||||||
|
|
||||||
|
module = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
|
||||||
|
CloseHandle( mapping );
|
||||||
|
if (!module) goto failed;
|
||||||
|
|
||||||
|
if (!(flags & LOAD_LIBRARY_AS_IMAGE_RESOURCE))
|
||||||
|
{
|
||||||
|
/* make sure it's a valid PE file */
|
||||||
|
if (!RtlImageNtHeader( module )) goto failed;
|
||||||
|
*mod_ret = (HMODULE)((char *)module + 1); /* set bit 0 for data file module */
|
||||||
|
|
||||||
|
if (flags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
|
||||||
|
{
|
||||||
|
struct exclusive_datafile *file = HeapAlloc( GetProcessHeap(), 0, sizeof(*file) );
|
||||||
|
if (!file) goto failed;
|
||||||
|
file->module = *mod_ret;
|
||||||
|
file->file = file;
|
||||||
|
list_add_head( &exclusive_datafile_list, &file->entry );
|
||||||
|
TRACE( "delaying close %p for module %p\n", file->file, file->module );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else *mod_ret = (HMODULE)((char *)module + 2); /* set bit 1 for image resource module */
|
||||||
|
|
||||||
|
CloseHandle( file );
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
if (module) UnmapViewOfFile( module );
|
||||||
|
CloseHandle( file );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* load_library
|
||||||
|
*/
|
||||||
|
static HMODULE load_library( const UNICODE_STRING *libname, DWORD flags )
|
||||||
|
{
|
||||||
|
const DWORD unsupported_flags = LOAD_IGNORE_CODE_AUTHZ_LEVEL | LOAD_LIBRARY_REQUIRE_SIGNED_TARGET;
|
||||||
|
NTSTATUS status;
|
||||||
|
HMODULE module;
|
||||||
|
WCHAR *load_path, *dummy;
|
||||||
|
|
||||||
|
if (flags & unsupported_flags) FIXME( "unsupported flag(s) used %#08x\n", flags );
|
||||||
|
|
||||||
|
if (!set_ntstatus( LdrGetDllPath( libname->Buffer, flags, &load_path, &dummy ))) return 0;
|
||||||
|
|
||||||
|
if (flags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE |
|
||||||
|
LOAD_LIBRARY_AS_IMAGE_RESOURCE))
|
||||||
|
{
|
||||||
|
ULONG_PTR magic;
|
||||||
|
|
||||||
|
LdrLockLoaderLock( 0, NULL, &magic );
|
||||||
|
if (!LdrGetDllHandle( load_path, flags, libname, &module ))
|
||||||
|
{
|
||||||
|
LdrAddRefDll( 0, module );
|
||||||
|
LdrUnlockLoaderLock( 0, magic );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (load_library_as_datafile( load_path, flags, libname->Buffer, &module ))
|
||||||
|
{
|
||||||
|
LdrUnlockLoaderLock( 0, magic );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
LdrUnlockLoaderLock( 0, magic );
|
||||||
|
flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
|
||||||
|
/* Fallback to normal behaviour */
|
||||||
|
}
|
||||||
|
|
||||||
|
status = LdrLoadDll( load_path, flags, libname, &module );
|
||||||
|
if (status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
module = 0;
|
||||||
|
if (status == STATUS_DLL_NOT_FOUND && (GetVersion() & 0x80000000))
|
||||||
|
SetLastError( ERROR_DLL_NOT_FOUND );
|
||||||
|
else
|
||||||
|
SetLastError( RtlNtStatusToDosError( status ) );
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
RtlReleasePath( load_path );
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* AddDllDirectory (kernelbase.@)
|
* AddDllDirectory (kernelbase.@)
|
||||||
*/
|
*/
|
||||||
|
@ -83,6 +227,49 @@ BOOL WINAPI DECLSPEC_HOTPATCH DisableThreadLibraryCalls( HMODULE module )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* FreeLibrary (kernelbase.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI DECLSPEC_HOTPATCH FreeLibrary( HINSTANCE module )
|
||||||
|
{
|
||||||
|
if (!module)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_INVALID_HANDLE );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ULONG_PTR)module & 3) /* this is a datafile module */
|
||||||
|
{
|
||||||
|
void *ptr = (void *)((ULONG_PTR)module & ~3);
|
||||||
|
if (!RtlImageNtHeader( ptr ))
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_BAD_EXE_FORMAT );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if ((ULONG_PTR)module & 1)
|
||||||
|
{
|
||||||
|
struct exclusive_datafile *file;
|
||||||
|
ULONG_PTR magic;
|
||||||
|
|
||||||
|
LdrLockLoaderLock( 0, NULL, &magic );
|
||||||
|
LIST_FOR_EACH_ENTRY( file, &exclusive_datafile_list, struct exclusive_datafile, entry )
|
||||||
|
{
|
||||||
|
if (file->module != module) continue;
|
||||||
|
TRACE( "closing %p for module %p\n", file->file, file->module );
|
||||||
|
CloseHandle( file->file );
|
||||||
|
list_remove( &file->entry );
|
||||||
|
HeapFree( GetProcessHeap(), 0, file );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LdrUnlockLoaderLock( 0, magic );
|
||||||
|
}
|
||||||
|
return UnmapViewOfFile( ptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
return set_ntstatus( LdrUnloadDll( module ));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* GetModuleFileNameA (kernelbase.@)
|
* GetModuleFileNameA (kernelbase.@)
|
||||||
*/
|
*/
|
||||||
|
@ -239,6 +426,115 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetModuleHandleExW( DWORD flags, LPCWSTR name, HMO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* GetProcAddress (kernelbase.@)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
/*
|
||||||
|
* Work around a Delphi bug on x86_64. When delay loading a symbol,
|
||||||
|
* Delphi saves rcx, rdx, r8 and r9 to the stack. It then calls
|
||||||
|
* GetProcAddress(), pops the saved registers and calls the function.
|
||||||
|
* This works fine if all of the parameters are ints. However, since
|
||||||
|
* it does not save xmm0 - 3, it relies on GetProcAddress() preserving
|
||||||
|
* these registers if the function takes floating point parameters.
|
||||||
|
* This wrapper saves xmm0 - 3 to the stack.
|
||||||
|
*/
|
||||||
|
__ASM_GLOBAL_FUNC( GetProcAddress,
|
||||||
|
".byte 0x48\n\t" /* hotpatch prolog */
|
||||||
|
"pushq %rbp\n\t"
|
||||||
|
__ASM_SEH(".seh_pushreg %rbp\n\t")
|
||||||
|
__ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
|
||||||
|
__ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
|
||||||
|
"movq %rsp,%rbp\n\t"
|
||||||
|
__ASM_SEH(".seh_setframe %rbp,0\n\t")
|
||||||
|
__ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
|
||||||
|
"subq $0x60,%rsp\n\t"
|
||||||
|
__ASM_SEH(".seh_stackalloc 0x60\n\t")
|
||||||
|
__ASM_SEH(".seh_endprologue\n\t")
|
||||||
|
"movaps %xmm0,-0x10(%rbp)\n\t"
|
||||||
|
"movaps %xmm1,-0x20(%rbp)\n\t"
|
||||||
|
"movaps %xmm2,-0x30(%rbp)\n\t"
|
||||||
|
"movaps %xmm3,-0x40(%rbp)\n\t"
|
||||||
|
"call " __ASM_NAME("get_proc_address") "\n\t"
|
||||||
|
"movaps -0x40(%rbp), %xmm3\n\t"
|
||||||
|
"movaps -0x30(%rbp), %xmm2\n\t"
|
||||||
|
"movaps -0x20(%rbp), %xmm1\n\t"
|
||||||
|
"movaps -0x10(%rbp), %xmm0\n\t"
|
||||||
|
"leaq 0(%rbp),%rsp\n\t"
|
||||||
|
__ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
|
||||||
|
"popq %rbp\n\t"
|
||||||
|
__ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
|
||||||
|
__ASM_CFI(".cfi_same_value %rbp\n\t")
|
||||||
|
"ret" )
|
||||||
|
#else /* __x86_64__ */
|
||||||
|
|
||||||
|
FARPROC WINAPI DECLSPEC_HOTPATCH GetProcAddress( HMODULE module, LPCSTR function )
|
||||||
|
{
|
||||||
|
return get_proc_address( module, function );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __x86_64__ */
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* LoadLibraryA (kernelbase.@)
|
||||||
|
*/
|
||||||
|
HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryA( LPCSTR name )
|
||||||
|
{
|
||||||
|
return LoadLibraryExA( name, 0, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* LoadLibraryW (kernelbase.@)
|
||||||
|
*/
|
||||||
|
HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryW( LPCWSTR name )
|
||||||
|
{
|
||||||
|
return LoadLibraryExW( name, 0, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* LoadLibraryExA (kernelbase.@)
|
||||||
|
*/
|
||||||
|
HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExA( LPCSTR name, HANDLE file, DWORD flags )
|
||||||
|
{
|
||||||
|
WCHAR *nameW;
|
||||||
|
|
||||||
|
if (!(nameW = file_name_AtoW( name, FALSE ))) return 0;
|
||||||
|
return LoadLibraryExW( nameW, file, flags );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* LoadLibraryExW (kernelbase.@)
|
||||||
|
*/
|
||||||
|
HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW( LPCWSTR name, HANDLE file, DWORD flags )
|
||||||
|
{
|
||||||
|
UNICODE_STRING str;
|
||||||
|
HMODULE module;
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
RtlInitUnicodeString( &str, name );
|
||||||
|
if (str.Buffer[str.Length/sizeof(WCHAR) - 1] != ' ') return load_library( &str, flags );
|
||||||
|
|
||||||
|
/* library name has trailing spaces */
|
||||||
|
RtlCreateUnicodeString( &str, name );
|
||||||
|
while (str.Length > sizeof(WCHAR) && str.Buffer[str.Length/sizeof(WCHAR) - 1] == ' ')
|
||||||
|
str.Length -= sizeof(WCHAR);
|
||||||
|
|
||||||
|
str.Buffer[str.Length/sizeof(WCHAR)] = 0;
|
||||||
|
module = load_library( &str, flags );
|
||||||
|
RtlFreeUnicodeString( &str );
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* RemoveDllDirectory (kernelbase.@)
|
* RemoveDllDirectory (kernelbase.@)
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue