VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/components/xcDll.cpp@ 101942

Last change on this file since 101942 was 101942, checked in by vboxsync, 17 months ago

libs/xpcom: Remove unused code in xcDll.{cpp,h}, bugref:10545

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/* nsDll
39 *
40 * Abstraction of a Dll. Stores modifiedTime and size for easy detection of
41 * change in dll.
42 *
43 * dp Suresh <[email protected]>
44 */
45
46#include "xcDll.h"
47#include "nsDebug.h"
48#include "nsIComponentManager.h"
49#include "nsIComponentLoaderManager.h"
50#include "nsIModule.h"
51#include "nsILocalFile.h"
52#include "nsDirectoryServiceDefs.h"
53#include "nsDirectoryServiceUtils.h"
54#include "nsCOMPtr.h"
55#include "nsCRT.h"
56#include "nsString.h"
57#include "nsModule.h"
58#ifdef DEBUG
59#if defined(XP_MACOSX)
60#include <signal.h>
61#endif
62#endif /* defined(DEBUG) */
63
64#include "nsTraceRefcntImpl.h"
65
66#include "nsNativeComponentLoader.h"
67#ifdef VBOX_USE_IPRT_IN_XPCOM
68# include "nsMemory.h"
69#endif
70
71nsDll::nsDll(nsIFile *dllSpec, nsNativeComponentLoader *loader)
72 : m_dllSpec(do_QueryInterface(dllSpec)),
73 m_instance(NULL),
74 m_moduleObject(NULL),
75 m_loader(loader),
76 m_markForUnload(PR_FALSE)
77{
78 NS_ASSERTION(loader, "Null loader when creating a nsDLL");
79}
80
81nsDll::~nsDll(void)
82{
83 //#if DEBUG_dougt
84 // The dll gets deleted when the dllStore is destroyed. This happens on
85 // app shutdown. At that point, unloading dlls can cause crashes if we have
86 // - dll dependencies
87 // - callbacks
88 // - static dtors
89 // Hence turn it back on after all the above have been removed.
90 //Unload();
91 //#endif
92}
93
94void
95nsDll::GetDisplayPath(nsACString& aLeafName)
96{
97 m_dllSpec->GetNativeLeafName(aLeafName);
98
99 if (aLeafName.IsEmpty())
100 aLeafName.AssignLiteral("unknown!");
101}
102
103PRBool
104nsDll::HasChanged()
105{
106 nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(m_loader->mCompMgr);
107 if (!manager)
108 return PR_TRUE;
109
110 // If mod date has changed, then dll has changed
111 PRInt64 currentDate;
112 nsresult rv = m_dllSpec->GetLastModifiedTime(&currentDate);
113 if (NS_FAILED(rv))
114 return PR_TRUE;
115 PRBool changed = PR_TRUE;
116 manager->HasFileChanged(m_dllSpec, nsnull, currentDate, &changed);
117 return changed;
118}
119
120PRBool nsDll::Load(void)
121{
122 if (m_instance != NULL)
123 {
124 // Already loaded
125 return (PR_TRUE);
126 }
127
128 if (m_dllSpec)
129 {
130#ifdef NS_BUILD_REFCNT_LOGGING
131 nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
132#endif
133
134 // Load any library dependencies
135 // The Component Loader Manager may hold onto some extra data
136 // set by either the native component loader or the native
137 // component. We assume that this data is a space delimited
138 // listing of dependent libraries which are required to be
139 // loaded prior to us loading the given component. Once, the
140 // component is loaded into memory, we can release our hold
141 // on the dependent libraries with the assumption that the
142 // component library holds a reference via the OS so loader.
143 nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(m_loader->mCompMgr);
144 if (!manager)
145 return PR_TRUE;
146
147 nsXPIDLCString extraData;
148 manager->GetOptionalData(m_dllSpec, nsnull, getter_Copies(extraData));
149
150 nsVoidArray dependentLibArray;
151
152 // if there was any extra data, treat it as a listing of dependent libs
153 if (extraData != nsnull)
154 {
155 // all dependent libraries are suppose to be in the "gre" directory.
156 // note that the gre directory is the same as the "bin" directory,
157 // when there isn't a real "gre" found.
158
159 nsXPIDLCString path;
160 nsCOMPtr<nsIFile> file;
161 NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file));
162
163 if (!file)
164 return NS_ERROR_FAILURE;
165
166 // we are talking about a file in the GRE dir. Lets append something
167 // stupid right now, so that later we can just set the leaf name.
168 file->AppendNative(NS_LITERAL_CSTRING("dummy"));
169
170 char *buffer = (char *)nsMemory::Clone(extraData, strlen(extraData) + 1);
171 if (!buffer)
172 return NS_ERROR_OUT_OF_MEMORY;
173
174 char* newStr;
175 char *token = nsCRT::strtok(buffer, " ", &newStr);
176 while (token!=nsnull)
177 {
178 nsCStringKey key(token);
179 if (m_loader->mLoadedDependentLibs.Get(&key)) {
180 token = nsCRT::strtok(newStr, " ", &newStr);
181 continue;
182 }
183
184 m_loader->mLoadedDependentLibs.Put(&key, (void*)1);
185
186 nsXPIDLCString libpath;
187 file->SetNativeLeafName(nsDependentCString(token));
188 file->GetNativePath(path);
189 if (!path)
190 return NS_ERROR_FAILURE;
191
192 // Load this dependent library with the global flag and stash
193 // the result for later so that we can unload it.
194 PRLibSpec libSpec;
195 libSpec.type = PR_LibSpec_Pathname;
196
197 // if the depend library path starts with a / we are
198 // going to assume that it is a full path and should
199 // be loaded without prepending the gre diretory
200 // location. We could have short circuited the
201 // SetNativeLeafName above, but this is clearer and
202 // the common case is a relative path.
203
204 if (token[0] == '/')
205 libSpec.value.pathname = token;
206 else
207 libSpec.value.pathname = path;
208
209 PRLibrary* lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_LAZY|PR_LD_GLOBAL);
210 // if we couldn't load the dependent library. We did the best we
211 // can. Now just let us fail later if this really was a required
212 // dependency.
213 if (lib)
214 dependentLibArray.AppendElement((void*)lib);
215
216 token = nsCRT::strtok(newStr, " ", &newStr);
217 }
218 nsMemory::Free(buffer);
219 }
220
221 // load the component
222 nsCOMPtr<nsILocalFile> lf(do_QueryInterface(m_dllSpec));
223 NS_ASSERTION(lf, "nsIFile here must implement a nsILocalFile");
224 lf->Load(&m_instance);
225
226 // Unload any of library dependencies we loaded earlier. The assumption
227 // here is that the component will have a "internal" reference count to
228 // the dependency library we just loaded.
229 // XXX should we unload later - or even at all?
230 if (extraData != nsnull)
231 {
232 PRInt32 arrayCount = dependentLibArray.Count();
233 for (PRInt32 index = 0; index < arrayCount; index++)
234 PR_UnloadLibrary((PRLibrary*)dependentLibArray.ElementAt(index));
235 }
236
237#ifdef NS_BUILD_REFCNT_LOGGING
238 nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
239 if (m_instance) {
240 // Inform refcnt tracer of new library so that calls through the
241 // new library can be traced.
242 nsXPIDLCString displayPath;
243 GetDisplayPath(displayPath);
244 nsTraceRefcntImpl::LoadLibrarySymbols(displayPath.get(), m_instance);
245 }
246#endif
247 }
248
249 return ((m_instance == NULL) ? PR_FALSE : PR_TRUE);
250}
251
252PRBool nsDll::Unload(void)
253{
254 if (m_instance == NULL)
255 return (PR_FALSE);
256
257 // Shutdown the dll
258 Shutdown();
259
260#ifdef NS_BUILD_REFCNT_LOGGING
261 nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
262#endif
263 PRStatus ret = PR_UnloadLibrary(m_instance);
264#ifdef NS_BUILD_REFCNT_LOGGING
265 nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
266#endif
267
268 if (ret == PR_SUCCESS)
269 {
270 m_instance = NULL;
271 return (PR_TRUE);
272 }
273 else
274 return (PR_FALSE);
275}
276
277void * nsDll::FindSymbol(const char *symbol)
278{
279 if (symbol == NULL)
280 return (NULL);
281
282 // If not already loaded, load it now.
283 if (Load() != PR_TRUE)
284 return (NULL);
285
286 return(PR_FindSymbol(m_instance, symbol));
287}
288
289
290// Component dll specific functions
291nsresult nsDll::GetDllSpec(nsIFile **fsobj)
292{
293 NS_ASSERTION(m_dllSpec, "m_dllSpec NULL");
294 NS_ASSERTION(fsobj, "xcDll::GetModule : Null argument" );
295
296 *fsobj = m_dllSpec;
297 NS_ADDREF(*fsobj);
298 return NS_OK;
299}
300
301nsresult nsDll::GetModule(nsISupports *servMgr, nsIModule **cobj)
302{
303 // using the backpointer of the loader.
304 nsIComponentManager* compMgr = m_loader->mCompMgr;
305 NS_ASSERTION(compMgr, "Global Component Manager is null" );
306 if (!compMgr) return NS_ERROR_UNEXPECTED;
307
308 NS_ASSERTION(cobj, "xcDll::GetModule : Null argument" );
309
310 if (m_moduleObject)
311 {
312 NS_ADDREF(m_moduleObject);
313 *cobj = m_moduleObject;
314 return NS_OK;
315 }
316
317 // If not already loaded, load it now.
318 if (Load() != PR_TRUE) return NS_ERROR_FAILURE;
319
320 // We need a nsIFile for location
321 if (!m_dllSpec)
322 {
323 return NS_ERROR_FAILURE;
324 }
325
326 nsGetModuleProc proc =
327 (nsGetModuleProc) FindSymbol(NS_GET_MODULE_SYMBOL);
328
329 if (proc == NULL)
330 return NS_ERROR_FACTORY_NOT_LOADED;
331
332 nsresult rv = (*proc) (compMgr, m_dllSpec, &m_moduleObject);
333 if (NS_SUCCEEDED(rv))
334 {
335 NS_ADDREF(m_moduleObject);
336 *cobj = m_moduleObject;
337 }
338 return rv;
339}
340
341nsresult nsDll::Shutdown(void)
342{
343 // Release the module object if we got one
344 nsrefcnt refcnt;
345 if (m_moduleObject)
346 {
347 NS_RELEASE2(m_moduleObject, refcnt);
348 NS_ASSERTION(refcnt == 0, "Dll moduleObject refcount non zero");
349 }
350
351 return NS_OK;
352
353}
354
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette