Moved builtin dll registration to libwine.
Changed process initialization to not load imported dlls too early.
diff --git a/library/loader.c b/library/loader.c
new file mode 100644
index 0000000..95922d0
--- /dev/null
+++ b/library/loader.c
@@ -0,0 +1,203 @@
+/*
+ * Win32 builtin dlls support
+ *
+ * Copyright 2000 Alexandre Julliard
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#ifdef HAVE_DL_API
+#include <dlfcn.h>
+#endif
+
+#include "windef.h"
+#include "wine/library.h"
+
+#define MAX_DLLS 100
+
+static struct
+{
+ const IMAGE_NT_HEADERS *nt; /* NT header */
+ 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 char **dll_paths;
+static int nb_dll_paths;
+static int dll_path_maxlen;
+static int init_done;
+
+
+/* build the dll load path from the WINEDLLPATH variable */
+static void build_dll_path(void)
+{
+ int count = 0;
+ char *p, *path = getenv( "WINEDLLPATH" );
+
+ init_done = 1;
+ if (!path) return;
+ path = strdup(path);
+ p = path;
+ while (*p)
+ {
+ while (*p == ':') p++;
+ if (!*p) break;
+ count++;
+ while (*p && *p != ':') p++;
+ }
+
+ dll_paths = malloc( count * sizeof(*dll_paths) );
+ p = path;
+ nb_dll_paths = 0;
+ while (*p)
+ {
+ while (*p == ':') *p++ = 0;
+ if (!*p) break;
+ dll_paths[nb_dll_paths] = p;
+ while (*p && *p != ':') p++;
+ if (p - dll_paths[nb_dll_paths] > dll_path_maxlen)
+ dll_path_maxlen = p - dll_paths[nb_dll_paths];
+ nb_dll_paths++;
+ }
+}
+
+
+/* open a library for a given dll, searching in the dll path
+ * 'name' must be the Windows dll name (e.g. "kernel32.dll") */
+static void *dlopen_dll( const char *name )
+{
+#ifdef HAVE_DL_API
+ int i, namelen = strlen(name);
+ char *buffer, *p;
+ void *ret = NULL;
+
+ if (!init_done) build_dll_path();
+
+ /* check for .dll or .exe extension to remove */
+ if ((p = strrchr( name, '.' )))
+ {
+ if (!strcasecmp( p, ".dll" ) || !strcasecmp( p, ".exe" )) namelen -= 4;
+ }
+
+ buffer = malloc( dll_path_maxlen + namelen + 8 );
+
+ /* store the name at the end of the buffer, prefixed by /lib and followed by .so */
+ p = buffer + dll_path_maxlen;
+ memcpy( p, "/lib", 4 );
+ for (i = 0, p += 4; i < namelen; i++, p++) *p = tolower(name[i]);
+ memcpy( p, ".so", 4 );
+
+ for (i = 0; i < nb_dll_paths; i++)
+ {
+ int len = strlen(dll_paths[i]);
+ char *p = buffer + dll_path_maxlen - len;
+ memcpy( p, dll_paths[i], len );
+ if ((ret = dlopen( p, RTLD_NOW ))) break;
+ }
+
+ /* now try the default dlopen search path */
+ if (!ret) ret = dlopen( buffer + dll_path_maxlen + 1, RTLD_NOW );
+ free( buffer );
+ return ret;
+#else
+ return NULL;
+#endif
+}
+
+
+/***********************************************************************
+ * __wine_dll_register
+ *
+ * Register a built-in DLL descriptor.
+ */
+void __wine_dll_register( const IMAGE_NT_HEADERS *header, const char *filename )
+{
+ if (load_dll_callback) load_dll_callback( header, filename );
+ else
+ {
+ if (!(header->FileHeader.Characteristics & IMAGE_FILE_DLL))
+ main_exe = header;
+ else
+ {
+ assert( nb_dlls < MAX_DLLS );
+ builtin_dlls[nb_dlls].nt = header;
+ builtin_dlls[nb_dlls].filename = filename;
+ nb_dlls++;
+ }
+ }
+}
+
+
+/***********************************************************************
+ * wine_dll_set_callback
+ *
+ * Set the callback function for dll loading, and call it
+ * for all dlls that were implicitly loaded already.
+ */
+void wine_dll_set_callback( load_dll_callback_t load )
+{
+ int i;
+ load_dll_callback = load;
+ for (i = 0; i < nb_dlls; i++)
+ {
+ const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
+ if (!nt) continue;
+ builtin_dlls[i].nt = NULL;
+ load_dll_callback( nt, builtin_dlls[i].filename );
+ }
+ nb_dlls = 0;
+ if (main_exe) load_dll_callback( main_exe, "" );
+}
+
+
+/***********************************************************************
+ * wine_dll_load
+ *
+ * Load a builtin dll.
+ */
+void *wine_dll_load( const char *filename )
+{
+ int i;
+
+ /* callback must have been set already */
+ assert( load_dll_callback );
+
+ /* 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;
+ if (!strcasecmp( builtin_dlls[i].filename, filename ))
+ {
+ const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
+ builtin_dlls[i].nt = NULL;
+ load_dll_callback( nt, builtin_dlls[i].filename );
+ return (void *)1;
+ }
+ }
+ return dlopen_dll( filename );
+}
+
+
+/***********************************************************************
+ * wine_dll_unload
+ *
+ * Unload a builtin dll.
+ */
+void wine_dll_unload( void *handle )
+{
+#ifdef HAVE_DL_API
+ if (handle != (void *)1) dlclose( handle );
+#endif
+}