]> git.sesse.net Git - vlc/blobdiff - src/modules/modules.c
Win32: support loading plugins from directories with extra-ACP characters
[vlc] / src / modules / modules.c
index 413b7814f080cc3863fe645566ea6ac177044ebf..f1c197480c889696784cd14c3be460b829dc45bf 100644 (file)
 #include "vlc_arrays.h"
 
 #include "modules/modules.h"
-#include "modules/builtin.h"
 
 static module_bank_t *p_module_bank = NULL;
+static vlc_mutex_t module_lock = VLC_STATIC_MUTEX;
+
+int vlc_entry__main( module_t * );
 
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
 #ifdef HAVE_DYNAMIC_PLUGINS
-static void AllocateAllPlugins  ( vlc_object_t * );
-static void AllocatePluginDir   ( vlc_object_t *, const char *, int );
-static int  AllocatePluginFile  ( vlc_object_t *, char *, int64_t, int64_t );
-static module_t * AllocatePlugin( vlc_object_t *, char * );
+static void AllocateAllPlugins( vlc_object_t *, module_bank_t * );
+static void AllocatePluginDir( vlc_object_t *, module_bank_t *, const char *,
+                               unsigned );
+static int  AllocatePluginFile( vlc_object_t *, module_bank_t *, const char *,
+                                int64_t, int64_t );
+static module_t * AllocatePlugin( vlc_object_t *, const char * );
 #endif
 static int  AllocateBuiltinModule( vlc_object_t *, int ( * ) ( module_t * ) );
-static void DeleteModule ( module_t * );
+static void DeleteModule ( module_bank_t *, module_t * );
 #ifdef HAVE_DYNAMIC_PLUGINS
 static void   DupModule        ( module_t * );
 static void   UndupModule      ( module_t * );
@@ -120,7 +124,7 @@ void __module_InitBank( vlc_object_t *p_this )
 {
     module_bank_t *p_bank = NULL;
 
-    vlc_mutex_lock( &global_lock );
+    vlc_mutex_lock( &module_lock );
 
     if( p_module_bank == NULL )
     {
@@ -144,44 +148,56 @@ void __module_InitBank( vlc_object_t *p_this )
     else
         p_module_bank->i_usage++;
 
-    vlc_mutex_unlock( &global_lock );
+    /* We do retain the module bank lock until the plugins are loaded as well.
+     * This is ugly, this staged loading approach is needed: LibVLC gets
+     * some configuration parameters relevant to loading the plugins from
+     * the main (builtin) module. The module bank becomes shared read-only data
+     * once it is ready, so we need to fully serialize initialization.
+     * DO NOT UNCOMMENT the following line unless you managed to squeeze
+     * module_LoadPlugins() before you unlock the mutex. */
+    /*vlc_mutex_unlock( &module_lock );*/
 }
 
-
+#undef module_EndBank
 /**
- * End bank
- *
  * Unloads all unused plugin modules and empties the module
  * bank in case of success.
  * \param p_this vlc object structure
  * \return nothing
  */
-void __module_EndBank( vlc_object_t *p_this )
+void module_EndBank( vlc_object_t *p_this, bool b_plugins )
 {
-    module_bank_t *p_bank;
+    module_bank_t *p_bank = p_module_bank;
 
-    vlc_mutex_lock( &global_lock );
-    p_bank = p_module_bank;
     assert (p_bank != NULL);
+
+    /* Save the configuration */
+    if( !config_GetInt( p_this, "ignore-config" ) )
+        config_AutoSaveConfigFile( p_this );
+
+    /* If plugins were _not_ loaded, then the caller still has the bank lock
+     * from module_InitBank(). */
+    if( b_plugins )
+        vlc_mutex_lock( &module_lock );
+    /*else
+        vlc_assert_locked( &module_lock ); not for static mutexes :( */
+
     if( --p_bank->i_usage > 0 )
     {
-        vlc_mutex_unlock( &global_lock );
+        vlc_mutex_unlock( &module_lock );
         return;
     }
-    /*FIXME: For thread safety, we need to:
-    p_module_bank = NULL; - immediately, but that will crash the cache */
-    vlc_mutex_unlock( &global_lock );
-
-    /* Save the configuration */
-    config_AutoSaveConfigFile( p_this );
+    p_module_bank = NULL;
+    vlc_mutex_unlock( &module_lock );
 
 #ifdef HAVE_DYNAMIC_PLUGINS
-    if( p_bank->b_cache ) CacheSave( p_this, p_module_bank );
+    if( p_bank->b_cache )
+        CacheSave( p_this, p_bank );
     while( p_bank->i_loaded_cache-- )
     {
         if( p_bank->pp_loaded_cache[p_bank->i_loaded_cache] )
         {
-            DeleteModule(
+            DeleteModule( p_bank,
                     p_bank->pp_loaded_cache[p_bank->i_loaded_cache]->p_module );
             free( p_bank->pp_loaded_cache[p_bank->i_loaded_cache]->psz_file );
             free( p_bank->pp_loaded_cache[p_bank->i_loaded_cache] );
@@ -207,65 +223,39 @@ void __module_EndBank( vlc_object_t *p_this )
 #endif
 
     while( p_bank->head != NULL )
-        DeleteModule( p_bank->head );
+        DeleteModule( p_bank, p_bank->head );
 
-    p_module_bank = NULL; /* FIXME: do this inside the lock */
     free( p_bank );
 }
 
-/**
- * Load all modules which we built with.
- *
- * Fills the module bank structure with the builtin modules.
- * \param p_this vlc object structure
- * \return nothing
- */
-void __module_LoadBuiltins( vlc_object_t * p_this )
-{
-    vlc_mutex_lock( &global_lock );
-    if( p_module_bank->b_builtins )
-    {
-        vlc_mutex_unlock( &global_lock );
-        return;
-    }
-    p_module_bank->b_builtins = true;
-    vlc_mutex_unlock( &global_lock );
-
-    msg_Dbg( p_this, "checking builtin modules" );
-    ALLOCATE_ALL_BUILTINS();
-}
-
 #undef module_LoadPlugins
 /**
- * Load all plugins
- *
- * Load all plugin modules we can find.
+ * Loads module descriptions for all available plugins.
  * Fills the module bank structure with the plugin modules.
+ *
  * \param p_this vlc object structure
  * \return nothing
  */
 void module_LoadPlugins( vlc_object_t * p_this, bool b_cache_delete )
 {
-#ifdef HAVE_DYNAMIC_PLUGINS
-    vlc_mutex_lock( &global_lock );
-    if( p_module_bank->b_plugins )
-    {
-        vlc_mutex_unlock( &global_lock );
-        return;
-    }
-    p_module_bank->b_plugins = true;
-    vlc_mutex_unlock( &global_lock );
-
-    msg_Dbg( p_this, "checking plugin modules" );
+    module_bank_t *p_bank = p_module_bank;
 
-    if( config_GetInt( p_this, "plugins-cache" ) )
-        p_module_bank->b_cache = true;
+    assert( p_bank );
+    /*vlc_assert_locked( &module_lock ); not for static mutexes :( */
 
-    if( p_module_bank->b_cache || b_cache_delete )
-        CacheLoad( p_this, p_module_bank, b_cache_delete );
+#ifdef HAVE_DYNAMIC_PLUGINS
+    if( p_bank->i_usage == 1 )
+    {
+        msg_Dbg( p_this, "checking plugin modules" );
+        p_module_bank->b_cache = config_GetInt( p_this, "plugins-cache" ) > 0;
 
-    AllocateAllPlugins( p_this );
+        if( p_module_bank->b_cache || b_cache_delete )
+            CacheLoad( p_this, p_module_bank, b_cache_delete );
+        AllocateAllPlugins( p_this, p_module_bank );
+    }
 #endif
+    p_module_bank->b_plugins = true;
+    vlc_mutex_unlock( &module_lock );
 }
 
 /**
@@ -303,7 +293,7 @@ const char *module_get_name( const module_t *m, bool long_name )
     if( long_name && ( m->psz_longname != NULL) )
         return m->psz_longname;
 
-    return m->psz_shortname ?: m->psz_object_name;
+    return m->psz_shortname ? m->psz_shortname : m->psz_object_name;
 }
 
 /**
@@ -317,6 +307,28 @@ const char *module_get_help( const module_t *m )
     return m->psz_help;
 }
 
+/**
+ * Get the capability for a module
+ *
+ * \param m the module
+ * return the capability
+ */
+const char *module_get_capability( const module_t *m )
+{
+    return m->psz_capability;
+}
+
+/**
+ * Get the score for a module
+ *
+ * \param m the module
+ * return the score for the capability
+ */
+int module_get_score( const module_t *m )
+{
+    return m->i_score;
+}
+
 module_t *module_hold (module_t *m)
 {
     vlc_hold (&m->vlc_gc_data);
@@ -330,7 +342,7 @@ void module_release (module_t *m)
 
 /**
  * Frees the flat list of VLC modules.
- * @param list list obtained by module_list_get
+ * @param list list obtained by module_list_get()
  * @param length number of items on the list
  * @return nothing.
  */
@@ -357,6 +369,7 @@ module_t **module_list_get (size_t *n)
     module_t **tab = NULL;
     size_t i = 0;
 
+    assert (p_module_bank);
     for (module_t *mod = p_module_bank->head; mod; mod = mod->next)
     {
          module_t **nt;
@@ -381,7 +394,7 @@ module_t **module_list_get (size_t *n)
 typedef struct module_list_t
 {
     module_t *p_module;
-    uint16_t i_score;
+    int16_t  i_score;
     bool     b_force;
 } module_list_t;
 
@@ -522,11 +535,10 @@ module_t * __module_need( vlc_object_t *p_this, const char *psz_capability,
             if( b_strict )
                 continue;
         }
-        /* If we didn't require a shortcut, trash <= 0 scored plugins */
-        else if( p_module->i_score <= 0 )
-        {
+
+        /* Trash <= 0 scored plugins (they can only be selected by shortcut) */
+        if( p_module->i_score <= 0 )
             continue;
-        }
 
 found_shortcut:
         /* Store this new module */
@@ -543,7 +555,7 @@ found_shortcut:
 
     /* Sort candidates by descending score */
     qsort (p_list, count, sizeof (p_list[0]), modulecmp);
-    msg_Dbg( p_this, "looking for %s module: %i candidate%s", psz_capability,
+    msg_Dbg( p_this, "looking for %s module: %zu candidate%s", psz_capability,
              count, count == 1 ? "" : "s" );
 
     /* Parse the linked list and use the first successful module */
@@ -562,7 +574,7 @@ found_shortcut:
             if( p_new_module )
             {
                 CacheMerge( p_this, p_real, p_new_module );
-                DeleteModule( p_new_module );
+                DeleteModule( p_module_bank, p_new_module );
             }
         }
 #endif
@@ -601,6 +613,7 @@ found_shortcut:
     else if( count == 0 )
     {
         if( !strcmp( psz_capability, "access_demux" )
+         || !strcmp( psz_capability, "stream_filter" )
          || !strcmp( psz_capability, "vout_window" ) )
         {
             msg_Dbg( p_this, "no %s module matched \"%s\"",
@@ -659,7 +672,6 @@ void __module_unneed( vlc_object_t * p_this, module_t * p_module )
 /**
  * Get a pointer to a module_t given it's name.
  *
- * \param p_this vlc object structure
  * \param psz_name the name of the module
  * \return a pointer to the module or NULL in case of a failure
  */
@@ -688,7 +700,6 @@ module_t *module_find( const char * psz_name )
 /**
  * Tell if a module exists and release it in thic case
  *
- * \param p_this vlc object structure
  * \param psz_name th name of the module
  * \return TRUE if the module exists
  */
@@ -700,45 +711,83 @@ bool module_exists (const char * psz_name)
     return p_module != NULL;
 }
 
+/**
+ * Get a pointer to a module_t that matches a shortcut.
+ * This is a temporary hack for SD. Do not re-use (generally multiple modules
+ * can have the same shortcut, so this is *broken* - use module_need()!).
+ *
+ * \param psz_shortcut shortcut of the module
+ * \param psz_cap capability of the module
+ * \return a pointer to the module or NULL in case of a failure
+ */
+module_t *module_find_by_shortcut (const char *psz_shortcut)
+{
+    module_t **list, *module;
+
+    list = module_list_get (NULL);
+    if (!list)
+        return NULL;
+
+    for (size_t i = 0; (module = list[i]) != NULL; i++)
+    {
+        for (size_t j = 0;
+             (module->pp_shortcuts[j] != NULL) && (j < MODULE_SHORTCUT_MAX);
+             j++)
+        {
+            if (!strcmp (module->pp_shortcuts[j], psz_shortcut))
+            {
+                module_hold (module);
+                goto out;
+             }
+        }
+    }
+out:
+    module_list_free (list);
+    return module;
+}
+
 /**
  * GetModuleNamesForCapability
  *
  * Return a NULL terminated array with the names of the modules
  * that have a certain capability.
  * Free after uses both the string and the table.
- * \param p_this vlc object structure
  * \param psz_capability the capability asked
  * \param pppsz_longname an pointer to an array of string to contain
     the long names of the modules. If set to NULL the function don't use it.
  * \return the NULL terminated array
  */
-char ** __module_GetModulesNamesForCapability( vlc_object_t *p_this,
-                                               const char *psz_capability,
-                                               char ***pppsz_longname )
+char ** module_GetModulesNamesForCapability( const char *psz_capability,
+                                             char ***pppsz_longname )
 {
     size_t count = 0;
     char **psz_ret;
 
     module_t **list = module_list_get (NULL);
 
-    /* Do it in two passes : count the number of modules before */
+    /* Proceed in two passes: count the number of modules first */
     for (size_t i = 0; list[i]; i++)
     {
         module_t *p_module = list[i];
         const char *psz_module_capability = p_module->psz_capability;
 
-        if( psz_module_capability && !strcmp( psz_module_capability, psz_capability ) )
+        if( psz_module_capability
+         && !strcmp( psz_module_capability, psz_capability ) )
             count++;
     }
 
+    /* Then get the names */
     psz_ret = malloc( sizeof(char*) * (count+1) );
     if( pppsz_longname )
         *pppsz_longname = malloc( sizeof(char*) * (count+1) );
     if( !psz_ret || ( pppsz_longname && *pppsz_longname == NULL ) )
     {
         free( psz_ret );
-        free( *pppsz_longname );
-        *pppsz_longname = NULL;
+        if( pppsz_longname )
+        {
+            free( *pppsz_longname );
+            *pppsz_longname = NULL;
+        }
         module_list_free (list);
         return NULL;
     }
@@ -748,16 +797,17 @@ char ** __module_GetModulesNamesForCapability( vlc_object_t *p_this,
         module_t *p_module = list[i];
         const char *psz_module_capability = p_module->psz_capability;
 
-        if( psz_module_capability && !strcmp( psz_module_capability, psz_capability ) )
+        if( psz_module_capability
+         && !strcmp( psz_module_capability, psz_capability ) )
         {
-            int k = -1; /* hack to handle submodules properly */
-            if( p_module->b_submodule )
-            {
-                while( p_module->pp_shortcuts[++k] != NULL );
-                k--;
-            }
-            psz_ret[j] = strdup( k>=0?p_module->pp_shortcuts[k]
-                                     :p_module->psz_object_name );
+            /* Explicit hack: Use the last shortcut. It _should_ be
+             * different from the object name, at least if the object
+             * contains multiple submodules with the same capability. */
+            unsigned k = 0;
+            while( p_module->pp_shortcuts[k] != NULL )
+                k++;
+            assert( k > 0); /* pp_shortcuts[0] is always set */
+            psz_ret[j] = strdup( p_module->pp_shortcuts[k - 1] );
             if( pppsz_longname )
                 (*pppsz_longname)[j] = strdup( module_get_name( p_module, true ) );
             j++;
@@ -857,7 +907,7 @@ static char * copy_next_paths_token( char * paths, char ** remaining_paths )
         else
             path[done++] = paths[i];
     }
-    path[done++] = 0;
+    path[done] = 0;
 
     /* Return the remaining paths */
     if( remaining_paths ) {
@@ -867,13 +917,13 @@ static char * copy_next_paths_token( char * paths, char ** remaining_paths )
     return path;
 }
 
-extern char *psz_vlcpath = NULL;
+char *psz_vlcpath = NULL;
 
 /*****************************************************************************
  * AllocateAllPlugins: load all plugin modules we can find.
  *****************************************************************************/
 #ifdef HAVE_DYNAMIC_PLUGINS
-static void AllocateAllPlugins( vlc_object_t *p_this )
+static void AllocateAllPlugins( vlc_object_t *p_this, module_bank_t *p_bank )
 {
     const char *vlcpath = psz_vlcpath;
     int count,i;
@@ -912,7 +962,7 @@ static void AllocateAllPlugins( vlc_object_t *p_this )
         msg_Dbg( p_this, "recursively browsing `%s'", path );
 
         /* Don't go deeper than 5 subdirectories */
-        AllocatePluginDir( p_this, path, 5 );
+        AllocatePluginDir( p_this, p_bank, path, 5 );
 
         free( path );
     }
@@ -924,181 +974,51 @@ static void AllocateAllPlugins( vlc_object_t *p_this )
 /*****************************************************************************
  * AllocatePluginDir: recursively parse a directory to look for plugins
  *****************************************************************************/
-static void AllocatePluginDir( vlc_object_t *p_this, const char *psz_dir,
-                               int i_maxdepth )
+static void AllocatePluginDir( vlc_object_t *p_this, module_bank_t *p_bank,
+                               const char *psz_dir, unsigned i_maxdepth )
 {
-/* FIXME: Needs to be ported to wide char on ALL Windows builds */
-#ifdef WIN32
-# undef opendir
-# undef closedir
-# undef readdir
-#endif
-#if defined( UNDER_CE ) || defined( _MSC_VER )
-#ifdef UNDER_CE
-    wchar_t psz_wpath[MAX_PATH + 256];
-    wchar_t psz_wdir[MAX_PATH];
-#endif
-    char psz_path[MAX_PATH + 256];
-    WIN32_FIND_DATA finddata;
-    HANDLE handle;
-    int rc;
-#else
-    int    i_dirlen;
-    DIR *  dir;
-    struct dirent * file;
-#endif
-    char * psz_file;
-
-    if( p_this->p_libvlc->b_die || i_maxdepth < 0 )
-    {
+    if( i_maxdepth == 0 )
         return;
-    }
 
-#if defined( UNDER_CE ) || defined( _MSC_VER )
-#ifdef UNDER_CE
-    MultiByteToWideChar( CP_ACP, 0, psz_dir, -1, psz_wdir, MAX_PATH );
-
-    rc = GetFileAttributes( psz_wdir );
-    if( rc<0 || !(rc&FILE_ATTRIBUTE_DIRECTORY) ) return; /* Not a directory */
-
-    /* Parse all files in the directory */
-    swprintf( psz_wpath, L"%ls\\*", psz_wdir );
-#else
-    rc = GetFileAttributes( psz_dir );
-    if( rc<0 || !(rc&FILE_ATTRIBUTE_DIRECTORY) ) return; /* Not a directory */
-#endif
-
-    /* Parse all files in the directory */
-    sprintf( psz_path, "%s\\*", psz_dir );
-
-#ifdef UNDER_CE
-    handle = FindFirstFile( psz_wpath, &finddata );
-#else
-    handle = FindFirstFile( psz_path, &finddata );
-#endif
-    if( handle == INVALID_HANDLE_VALUE )
-    {
-        /* Empty directory */
+    DIR *dh = utf8_opendir (psz_dir);
+    if (dh == NULL)
         return;
-    }
 
     /* Parse the directory and try to load all files it contains. */
-    do
+    for (;;)
     {
-#ifdef UNDER_CE
-        unsigned int i_len = wcslen( finddata.cFileName );
-        swprintf( psz_wpath, L"%ls\\%ls", psz_wdir, finddata.cFileName );
-        sprintf( psz_path, "%s\\%ls", psz_dir, finddata.cFileName );
-#else
-        unsigned int i_len = strlen( finddata.cFileName );
-        sprintf( psz_path, "%s\\%s", psz_dir, finddata.cFileName );
-#endif
-
-        /* Skip ".", ".." */
-        if( !*finddata.cFileName || !strcmp( finddata.cFileName, "." )
-         || !strcmp( finddata.cFileName, ".." ) )
-        {
-            if( !FindNextFile( handle, &finddata ) ) break;
-            continue;
-        }
-
-#ifdef UNDER_CE
-        if( GetFileAttributes( psz_wpath ) & FILE_ATTRIBUTE_DIRECTORY )
-#else
-        if( GetFileAttributes( psz_path ) & FILE_ATTRIBUTE_DIRECTORY )
-#endif
-        {
-            AllocatePluginDir( p_this, psz_path, i_maxdepth - 1 );
-        }
-        else if( i_len > strlen( LIBEXT )
-                  /* We only load files ending with LIBEXT */
-                  && !strncasecmp( psz_path + strlen( psz_path)
-                                   - strlen( LIBEXT ),
-                                   LIBEXT, strlen( LIBEXT ) ) )
-        {
-            WIN32_FILE_ATTRIBUTE_DATA attrbuf;
-            int64_t i_time = 0, i_size = 0;
-
-#ifdef UNDER_CE
-            if( GetFileAttributesEx( psz_wpath, GetFileExInfoStandard,
-                                     &attrbuf ) )
-#else
-            if( GetFileAttributesEx( psz_path, GetFileExInfoStandard,
-                                     &attrbuf ) )
-#endif
-            {
-                i_time = attrbuf.ftLastWriteTime.dwHighDateTime;
-                i_time <<= 32;
-                i_time |= attrbuf.ftLastWriteTime.dwLowDateTime;
-                i_size = attrbuf.nFileSizeHigh;
-                i_size <<= 32;
-                i_size |= attrbuf.nFileSizeLow;
-            }
-            psz_file = psz_path;
-
-            AllocatePluginFile( p_this, psz_file, i_time, i_size );
-        }
-    }
-    while( !p_this->p_libvlc->b_die && FindNextFile( handle, &finddata ) );
-
-    /* Close the directory */
-    FindClose( handle );
-
-#else
-    dir = opendir( psz_dir );
-    if( !dir )
-    {
-        return;
-    }
-
-    i_dirlen = strlen( psz_dir );
+        char *file = utf8_readdir (dh), *path;
+        struct stat st;
 
-    /* Parse the directory and try to load all files it contains. */
-    while( !p_this->p_libvlc->b_die && ( file = readdir( dir ) ) )
-    {
-        struct stat statbuf;
-        unsigned int i_len;
-        int i_stat;
+        if (file == NULL)
+            break;
 
         /* Skip ".", ".." */
-        if( !*file->d_name || !strcmp( file->d_name, "." )
-         || !strcmp( file->d_name, ".." ) )
+        if (!strcmp (file, ".") || !strcmp (file, ".."))
         {
+            free (file);
             continue;
         }
 
-        i_len = strlen( file->d_name );
-        psz_file = malloc( i_dirlen + 1 + i_len + 1 );
-        sprintf( psz_file, "%s"DIR_SEP"%s", psz_dir, file->d_name );
-
-        i_stat = stat( psz_file, &statbuf );
-        if( !i_stat && statbuf.st_mode & S_IFDIR )
-        {
-            AllocatePluginDir( p_this, psz_file, i_maxdepth - 1 );
-        }
-        else if( i_len > strlen( LIBEXT )
-                  /* We only load files ending with LIBEXT */
-                  && !strncasecmp( file->d_name + i_len - strlen( LIBEXT ),
-                                   LIBEXT, strlen( LIBEXT ) ) )
-        {
-            int64_t i_time = 0, i_size = 0;
-
-            if( !i_stat )
-            {
-                i_time = statbuf.st_mtime;
-                i_size = statbuf.st_size;
-            }
-
-            AllocatePluginFile( p_this, psz_file, i_time, i_size );
-        }
+        const int pathlen = asprintf (&path, "%s"DIR_SEP"%s", psz_dir, file);
+        free (file);
+        if (pathlen == -1 || utf8_stat (path, &st))
+            continue;
 
-        free( psz_file );
+        if (S_ISDIR (st.st_mode))
+            /* Recurse into another directory */
+            AllocatePluginDir (p_this, p_bank, path, i_maxdepth - 1);
+        else
+        if (S_ISREG (st.st_mode)
+         && ((size_t)pathlen >= strlen (LIBEXT))
+         && !strncasecmp (path + pathlen - strlen (LIBEXT), LIBEXT,
+                          strlen (LIBEXT)))
+            /* ^^ We only load files ending with LIBEXT */
+            AllocatePluginFile (p_this, p_bank, path, st.st_mtime, st.st_size);
+
+        free (path);
     }
-
-    /* Close the directory */
-    closedir( dir );
-
-#endif
+    closedir (dh);
 }
 
 /*****************************************************************************
@@ -1108,7 +1028,8 @@ static void AllocatePluginDir( vlc_object_t *p_this, const char *psz_dir,
  * for its information data. The module can then be handled by module_need
  * and module_unneed. It can be removed by DeleteModule.
  *****************************************************************************/
-static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file,
+static int AllocatePluginFile( vlc_object_t * p_this, module_bank_t *p_bank,
+                               const char *psz_file,
                                int64_t i_file_time, int64_t i_file_size )
 {
     module_t * p_module = NULL;
@@ -1117,76 +1038,71 @@ static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file,
     /*
      * Check our plugins cache first then load plugin if needed
      */
-    p_cache_entry =
-        CacheFind( p_module_bank, psz_file, i_file_time, i_file_size );
-
+    p_cache_entry = CacheFind( p_bank, psz_file, i_file_time, i_file_size );
     if( !p_cache_entry )
     {
         p_module = AllocatePlugin( p_this, psz_file );
     }
     else
+    /* If junk dll, don't try to load it */
+    if( p_cache_entry->b_junk )
+        return -1;
+    else
     {
-        /* If junk dll, don't try to load it */
-        if( p_cache_entry->b_junk )
-        {
-            p_module = NULL;
-        }
-        else
-        {
-            module_config_t *p_item = NULL, *p_end = NULL;
+        module_config_t *p_item = NULL, *p_end = NULL;
 
-            p_module = p_cache_entry->p_module;
-            p_module->b_loaded = false;
+        p_module = p_cache_entry->p_module;
+        p_module->b_loaded = false;
 
-            /* For now we force loading if the module's config contains
-             * callbacks or actions.
-             * Could be optimized by adding an API call.*/
-            for( p_item = p_module->p_config, p_end = p_item + p_module->confsize;
-                 p_item < p_end; p_item++ )
+        /* For now we force loading if the module's config contains
+         * callbacks or actions.
+         * Could be optimized by adding an API call.*/
+        for( p_item = p_module->p_config, p_end = p_item + p_module->confsize;
+             p_item < p_end; p_item++ )
+        {
+            if( p_item->pf_callback || p_item->i_action )
             {
-                if( p_item->pf_callback || p_item->i_action )
-                {
-                    p_module = AllocatePlugin( p_this, psz_file );
-                    break;
-                }
+                p_module = AllocatePlugin( p_this, psz_file );
+                break;
             }
-            if( p_module == p_cache_entry->p_module )
-                p_cache_entry->b_used = true;
         }
+        if( p_module == p_cache_entry->p_module )
+            p_cache_entry->b_used = true;
     }
 
-    if( p_module )
-    {
-        /* Everything worked fine !
-         * The module is ready to be added to the list. */
-        p_module->b_builtin = false;
-
-        /* msg_Dbg( p_this, "plugin \"%s\", %s",
-                    p_module->psz_object_name, p_module->psz_longname ); */
-        p_module->next = p_module_bank->head;
-        p_module_bank->head = p_module;
-
-        if( !p_module_bank->b_cache )
-            return 0;
-
-#define p_bank p_module_bank
-        /* Add entry to cache */
-        p_bank->pp_cache =
-            realloc( p_bank->pp_cache, (p_bank->i_cache + 1) * sizeof(void *) );
-        p_bank->pp_cache[p_bank->i_cache] = malloc( sizeof(module_cache_t) );
-        if( !p_bank->pp_cache[p_bank->i_cache] )
-            return -1;
-        p_bank->pp_cache[p_bank->i_cache]->psz_file = strdup( psz_file );
-        p_bank->pp_cache[p_bank->i_cache]->i_time = i_file_time;
-        p_bank->pp_cache[p_bank->i_cache]->i_size = i_file_size;
-        p_bank->pp_cache[p_bank->i_cache]->b_junk = p_module ? 0 : 1;
-        p_bank->pp_cache[p_bank->i_cache]->b_used = true;
-        p_bank->pp_cache[p_bank->i_cache]->p_module = p_module;
-        p_bank->i_cache++;
-#undef p_bank
-    }
+    if( p_module == NULL )
+        return -1;
+
+    /* Everything worked fine !
+     * The module is ready to be added to the list. */
+    p_module->b_builtin = false;
+
+    /* msg_Dbg( p_this, "plugin \"%s\", %s",
+                p_module->psz_object_name, p_module->psz_longname ); */
+    p_module->next = p_bank->head;
+    p_bank->head = p_module;
 
-    return p_module ? 0 : -1;
+    if( !p_module_bank->b_cache )
+        return 0;
+
+    /* Add entry to cache */
+    module_cache_t **pp_cache = p_bank->pp_cache;
+
+    pp_cache = realloc( pp_cache, (p_bank->i_cache + 1) * sizeof(void *) );
+    if( pp_cache == NULL )
+        return -1;
+    pp_cache[p_bank->i_cache] = malloc( sizeof(module_cache_t) );
+    if( pp_cache[p_bank->i_cache] == NULL )
+        return -1;
+    pp_cache[p_bank->i_cache]->psz_file = strdup( psz_file );
+    pp_cache[p_bank->i_cache]->i_time = i_file_time;
+    pp_cache[p_bank->i_cache]->i_size = i_file_size;
+    pp_cache[p_bank->i_cache]->b_junk = p_module ? 0 : 1;
+    pp_cache[p_bank->i_cache]->b_used = true;
+    pp_cache[p_bank->i_cache]->p_module = p_module;
+    p_bank->pp_cache = pp_cache;
+    p_bank->i_cache++;
+    return  0;
 }
 
 /*****************************************************************************
@@ -1196,7 +1112,7 @@ static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file,
  * for its information data. The module can then be handled by module_need
  * and module_unneed. It can be removed by DeleteModule.
  *****************************************************************************/
-static module_t * AllocatePlugin( vlc_object_t * p_this, char * psz_file )
+static module_t * AllocatePlugin( vlc_object_t * p_this, const char *psz_file )
 {
     module_t * p_module = NULL;
     module_handle_t handle;
@@ -1213,8 +1129,7 @@ static module_t * AllocatePlugin( vlc_object_t * p_this, char * psz_file )
         return NULL;
     }
 
-    /* We need to fill these since they may be needed by module_Call() */
-    p_module->psz_filename = psz_file;
+    p_module->psz_filename = strdup( psz_file );
     p_module->handle = handle;
     p_module->b_loaded = true;
 
@@ -1222,13 +1137,13 @@ static module_t * AllocatePlugin( vlc_object_t * p_this, char * psz_file )
     if( module_Call( p_this, p_module ) != 0 )
     {
         /* We couldn't call module_init() */
+        free( p_module->psz_filename );
         module_release( p_module );
         module_Unload( handle );
         return NULL;
     }
 
     DupModule( p_module );
-    p_module->psz_filename = strdup( p_module->psz_filename );
 
     /* Everything worked fine ! The module is ready to be added to the list. */
     p_module->b_builtin = false;
@@ -1335,12 +1250,12 @@ static int AllocateBuiltinModule( vlc_object_t * p_this,
  *****************************************************************************
  * This function can only be called if the module isn't being used.
  *****************************************************************************/
-static void DeleteModule( module_t * p_module )
+static void DeleteModule( module_bank_t *p_bank, module_t * p_module )
 {
     assert( p_module );
 
     /* Unlist the module (if it is in the list) */
-    module_t **pp_self = &p_module_bank->head;
+    module_t **pp_self = &p_bank->head;
     while (*pp_self != NULL && *pp_self != p_module)
         pp_self = &((*pp_self)->next);
     if (*pp_self)