]> git.saurik.com Git - wxWidgets.git/blame - src/common/module.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / module.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
32d4c30a 2// Name: src/common/module.cpp
c801d85f
KB
3// Purpose: Modules initialization/destruction
4// Author: Wolfram Gloger/adapted by Guilhem Lavaux
5// Modified by:
6// Created: 04/11/98
7// RCS-ID: $Id$
8// Copyright: (c) Wolfram Gloger and Guilhem Lavaux
65571936 9// Licence: wxWindows licence
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
c801d85f
KB
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
32d4c30a
WS
16 #pragma hdrstop
17#endif
18
88a7a4e1
WS
19#include "wx/module.h"
20
32d4c30a
WS
21#ifndef WX_PRECOMP
22 #include "wx/hash.h"
88a7a4e1 23 #include "wx/intl.h"
e4db172a 24 #include "wx/log.h"
c801d85f
KB
25#endif
26
642c0eda 27#include "wx/listimpl.cpp"
8aa4edd2 28
9a83f860 29#define TRACE_MODULE wxT("module")
3b96fc2f 30
4115960d 31WX_DEFINE_LIST(wxModuleList)
c801d85f 32
e765d7ee 33wxIMPLEMENT_ABSTRACT_CLASS(wxModule, wxObject)
c801d85f 34
8aa4edd2 35wxModuleList wxModule::m_modules;
c801d85f
KB
36
37void wxModule::RegisterModule(wxModule* module)
38{
af266e5b 39 module->m_state = State_Registered;
8aa4edd2 40 m_modules.Append(module);
c801d85f
KB
41}
42
0b9ab0bd
RL
43void wxModule::UnregisterModule(wxModule* module)
44{
45 m_modules.DeleteObject(module);
df5168c4 46 delete module;
0b9ab0bd
RL
47}
48
c801d85f
KB
49// Collect up all module-derived classes, create an instance of each,
50// and register them.
8aa4edd2 51void wxModule::RegisterModules()
c801d85f 52{
644cb537
MB
53 for (wxClassInfo::const_iterator it = wxClassInfo::begin_classinfo(),
54 end = wxClassInfo::end_classinfo();
55 it != end; ++it)
c801d85f 56 {
644cb537
MB
57 const wxClassInfo* classInfo = *it;
58
80a46597 59 if ( classInfo->IsKindOf(wxCLASSINFO(wxModule)) &&
644cb537 60 (classInfo != (& (wxModule::ms_classInfo))) )
c801d85f 61 {
3b96fc2f
MB
62 wxLogTrace(TRACE_MODULE, wxT("Registering module %s"),
63 classInfo->GetClassName());
8aa4edd2 64 wxModule* module = (wxModule *)classInfo->CreateObject();
644cb537 65 wxModule::RegisterModule(module);
c801d85f 66 }
c801d85f 67 }
c801d85f
KB
68}
69
af266e5b
VZ
70bool wxModule::DoInitializeModule(wxModule *module,
71 wxModuleList &initializedModules)
c801d85f 72{
af266e5b 73 if ( module->m_state == State_Initializing )
c801d85f 74 {
af266e5b
VZ
75 wxLogError(_("Circular dependency involving module \"%s\" detected."),
76 module->GetClassInfo()->GetClassName());
77 return false;
78 }
79
80 module->m_state = State_Initializing;
81
d04a9fdf
VZ
82 // translate named dependencies to the normal ones first
83 if ( !module->ResolveNamedDependencies() )
84 return false;
85
af266e5b
VZ
86 const wxArrayClassInfo& dependencies = module->m_dependencies;
87
88 // satisfy module dependencies by loading them before the current module
89 for ( unsigned int i = 0; i < dependencies.size(); ++i )
90 {
91 wxClassInfo * cinfo = dependencies[i];
92
93 // Check if the module is already initialized
94 wxModuleList::compatibility_iterator node;
95 for ( node = initializedModules.GetFirst(); node; node = node->GetNext() )
8aa4edd2 96 {
af266e5b
VZ
97 if ( node->GetData()->GetClassInfo() == cinfo )
98 break;
99 }
100
101 if ( node )
102 {
103 // this dependency is already initialized, nothing to do
104 continue;
105 }
8c18c674 106
af266e5b
VZ
107 // find the module in the registered modules list
108 for ( node = m_modules.GetFirst(); node; node = node->GetNext() )
109 {
110 wxModule *moduleDep = node->GetData();
111 if ( moduleDep->GetClassInfo() == cinfo )
8aa4edd2 112 {
af266e5b
VZ
113 if ( !DoInitializeModule(moduleDep, initializedModules ) )
114 {
115 // failed to initialize a dependency, so fail this one too
116 return false;
117 }
118
119 break;
8aa4edd2 120 }
af266e5b 121 }
8aa4edd2 122
af266e5b
VZ
123 if ( !node )
124 {
125 wxLogError(_("Dependency \"%s\" of module \"%s\" doesn't exist."),
126 cinfo->GetClassName(),
127 module->GetClassInfo()->GetClassName());
4e32eea1 128 return false;
8aa4edd2 129 }
c801d85f 130 }
8aa4edd2 131
af266e5b
VZ
132 if ( !module->Init() )
133 {
134 wxLogError(_("Module \"%s\" initialization failed"),
135 module->GetClassInfo()->GetClassName());
136 return false;
137 }
138
139 wxLogTrace(TRACE_MODULE, wxT("Module \"%s\" initialized"),
140 module->GetClassInfo()->GetClassName());
141
142 module->m_state = State_Initialized;
143 initializedModules.Append(module);
144
4e32eea1 145 return true;
c801d85f
KB
146}
147
af266e5b
VZ
148// Initialize user-defined modules
149bool wxModule::InitializeModules()
c801d85f 150{
af266e5b
VZ
151 wxModuleList initializedModules;
152
153 for ( wxModuleList::compatibility_iterator node = m_modules.GetFirst();
154 node;
155 node = node->GetNext() )
156 {
157 wxModule *module = node->GetData();
158
159 // the module could have been already initialized as dependency of
160 // another one
161 if ( module->m_state == State_Registered )
162 {
163 if ( !DoInitializeModule( module, initializedModules ) )
164 {
165 // failed to initialize all modules, so clean up the already
166 // initialized ones
167 DoCleanUpModules(initializedModules);
168
169 return false;
170 }
171 }
172 }
173
174 // remember the real initialisation order
175 m_modules = initializedModules;
176
177 return true;
178}
179
180// Clean up all currently initialized modules
181void wxModule::DoCleanUpModules(const wxModuleList& modules)
182{
183 // cleanup user-defined modules in the reverse order compared to their
184 // initialization -- this ensures that dependencies are respected
185 for ( wxModuleList::compatibility_iterator node = modules.GetLast();
186 node;
187 node = node->GetPrevious() )
c801d85f 188 {
3b96fc2f
MB
189 wxLogTrace(TRACE_MODULE, wxT("Cleanup module %s"),
190 node->GetData()->GetClassInfo()->GetClassName());
af266e5b
VZ
191
192 wxModule * module = node->GetData();
193
194 wxASSERT_MSG( module->m_state == State_Initialized,
9a83f860 195 wxT("not initialized module being cleaned up") );
af266e5b
VZ
196
197 module->Exit();
198 module->m_state = State_Registered;
c801d85f 199 }
8aa4edd2 200
af266e5b 201 // clear all modules, even the non-initialized ones
df5168c4 202 WX_CLEAR_LIST(wxModuleList, m_modules);
c801d85f 203}
d04a9fdf
VZ
204
205bool wxModule::ResolveNamedDependencies()
206{
207 // first resolve required dependencies
208 for ( size_t i = 0; i < m_namedDependencies.size(); ++i )
209 {
210 wxClassInfo *info = wxClassInfo::FindClass(m_namedDependencies[i]);
211
212 if ( !info )
213 {
214 // required dependency not found
215 return false;
216 }
217
218 // add it even if it is not derived from wxModule because
219 // DoInitializeModule() will make sure a module with the same class
220 // info exists and fail if it doesn't
221 m_dependencies.Add(info);
222 }
223
224 return true;
225}