loader.c revision 114410893548b9522c46fdcbd8f63385eb8bfb68
/*
* Win32 builtin dlls support
*
* Copyright 2000 Alexandre Julliard
*
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
* Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
* other than GPL or LGPL is available it will apply instead, Sun elects to use only
* the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
* a choice of LGPL license versions is made available with the language indicating
* that LGPLv2 or any later version may be used, or where a choice of which version
* of the LGPL is applied is otherwise unspecified.
*/
#include "config.h"
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_MMAN_H
#endif
#ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#ifdef __APPLE__
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#else
# ifndef _MSC_VER
extern char **environ;
# endif
#endif
int __wine_main_argc = 0;
char **__wine_main_argv = NULL;
char **__wine_main_environ = NULL;
struct dll_path_context
{
unsigned int index; /* current index in the dll path list */
char *buffer; /* buffer used for storing path names */
char *name; /* start of file name part in buffer (including leading slash) */
int namelen; /* length of file name without .so extension */
int win16; /* 16-bit dll search */
};
#define MAX_DLLS 100
static struct
{
const char *filename; /* DLL file name */
} builtin_dlls[MAX_DLLS];
static int nb_dlls;
static const IMAGE_NT_HEADERS *main_exe;
static load_dll_callback_t load_dll_callback;
static const char *build_dir;
static const char *default_dlldir;
static const char **dll_paths;
static unsigned int nb_dll_paths;
static int dll_path_maxlen;
extern void mmap_init(void);
extern const char *get_dlldir( const char **default_dlldir );
/* build the dll load path from the WINEDLLPATH variable */
static void build_dll_path(void)
{
if (path)
{
/* count how many path elements we need */
p = path;
while (*p)
{
while (*p == ':') p++;
if (!*p) break;
count++;
while (*p && *p != ':') p++;
}
}
nb_dll_paths = 0;
if (dlldir)
{
}
else if ((build_dir = wine_get_build_dir()))
{
}
if (count)
{
p = path;
while (*p)
{
while (*p == ':') *p++ = 0;
if (!*p) break;
dll_paths[nb_dll_paths] = p;
while (*p && *p != ':') p++;
nb_dll_paths++;
}
}
/* append default dll dir (if not empty) to path */
{
}
}
/* check if a given file can be opened */
static inline int file_exists( const char *name )
{
return (fd != -1);
}
{
}
/* get a filename from the next entry in the dll path */
{
switch(index)
{
case 0: /* try dlls dir with subdir prefix */
return path;
case 1: /* try programs dir with subdir prefix */
{
return path;
}
/* fall through */
default:
index -= 2;
if (index < nb_dll_paths)
break;
}
return NULL;
}
/* get a filename from the first entry in the dll path */
{
char *p;
/* store the name at the end of the buffer, followed by extension */
*p++ = '/';
return next_dll_path( context );
}
/* free the dll path context created by first_dll_path */
{
}
/* open a library for a given dll, searching in the dll path
* 'name' must be the Windows dll name (e.g. "kernel32.dll") */
{
struct dll_path_context context;
char *path;
*exists = 0;
{
}
free_dll_path( &context );
return ret;
}
/* adjust an array of pointers to make them into RVAs */
{
while (count--)
{
src++;
}
}
/* fixup an array of RVAs by adding the specified delta */
{
while (count--)
{
ptr++;
}
}
/* fixup RVAs in the import directory */
{
{
ptr = (UINT_PTR *)(base + (dir->u.OriginalFirstThunk ? dir->u.OriginalFirstThunk : dir->FirstThunk));
while (*ptr)
{
ptr++;
}
dir++;
}
}
/* fixup RVAs in the export directory */
{
}
/* fixup RVAs in the resource directory */
{
int i;
{
else
{
}
}
}
/* map a builtin dll in memory and fixup RVAs */
{
#ifdef HAVE_MMAP
unsigned int i;
+ sizeof(IMAGE_NT_HEADERS)
+ nb_sections * sizeof(IMAGE_SECTION_HEADER));
/* module address must be aligned on 64K boundary */
/* Build the DOS and NT headers */
dos->e_minalloc = 0;
#ifndef _WIN64
#endif
/* Build the code section */
sec++;
/* Build the data section */
sec++;
/* Build the import directory */
{
}
/* Build the resource directory */
{
}
/* Build the export directory */
{
}
return addr;
#else /* HAVE_MMAP */
return NULL;
#endif /* HAVE_MMAP */
}
/***********************************************************************
* __wine_get_main_environment
*
* Return an environment pointer to work around lack of environ variable.
* Only exported on Mac OS.
*/
char **__wine_get_main_environment(void)
{
#ifndef _MSC_VER
return environ;
#else
return _environ;
#endif
}
/***********************************************************************
* __wine_dll_register
*
* Register a built-in DLL descriptor.
*/
{
else
{
else
{
nb_dlls++;
}
}
}
/***********************************************************************
* wine_dll_set_callback
*
* Set the callback function for dll loading, and call it
* for all dlls that were implicitly loaded already.
*/
{
int i;
for (i = 0; i < nb_dlls; i++)
{
if (!nt) continue;
}
nb_dlls = 0;
}
/***********************************************************************
* wine_dll_load
*
* Load a builtin dll.
*/
{
int i;
/* callback must have been set already */
/* check if we have it in the list */
/* this can happen when initializing pre-loaded dlls in wine_dll_set_callback */
for (i = 0; i < nb_dlls; i++)
{
if (!builtin_dlls[i].nt) continue;
{
*file_exists = 1;
return (void *)1;
}
}
}
/***********************************************************************
* wine_dll_unload
*
* Unload a builtin dll.
*/
void wine_dll_unload( void *handle )
{
if (handle != (void *)1)
}
/***********************************************************************
* wine_dll_load_main_exe
*
* Try to load the .so for the main exe.
*/
int test_only, int *file_exists )
{
}
/***********************************************************************
* wine_dll_enum_load_path
*
* Enumerate the dll load path.
*/
const char *wine_dll_enum_load_path( unsigned int index )
{
}
/***********************************************************************
* wine_dll_get_owner
*
* Retrieve the name of the 32-bit owner dll for a 16-bit dll.
* Return 0 if OK, -1 on error.
*/
{
int ret = -1;
char *path;
struct dll_path_context context;
*exists = 0;
{
if (fd != -1)
{
*exists = 1;
ret = 0;
break;
}
}
free_dll_path( &context );
return ret;
}
/***********************************************************************
* set_max_limit
*
* Set a user limit to the maximum allowed value.
*/
static void set_max_limit( int limit )
{
#ifdef HAVE_SETRLIMIT
{
{
/* On Leopard, setrlimit(RLIMIT_NOFILE, ...) fails on attempts to set
* rlim_cur above OPEN_MAX (even if rlim_max > OPEN_MAX). */
{
}
#endif
}
}
#endif
}
/***********************************************************************
* wine_init
*
* Main Wine initialisation.
*/
{
struct dll_path_context context;
char *path;
void (*init_func)(void);
/* force a few limits that are set too low on some platforms */
#ifdef RLIMIT_NOFILE
#endif
#ifdef RLIMIT_AS
#endif
wine_init_argv0_path( argv[0] );
mmap_init();
{
{
/* if we didn't use the default dll dir, remove it from the search path */
break;
}
}
free_dll_path( &context );
if (!ntdll) return;
init_func();
}
/*
* These functions provide wrappers around dlopen() and associated
* functions. They work around a bug in glibc 2.1.x where calling
* a dl*() function after a previous dl*() function has failed
* without a dlerror() call between the two will cause a crash.
* They all take a pointer to a buffer that
* will receive the error description (from dlerror()). This
* parameter may be NULL if the error description is not required.
*/
#ifndef RTLD_FIRST
#define RTLD_FIRST 0
#endif
/***********************************************************************
* wine_dlopen
*/
{
#ifdef HAVE_DLOPEN
void *ret;
const char *s;
#ifdef __APPLE__
/* the Mac OS loader pretends to be able to load PE files, so avoid them here */
unsigned char magic[2];
if (fd != -1)
{
{
static const char msg[] = "MZ format";
return NULL;
}
}
#endif
#ifdef __sun
{
/* Solaris' brain damaged dlopen() treats ':' as a path separator */
}
else
#endif
s = dlerror();
{
if (s)
{
}
else error[0] = 0;
}
dlerror();
return ret;
#else
if (error)
{
static const char msg[] = "dlopen interface not detected by configure";
}
return NULL;
#endif
}
/***********************************************************************
* wine_dlsym
*/
{
#ifdef HAVE_DLOPEN
void *ret;
const char *s;
s = dlerror();
{
if (s)
{
}
else error[0] = 0;
}
dlerror();
return ret;
#else
if (error)
{
static const char msg[] = "dlopen interface not detected by configure";
}
return NULL;
#endif
}
/***********************************************************************
* wine_dlclose
*/
{
#ifdef HAVE_DLOPEN
int ret;
const char *s;
s = dlerror();
{
if (s)
{
}
else error[0] = 0;
}
dlerror();
return ret;
#else
if (error)
{
static const char msg[] = "dlopen interface not detected by configure";
}
return 1;
#endif
}