+ // First, notify all modules that a module is about to be unloaded, so in case
+ // they pass execution to the soon to be unloaded module, it will happen now,
+ // i.e. before we unregister the services of the module being unloaded
+ FOREACH_MOD(OnUnloadModule, (mod));
+
+ std::map<std::string, Module*>::iterator modfind = Modules.find(mod->ModuleSourceFile);
+
+ std::vector<reference<ExtensionItem> > items;
+ ServerInstance->Extensions.BeginUnregister(modfind->second, items);
+ /* Give the module a chance to tidy out all its metadata */
+ for (chan_hash::iterator c = ServerInstance->chanlist->begin(); c != ServerInstance->chanlist->end(); c++)
+ {
+ mod->OnCleanup(TYPE_CHANNEL,c->second);
+ c->second->doUnhookExtensions(items);
+ const UserMembList* users = c->second->GetUsers();
+ for(UserMembCIter mi = users->begin(); mi != users->end(); mi++)
+ mi->second->doUnhookExtensions(items);
+ }
+ for (user_hash::iterator u = ServerInstance->Users->clientlist->begin(); u != ServerInstance->Users->clientlist->end(); u++)
+ {
+ mod->OnCleanup(TYPE_USER,u->second);
+ u->second->doUnhookExtensions(items);
+ }
+ for(char m='A'; m <= 'z'; m++)
+ {
+ ModeHandler* mh;
+ mh = ServerInstance->Modes->FindMode(m, MODETYPE_USER);
+ if (mh && mh->creator == mod)
+ this->DelService(*mh);
+ mh = ServerInstance->Modes->FindMode(m, MODETYPE_CHANNEL);
+ if (mh && mh->creator == mod)
+ this->DelService(*mh);
+ }
+ for(std::multimap<std::string, ServiceProvider*>::iterator i = DataProviders.begin(); i != DataProviders.end(); )
+ {
+ std::multimap<std::string, ServiceProvider*>::iterator curr = i++;
+ if (curr->second->creator == mod)
+ DataProviders.erase(curr);
+ }
+
+ dynamic_reference_base::reset_all();
+
+ DetachAll(mod);
+
+ Modules.erase(modfind);
+ ServerInstance->GlobalCulls.AddItem(mod);
+
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Module %s unloaded",mod->ModuleSourceFile.c_str());
+ this->ModCount--;
+ ServerInstance->ISupport.Build();