Back to index

lightning-sunbird  0.9+nobinonly
nsXPCOMGlue.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* vim:set ts=4 sw=4 et cindent: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsXPCOMGlue.h"
00040 #include "nsGlueLinking.h"
00041 
00042 #include "nspr.h"
00043 #include "nsDebug.h"
00044 #include "nsIServiceManager.h"
00045 #include "nsGREDirServiceProvider.h"
00046 #include "nsXPCOMPrivate.h"
00047 #include "nsCOMPtr.h"
00048 #include <stdlib.h>
00049 #include <stdio.h>
00050 
00051 #ifdef XP_WIN
00052 #include <windows.h>
00053 #include <mbstring.h>
00054 #include <malloc.h>
00055 #define snprintf _snprintf
00056 #endif
00057 
00058 // functions provided by nsDebug.cpp
00059 nsresult GlueStartupDebug();
00060 void GlueShutdownDebug();
00061 
00062 static XPCOMFunctions xpcomFunctions;
00063 
00064 extern "C"
00065 nsresult XPCOMGlueStartup(const char* xpcomFile)
00066 {
00067     xpcomFunctions.version = XPCOM_GLUE_VERSION;
00068     xpcomFunctions.size    = sizeof(XPCOMFunctions);
00069 
00070     GetFrozenFunctionsFunc func = nsnull;
00071 
00072     if (!xpcomFile)
00073         xpcomFile = XPCOM_DLL;
00074 
00075     func = XPCOMGlueLoad(xpcomFile);
00076 
00077     if (!func)
00078         return NS_ERROR_FAILURE;
00079 
00080     nsresult rv = (*func)(&xpcomFunctions, nsnull);
00081     if (NS_FAILED(rv)) {
00082         XPCOMGlueUnload();
00083         return rv;
00084     }
00085 
00086     rv = GlueStartupDebug();
00087     if (NS_FAILED(rv)) {
00088         memset(&xpcomFunctions, 0, sizeof(xpcomFunctions));
00089         XPCOMGlueUnload();
00090         return rv;
00091     }
00092 
00093     return NS_OK;
00094 }
00095 
00096 #if defined(XP_WIN) || defined(XP_OS2)
00097 #define READ_TEXTMODE "t"
00098 #else
00099 #define READ_TEXTMODE
00100 #endif
00101 
00102 void
00103 XPCOMGlueLoadDependentLibs(const char *xpcomDir, DependentLibsCallback cb)
00104 {
00105     char buffer[MAXPATHLEN];
00106     sprintf(buffer, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DEPENDENT_LIBS_LIST,
00107             xpcomDir);
00108 
00109     FILE *flist = fopen(buffer, "r" READ_TEXTMODE);
00110     if (!flist)
00111         return;
00112 
00113     while (fgets(buffer, sizeof(buffer), flist)) {
00114         int l = strlen(buffer);
00115 
00116         // ignore empty lines and comments
00117         if (l == 0 || *buffer == '#')
00118             continue;
00119 
00120         // cut the trailing newline, if present
00121         if (buffer[l - 1] == '\n')
00122             buffer[l - 1] = '\0';
00123 
00124         char buffer2[MAXPATHLEN];
00125         snprintf(buffer2, sizeof(buffer2),
00126                  "%s" XPCOM_FILE_PATH_SEPARATOR "%s",
00127                  xpcomDir, buffer);
00128         cb(buffer2);
00129     }
00130 
00131     fclose(flist);
00132 }
00133 
00134 extern "C"
00135 nsresult XPCOMGlueShutdown()
00136 {
00137     GlueShutdownDebug();
00138 
00139     XPCOMGlueUnload();
00140     
00141     memset(&xpcomFunctions, 0, sizeof(xpcomFunctions));
00142     return NS_OK;
00143 }
00144 
00145 extern "C" NS_COM nsresult
00146 NS_InitXPCOM2(nsIServiceManager* *result, 
00147               nsIFile* binDirectory,
00148               nsIDirectoryServiceProvider* appFileLocationProvider)
00149 {
00150     if (!xpcomFunctions.init)
00151         return NS_ERROR_NOT_INITIALIZED;
00152     return xpcomFunctions.init(result, binDirectory, appFileLocationProvider);
00153 }
00154 
00155 extern "C" NS_COM nsresult
00156 NS_InitXPCOM3(nsIServiceManager* *result,
00157               nsIFile* binDirectory,
00158               nsIDirectoryServiceProvider* appFileLocationProvider,
00159               nsStaticModuleInfo const *staticComponents,
00160               PRUint32 componentCount)
00161 {
00162     if (!xpcomFunctions.init3)
00163         return NS_ERROR_NOT_INITIALIZED;
00164     return xpcomFunctions.init3(result, binDirectory, appFileLocationProvider,
00165                                 staticComponents, componentCount);
00166 }
00167 
00168 extern "C" NS_COM nsresult
00169 NS_ShutdownXPCOM(nsIServiceManager* servMgr)
00170 {
00171     if (!xpcomFunctions.shutdown)
00172         return NS_ERROR_NOT_INITIALIZED;
00173     return xpcomFunctions.shutdown(servMgr);
00174 }
00175 
00176 extern "C" NS_COM nsresult
00177 NS_GetServiceManager(nsIServiceManager* *result)
00178 {
00179     if (!xpcomFunctions.getServiceManager)
00180         return NS_ERROR_NOT_INITIALIZED;
00181     return xpcomFunctions.getServiceManager(result);
00182 }
00183 
00184 extern "C" NS_COM nsresult
00185 NS_GetComponentManager(nsIComponentManager* *result)
00186 {
00187     if (!xpcomFunctions.getComponentManager)
00188         return NS_ERROR_NOT_INITIALIZED;
00189     return xpcomFunctions.getComponentManager(result);
00190 }
00191 
00192 extern "C" NS_COM nsresult
00193 NS_GetComponentRegistrar(nsIComponentRegistrar* *result)
00194 {
00195     if (!xpcomFunctions.getComponentRegistrar)
00196         return NS_ERROR_NOT_INITIALIZED;
00197     return xpcomFunctions.getComponentRegistrar(result);
00198 }
00199 
00200 extern "C" NS_COM nsresult
00201 NS_GetMemoryManager(nsIMemory* *result)
00202 {
00203     if (!xpcomFunctions.getMemoryManager)
00204         return NS_ERROR_NOT_INITIALIZED;
00205     return xpcomFunctions.getMemoryManager(result);
00206 }
00207 
00208 extern "C" NS_COM nsresult
00209 NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
00210 {
00211     if (!xpcomFunctions.newLocalFile)
00212         return NS_ERROR_NOT_INITIALIZED;
00213     return xpcomFunctions.newLocalFile(path, followLinks, result);
00214 }
00215 
00216 extern "C" NS_COM nsresult
00217 NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result)
00218 {
00219     if (!xpcomFunctions.newNativeLocalFile)
00220         return NS_ERROR_NOT_INITIALIZED;
00221     return xpcomFunctions.newNativeLocalFile(path, followLinks, result);
00222 }
00223 
00224 extern "C" NS_COM nsresult
00225 NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority)
00226 {
00227     if (!xpcomFunctions.registerExitRoutine)
00228         return NS_ERROR_NOT_INITIALIZED;
00229     return xpcomFunctions.registerExitRoutine(exitRoutine, priority);
00230 }
00231 
00232 extern "C" NS_COM nsresult
00233 NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine)
00234 {
00235     if (!xpcomFunctions.unregisterExitRoutine)
00236         return NS_ERROR_NOT_INITIALIZED;
00237     return xpcomFunctions.unregisterExitRoutine(exitRoutine);
00238 }
00239 
00240 extern "C" NS_COM nsresult
00241 NS_GetDebug(nsIDebug* *result)
00242 {
00243     if (!xpcomFunctions.getDebug)
00244         return NS_ERROR_NOT_INITIALIZED;
00245     return xpcomFunctions.getDebug(result);
00246 }
00247 
00248 
00249 extern "C" NS_COM nsresult
00250 NS_GetTraceRefcnt(nsITraceRefcnt* *result)
00251 {
00252     if (!xpcomFunctions.getTraceRefcnt)
00253         return NS_ERROR_NOT_INITIALIZED;
00254     return xpcomFunctions.getTraceRefcnt(result);
00255 }
00256 
00257 
00258 extern "C" NS_COM nsresult
00259 NS_StringContainerInit(nsStringContainer &aStr)
00260 {
00261     if (!xpcomFunctions.stringContainerInit)
00262         return NS_ERROR_NOT_INITIALIZED;
00263     return xpcomFunctions.stringContainerInit(aStr);
00264 }
00265 
00266 extern "C" NS_COM nsresult
00267 NS_StringContainerInit2(nsStringContainer &aStr,
00268                         const PRUnichar   *aData,
00269                         PRUint32           aDataLength,
00270                         PRUint32           aFlags)
00271 {
00272     if (!xpcomFunctions.stringContainerInit2)
00273         return NS_ERROR_NOT_INITIALIZED;
00274     return xpcomFunctions.stringContainerInit2(aStr, aData, aDataLength, aFlags);
00275 }
00276 
00277 extern "C" NS_COM void
00278 NS_StringContainerFinish(nsStringContainer &aStr)
00279 {
00280     if (xpcomFunctions.stringContainerFinish)
00281         xpcomFunctions.stringContainerFinish(aStr);
00282 }
00283 
00284 extern "C" NS_COM PRUint32
00285 NS_StringGetData(const nsAString &aStr, const PRUnichar **aBuf, PRBool *aTerm)
00286 {
00287     if (!xpcomFunctions.stringGetData) {
00288         *aBuf = nsnull;
00289         return 0;
00290     }
00291     return xpcomFunctions.stringGetData(aStr, aBuf, aTerm);
00292 }
00293 
00294 extern "C" NS_COM PRUint32
00295 NS_StringGetMutableData(nsAString &aStr, PRUint32 aLen, PRUnichar **aBuf)
00296 {
00297     if (!xpcomFunctions.stringGetMutableData) {
00298         *aBuf = nsnull;
00299         return 0;
00300     }
00301     return xpcomFunctions.stringGetMutableData(aStr, aLen, aBuf);
00302 }
00303 
00304 extern "C" NS_COM PRUnichar *
00305 NS_StringCloneData(const nsAString &aStr)
00306 {
00307     if (!xpcomFunctions.stringCloneData)
00308         return nsnull;
00309     return xpcomFunctions.stringCloneData(aStr);
00310 }
00311 
00312 extern "C" NS_COM nsresult
00313 NS_StringSetData(nsAString &aStr, const PRUnichar *aBuf, PRUint32 aCount)
00314 {
00315     if (!xpcomFunctions.stringSetData)
00316         return NS_ERROR_NOT_INITIALIZED;
00317 
00318     return xpcomFunctions.stringSetData(aStr, aBuf, aCount);
00319 }
00320 
00321 extern "C" NS_COM nsresult
00322 NS_StringSetDataRange(nsAString &aStr, PRUint32 aCutStart, PRUint32 aCutLength,
00323                       const PRUnichar *aBuf, PRUint32 aCount)
00324 {
00325     if (!xpcomFunctions.stringSetDataRange)
00326         return NS_ERROR_NOT_INITIALIZED;
00327     return xpcomFunctions.stringSetDataRange(aStr, aCutStart, aCutLength, aBuf, aCount);
00328 }
00329 
00330 extern "C" NS_COM nsresult
00331 NS_StringCopy(nsAString &aDest, const nsAString &aSrc)
00332 {
00333     if (!xpcomFunctions.stringCopy)
00334         return NS_ERROR_NOT_INITIALIZED;
00335     return xpcomFunctions.stringCopy(aDest, aSrc);
00336 }
00337 
00338 
00339 extern "C" NS_COM nsresult
00340 NS_CStringContainerInit(nsCStringContainer &aStr)
00341 {
00342     if (!xpcomFunctions.cstringContainerInit)
00343         return NS_ERROR_NOT_INITIALIZED;
00344     return xpcomFunctions.cstringContainerInit(aStr);
00345 }
00346 
00347 extern "C" NS_COM nsresult
00348 NS_CStringContainerInit2(nsCStringContainer &aStr,
00349                          const char         *aData,
00350                          PRUint32           aDataLength,
00351                          PRUint32           aFlags)
00352 {
00353     if (!xpcomFunctions.cstringContainerInit2)
00354         return NS_ERROR_NOT_INITIALIZED;
00355     return xpcomFunctions.cstringContainerInit2(aStr, aData, aDataLength, aFlags);
00356 }
00357 
00358 extern "C" NS_COM void
00359 NS_CStringContainerFinish(nsCStringContainer &aStr)
00360 {
00361     if (xpcomFunctions.cstringContainerFinish)
00362         xpcomFunctions.cstringContainerFinish(aStr);
00363 }
00364 
00365 extern "C" NS_COM PRUint32
00366 NS_CStringGetData(const nsACString &aStr, const char **aBuf, PRBool *aTerm)
00367 {
00368     if (!xpcomFunctions.cstringGetData) {
00369         *aBuf = nsnull;
00370         return 0;
00371     }
00372     return xpcomFunctions.cstringGetData(aStr, aBuf, aTerm);
00373 }
00374 
00375 extern "C" NS_COM PRUint32
00376 NS_CStringGetMutableData(nsACString &aStr, PRUint32 aLen, char **aBuf)
00377 {
00378     if (!xpcomFunctions.cstringGetMutableData) {
00379         *aBuf = nsnull;
00380         return 0;
00381     }
00382     return xpcomFunctions.cstringGetMutableData(aStr, aLen, aBuf);
00383 }
00384 
00385 extern "C" NS_COM char *
00386 NS_CStringCloneData(const nsACString &aStr)
00387 {
00388     if (!xpcomFunctions.cstringCloneData)
00389         return nsnull;
00390     return xpcomFunctions.cstringCloneData(aStr);
00391 }
00392 
00393 extern "C" NS_COM nsresult
00394 NS_CStringSetData(nsACString &aStr, const char *aBuf, PRUint32 aCount)
00395 {
00396     if (!xpcomFunctions.cstringSetData)
00397         return NS_ERROR_NOT_INITIALIZED;
00398     return xpcomFunctions.cstringSetData(aStr, aBuf, aCount);
00399 }
00400 
00401 extern "C" NS_COM nsresult
00402 NS_CStringSetDataRange(nsACString &aStr, PRUint32 aCutStart, PRUint32 aCutLength,
00403                        const char *aBuf, PRUint32 aCount)
00404 {
00405     if (!xpcomFunctions.cstringSetDataRange)
00406         return NS_ERROR_NOT_INITIALIZED;
00407     return xpcomFunctions.cstringSetDataRange(aStr, aCutStart, aCutLength, aBuf, aCount);
00408 }
00409 
00410 extern "C" NS_COM nsresult
00411 NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
00412 {
00413     if (!xpcomFunctions.cstringCopy)
00414         return NS_ERROR_NOT_INITIALIZED;
00415     return xpcomFunctions.cstringCopy(aDest, aSrc);
00416 }
00417 
00418 extern "C" NS_COM nsresult
00419 NS_CStringToUTF16(const nsACString &aSrc, nsCStringEncoding aSrcEncoding, nsAString &aDest)
00420 {
00421     if (!xpcomFunctions.cstringToUTF16)
00422         return NS_ERROR_NOT_INITIALIZED;
00423     return xpcomFunctions.cstringToUTF16(aSrc, aSrcEncoding, aDest);
00424 }
00425 
00426 extern "C" NS_COM nsresult
00427 NS_UTF16ToCString(const nsAString &aSrc, nsCStringEncoding aDestEncoding, nsACString &aDest)
00428 {
00429     if (!xpcomFunctions.utf16ToCString)
00430         return NS_ERROR_NOT_INITIALIZED;
00431     return xpcomFunctions.utf16ToCString(aSrc, aDestEncoding, aDest);
00432 }
00433 
00434 extern "C" NS_COM void*
00435 NS_Alloc(PRSize size)
00436 {
00437     if (!xpcomFunctions.allocFunc)
00438         return nsnull;
00439     return xpcomFunctions.allocFunc(size);
00440 }
00441 
00442 extern "C" NS_COM void*
00443 NS_Realloc(void* ptr, PRSize size)
00444 {
00445     if (!xpcomFunctions.reallocFunc)
00446         return nsnull;
00447     return xpcomFunctions.reallocFunc(ptr, size);
00448 }
00449 
00450 extern "C" NS_COM void
00451 NS_Free(void* ptr)
00452 {
00453     if (xpcomFunctions.freeFunc)
00454         xpcomFunctions.freeFunc(ptr);
00455 }
00456 
00457 // Default GRE startup/shutdown code
00458 
00459 extern "C"
00460 nsresult GRE_Startup()
00461 {
00462     const char* xpcomLocation = GRE_GetXPCOMPath();
00463 
00464     // Startup the XPCOM Glue that links us up with XPCOM.
00465     nsresult rv = XPCOMGlueStartup(xpcomLocation);
00466     
00467     if (NS_FAILED(rv)) {
00468         NS_WARNING("gre: XPCOMGlueStartup failed");
00469         return rv;
00470     }
00471 
00472 #ifdef XP_WIN
00473     // On windows we have legacy GRE code that does not load the GRE dependent
00474     // libs (seamonkey GRE, not libxul)... add the GRE to the PATH.
00475     // See bug 301043.
00476 
00477     const char *lastSlash = strrchr(xpcomLocation, '\\');
00478     if (lastSlash) {
00479         int xpcomPathLen = lastSlash - xpcomLocation;
00480         DWORD pathLen = GetEnvironmentVariable("PATH", nsnull, 0);
00481 
00482         char *newPath = (char*) _alloca(xpcomPathLen + pathLen + 1);
00483         strncpy(newPath, xpcomLocation, xpcomPathLen);
00484         // in case GetEnvironmentVariable fails
00485         newPath[xpcomPathLen] = ';';
00486         newPath[xpcomPathLen + 1] = '\0';
00487 
00488         GetEnvironmentVariable("PATH", newPath + xpcomPathLen + 1, pathLen);
00489         SetEnvironmentVariable("PATH", newPath);
00490     }
00491 #endif
00492 
00493     nsGREDirServiceProvider *provider = new nsGREDirServiceProvider();
00494     if ( !provider ) {
00495         NS_WARNING("GRE_Startup failed");
00496         XPCOMGlueShutdown();
00497         return NS_ERROR_OUT_OF_MEMORY;
00498     }
00499 
00500     nsCOMPtr<nsIServiceManager> servMan;
00501     NS_ADDREF( provider );
00502     rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, provider);
00503     NS_RELEASE(provider);
00504 
00505     if ( NS_FAILED(rv) || !servMan) {
00506         NS_WARNING("gre: NS_InitXPCOM failed");
00507         XPCOMGlueShutdown();
00508         return rv;
00509     }
00510 
00511     return NS_OK;
00512 }
00513 
00514 extern "C"
00515 nsresult GRE_Shutdown()
00516 {
00517     NS_ShutdownXPCOM(nsnull);
00518     XPCOMGlueShutdown();
00519     return NS_OK;
00520 }