// Calls OnShutdown() on all plugins.
void PluginRegistry::NotifyShutdown()
{
	while (!basic_plugins.empty())
	{
		basic_plugins.back()->OnShutdown();
		basic_plugins.pop_back();
	}
	document_plugins.clear();
	element_plugins.clear();
}
        void Application::Terminate()
        {
            BOOST_ASSERT( m_IsInitialized == true );

            // Terminate the subsystems in the opposite order as they were registered.
            SubsystemList::reverse_iterator iter = m_Subsystems.rbegin();
            while ( iter != m_Subsystems.rend() )
            {
                SubsystemPtr subsystem = (*iter);
                subsystem->Terminate();

                ++iter;
            }

            m_Subsystems.clear();

            // Unload any previously loaded plug-ins
            PluginList plugins = m_Plugins;
            PluginList::iterator pluginIter = plugins.begin();
            while ( pluginIter != plugins.end() )
            {
                PluginPtr plugin = (*pluginIter);
                plugin->Terminate();

                UnloadPlugin( plugin );
                ++pluginIter;
            }

            plugins.clear();
            m_PluginsByName.clear();
            m_PluginsByFileName.clear();
            m_Plugins.clear();

            // Flush all the libraries.  At this point
            // there should be no residual pointers to objects
            // created in the library.
            m_DynamicLibSubsystem->Flush();

            m_IsInitialized = false;

            OnTerminated( EventArgs( *this ) );
        }
  void PluginRegistry::Impl::get_plugins_from_dir (PluginList& list, std::string const& dir)
  {
      list.clear ();

#if defined(VISUAL_OS_WIN32)
      std::string pattern = dir + "/*";

      WIN32_FIND_DATA file_data;
      HANDLE hList = FindFirstFile (pattern.c_str (), &file_data);

      if (hList == INVALID_HANDLE_VALUE) {
          FindClose (hList);
          return;
      }

      bool finished = false;

      while (!finished) {
          if (!(file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
              std::string full_path = dir + "/" + file_data.cFileName;

              if (str_has_suffix (full_path, ".dll")) {
                  PluginRef* ref = load_plugin_ref (full_path);

                  if (ref) {
                      list.push_back (ref);
                  }
              }
          }

          if (!FindNextFile (hList, &file_data)) {
              if (GetLastError () == ERROR_NO_MORE_FILES) {
                  finished = true;
              }
          }
      }

      FindClose (hList);
#else
      // NOTE: This typecast is needed for glibc versions that define
      // alphasort() as taking const void * arguments

      typedef int (*ScandirCompareFunc) (const struct dirent **, const struct dirent **);

      struct dirent **namelist;

      int n = scandir (dir.c_str (), &namelist, NULL, ScandirCompareFunc (alphasort));
      if (n < 0)
          return;

      // First two entries are '.' and '..'
      visual_mem_free (namelist[0]);
      visual_mem_free (namelist[1]);

      for (int i = 2; i < n; i++) {
          std::string full_path = dir + "/" + namelist[i]->d_name;

          if (str_has_suffix (full_path, ".so")) {
              PluginRef* ref = load_plugin_ref (full_path);

              if (ref) {
                  list.push_back (ref);
              }
          }

          visual_mem_free (namelist[i]);
      }

      visual_mem_free (namelist);

#endif
  }