Back to index

lightning-sunbird  0.9+nobinonly
xpcom.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Python XPCOM language bindings.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * ActiveState Tool Corp.
00018  * Portions created by the Initial Developer are Copyright (C) 2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Mark Hammond <mhammond@skippinet.com.au> (original author)
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 //
00039 // This code is part of the XPCOM extensions for Python.
00040 //
00041 // Written May 2000 by Mark Hammond.
00042 //
00043 // Based heavily on the Python COM support, which is
00044 // (c) Mark Hammond and Greg Stein.
00045 //
00046 // (c) 2000, ActiveState corp.
00047 
00048 #include "PyXPCOM_std.h"
00049 #include "nsIThread.h"
00050 #include "nsXPCOM.h"
00051 #include "nsISupportsPrimitives.h"
00052 #include "nsIModule.h"
00053 #include "nsIFile.h"
00054 #include "nsILocalFile.h"
00055 #include "nsIComponentRegistrar.h"
00056 #include "nsIComponentManagerObsolete.h"
00057 
00058 #ifdef XP_WIN
00059 #ifndef WIN32_LEAN_AND_MEAN
00060 #define WIN32_LEAN_AND_MEAN
00061 #endif
00062 #include "windows.h"
00063 #endif
00064 
00065 #include "nsIEventQueue.h"
00066 #include "nsIProxyObjectManager.h"
00067 
00068 PYXPCOM_EXPORT PyObject *PyXPCOM_Error = NULL;
00069 extern PRInt32 _PyXPCOM_GetGatewayCount(void);
00070 extern PRInt32 _PyXPCOM_GetInterfaceCount(void);
00071 
00072 extern void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
00073 
00074 #define LOADER_LINKS_WITH_PYTHON
00075 
00076 #ifndef PYXPCOM_USE_PYGILSTATE
00077 extern void PyXPCOM_InterpreterState_Ensure();
00078 #endif
00079 
00080 PyXPCOM_INTERFACE_DEFINE(Py_nsIComponentManager, nsIComponentManager, PyMethods_IComponentManager)
00081 PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfoManager, nsIInterfaceInfoManager, PyMethods_IInterfaceInfoManager)
00082 PyXPCOM_INTERFACE_DEFINE(Py_nsIEnumerator, nsIEnumerator, PyMethods_IEnumerator)
00083 PyXPCOM_INTERFACE_DEFINE(Py_nsISimpleEnumerator, nsISimpleEnumerator, PyMethods_ISimpleEnumerator)
00084 PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfo, nsIInterfaceInfo, PyMethods_IInterfaceInfo)
00085 PyXPCOM_INTERFACE_DEFINE(Py_nsIInputStream, nsIInputStream, PyMethods_IInputStream)
00086 PyXPCOM_INTERFACE_DEFINE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassInfo)
00087 PyXPCOM_INTERFACE_DEFINE(Py_nsIVariant, nsIVariant, PyMethods_IVariant)
00088 // deprecated, but retained for backward compatibility:
00089 PyXPCOM_INTERFACE_DEFINE(Py_nsIComponentManagerObsolete, nsIComponentManagerObsolete, PyMethods_IComponentManagerObsolete)
00090 
00092 // This is the main entry point called by the Python component
00093 // loader.
00094 extern "C" NS_EXPORT nsresult PyXPCOM_NSGetModule(nsIComponentManager *servMgr,
00095                                           nsIFile* location,
00096                                           nsIModule** result)
00097 {
00098        NS_PRECONDITION(result!=NULL, "null result pointer in PyXPCOM_NSGetModule!");
00099        NS_PRECONDITION(location!=NULL, "null nsIFile pointer in PyXPCOM_NSGetModule!");
00100        NS_PRECONDITION(servMgr!=NULL, "null servMgr pointer in PyXPCOM_NSGetModule!");
00101 #ifndef LOADER_LINKS_WITH_PYTHON
00102        if (!Py_IsInitialized()) {
00103               Py_Initialize();
00104               if (!Py_IsInitialized()) {
00105                      PyXPCOM_LogError("Python initialization failed!\n");
00106                      return NS_ERROR_FAILURE;
00107               }
00108               PyEval_InitThreads();
00109 #ifndef PYXPCOM_USE_PYGILSTATE
00110               PyXPCOM_InterpreterState_Ensure();
00111 #endif
00112               PyEval_SaveThread();
00113        }
00114 #endif // LOADER_LINKS_WITH_PYTHON 
00115        CEnterLeavePython _celp;
00116        PyObject *func = NULL;
00117        PyObject *obServMgr = NULL;
00118        PyObject *obLocation = NULL;
00119        PyObject *wrap_ret = NULL;
00120        PyObject *args = NULL;
00121        PyObject *mod = PyImport_ImportModule("xpcom.server");
00122        if (!mod) goto done;
00123        func = PyObject_GetAttrString(mod, "NS_GetModule");
00124        if (func==NULL) goto done;
00125        obServMgr = Py_nsISupports::PyObjectFromInterface(servMgr, NS_GET_IID(nsIComponentManager), PR_TRUE);
00126        if (obServMgr==NULL) goto done;
00127        obLocation = Py_nsISupports::PyObjectFromInterface(location, NS_GET_IID(nsIFile), PR_TRUE);
00128        if (obLocation==NULL) goto done;
00129        args = Py_BuildValue("OO", obServMgr, obLocation);
00130        if (args==NULL) goto done;
00131        wrap_ret = PyEval_CallObject(func, args);
00132        if (wrap_ret==NULL) goto done;
00133        Py_nsISupports::InterfaceFromPyObject(wrap_ret, NS_GET_IID(nsIModule), (nsISupports **)result, PR_FALSE, PR_FALSE);
00134 done:
00135        nsresult nr = NS_OK;
00136        if (PyErr_Occurred()) {
00137               PyXPCOM_LogError("Obtaining the module object from Python failed.\n");
00138               nr = PyXPCOM_SetCOMErrorFromPyException();
00139        }
00140        Py_XDECREF(func);
00141        Py_XDECREF(obServMgr);
00142        Py_XDECREF(obLocation);
00143        Py_XDECREF(wrap_ret);
00144        Py_XDECREF(mod);
00145        Py_XDECREF(args);
00146        return nr;
00147 }
00148 
00149 // "boot-strap" methods - interfaces we need to get the base
00150 // interface support!
00151 
00152 /* deprecated, included for backward compatibility */
00153 static PyObject *
00154 PyXPCOMMethod_NS_GetGlobalComponentManager(PyObject *self, PyObject *args)
00155 {
00156        if (PyErr_Warn(PyExc_DeprecationWarning, "Use GetComponentManager instead") < 0)
00157               return NULL;
00158        if (!PyArg_ParseTuple(args, ""))
00159               return NULL;
00160        nsIComponentManager* cm;
00161        nsresult rv;
00162        Py_BEGIN_ALLOW_THREADS;
00163        rv = NS_GetComponentManager(&cm);
00164        Py_END_ALLOW_THREADS;
00165        if ( NS_FAILED(rv) )
00166               return PyXPCOM_BuildPyException(rv);
00167 
00168        nsCOMPtr<nsIComponentManagerObsolete> ocm(do_QueryInterface(cm, &rv));
00169        if ( NS_FAILED(rv) )
00170               return PyXPCOM_BuildPyException(rv);
00171 
00172        return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsIComponentManagerObsolete), PR_FALSE, PR_FALSE);
00173 }
00174 
00175 static PyObject *
00176 PyXPCOMMethod_GetComponentManager(PyObject *self, PyObject *args)
00177 {
00178        if (!PyArg_ParseTuple(args, ""))
00179               return NULL;
00180        nsIComponentManager* cm;
00181        nsresult rv;
00182        Py_BEGIN_ALLOW_THREADS;
00183        rv = NS_GetComponentManager(&cm);
00184        Py_END_ALLOW_THREADS;
00185        if ( NS_FAILED(rv) )
00186               return PyXPCOM_BuildPyException(rv);
00187 
00188        return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsIComponentManager), PR_FALSE, PR_FALSE);
00189 }
00190 
00191 static PyObject *
00192 PyXPCOMMethod_GetServiceManager(PyObject *self, PyObject *args)
00193 {
00194        if (!PyArg_ParseTuple(args, ""))
00195               return NULL;
00196        nsIServiceManager* sm;
00197        nsresult rv;
00198        Py_BEGIN_ALLOW_THREADS;
00199        rv = NS_GetServiceManager(&sm);
00200        Py_END_ALLOW_THREADS;
00201        if ( NS_FAILED(rv) )
00202               return PyXPCOM_BuildPyException(rv);
00203 
00204        // Return a type based on the IID.
00205        return Py_nsISupports::PyObjectFromInterface(sm, NS_GET_IID(nsIServiceManager), PR_FALSE);
00206 }
00207 
00208 /* deprecated, included for backward compatibility */
00209 static PyObject *
00210 PyXPCOMMethod_GetGlobalServiceManager(PyObject *self, PyObject *args)
00211 {
00212        if (PyErr_Warn(PyExc_DeprecationWarning, "Use GetServiceManager instead") < 0)
00213               return NULL;
00214 
00215        return PyXPCOMMethod_GetComponentManager(self, args);
00216 }
00217               
00218 static PyObject *
00219 PyXPCOMMethod_XPTI_GetInterfaceInfoManager(PyObject *self, PyObject *args)
00220 {
00221        if (!PyArg_ParseTuple(args, ""))
00222               return NULL;
00223        nsIInterfaceInfoManager* im;
00224        Py_BEGIN_ALLOW_THREADS;
00225        im = XPTI_GetInterfaceInfoManager();
00226        Py_END_ALLOW_THREADS;
00227        if ( im == nsnull )
00228               return PyXPCOM_BuildPyException(NS_ERROR_FAILURE);
00229 
00230        /* Return a type based on the IID (with no extra ref) */
00231        // Can not auto-wrap the interface info manager as it is critical to
00232        // building the support we need for autowrap.
00233        return Py_nsISupports::PyObjectFromInterface(im, NS_GET_IID(nsIInterfaceInfoManager), PR_FALSE, PR_FALSE);
00234 }
00235 
00236 static PyObject *
00237 PyXPCOMMethod_XPTC_InvokeByIndex(PyObject *self, PyObject *args)
00238 {
00239        PyObject *obIS, *obParams;
00240        nsCOMPtr<nsISupports> pis;
00241        int index;
00242 
00243        // We no longer rely on PyErr_Occurred() for our error state,
00244        // but keeping this assertion can't hurt - it should still always be true!
00245        NS_WARN_IF_FALSE(!PyErr_Occurred(), "Should be no pending Python error!");
00246 
00247        if (!PyArg_ParseTuple(args, "OiO", &obIS, &index, &obParams))
00248               return NULL;
00249 
00250        // Ack!  We must ask for the "native" interface supported by
00251        // the object, not specifically nsISupports, else we may not
00252        // back the same pointer (eg, Python, following identity rules,
00253        // will return the "original" gateway when QI'd for nsISupports)
00254        if (!Py_nsISupports::InterfaceFromPyObject(
00255                      obIS, 
00256                      Py_nsIID_NULL, 
00257                      getter_AddRefs(pis), 
00258                      PR_FALSE))
00259               return NULL;
00260 
00261        PyXPCOM_InterfaceVariantHelper arg_helper;
00262        if (!arg_helper.Init(obParams))
00263               return NULL;
00264 
00265        if (!arg_helper.FillArray())
00266               return NULL;
00267 
00268        nsresult r;
00269        Py_BEGIN_ALLOW_THREADS;
00270        r = XPTC_InvokeByIndex(pis, index, arg_helper.m_num_array, arg_helper.m_var_array);
00271        Py_END_ALLOW_THREADS;
00272        if ( NS_FAILED(r) )
00273               return PyXPCOM_BuildPyException(r);
00274 
00275        return arg_helper.MakePythonResult();
00276 }
00277 
00278 static PyObject *
00279 PyXPCOMMethod_WrapObject(PyObject *self, PyObject *args)
00280 {
00281        PyObject *ob, *obIID;
00282        int bWrapClient = 1;
00283        if (!PyArg_ParseTuple(args, "OO|i", &ob, &obIID, &bWrapClient))
00284               return NULL;
00285 
00286        nsIID  iid;
00287        if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
00288               return NULL;
00289 
00290        nsISupports *ret = NULL;
00291        nsresult r = PyXPCOM_XPTStub::CreateNew(ob, iid, (void **)&ret);
00292        if ( NS_FAILED(r) )
00293               return PyXPCOM_BuildPyException(r);
00294 
00295        // _ALL_ wrapped objects are associated with a weak-ref
00296        // to their "main" instance.
00297        AddDefaultGateway(ob, ret); // inject a weak reference to myself into the instance.
00298 
00299        // Now wrap it in an interface.
00300        return Py_nsISupports::PyObjectFromInterface(ret, iid, PR_FALSE, bWrapClient);
00301 }
00302 
00303 static PyObject *
00304 PyXPCOMMethod_UnwrapObject(PyObject *self, PyObject *args)
00305 {
00306        PyObject *ob;
00307        if (!PyArg_ParseTuple(args, "O", &ob))
00308               return NULL;
00309 
00310        nsISupports *uob = NULL;
00311        nsIInternalPython *iob = NULL;
00312        PyObject *ret = NULL;
00313        if (!Py_nsISupports::InterfaceFromPyObject(ob, 
00314                             NS_GET_IID(nsISupports), 
00315                             &uob, 
00316                             PR_FALSE))
00317               goto done;
00318        if (NS_FAILED(uob->QueryInterface(NS_GET_IID(nsIInternalPython), reinterpret_cast<void **>(&iob)))) {
00319               PyErr_SetString(PyExc_ValueError, "This XPCOM object is not implemented by Python");
00320               goto done;
00321        }
00322        ret = iob->UnwrapPythonObject();
00323 done:
00324        Py_BEGIN_ALLOW_THREADS;
00325        NS_IF_RELEASE(uob);
00326        NS_IF_RELEASE(iob);
00327        Py_END_ALLOW_THREADS;
00328        return ret;
00329 }
00330 
00331 // @pymethod int|pythoncom|_GetInterfaceCount|Retrieves the number of interface objects currently in existance
00332 static PyObject *
00333 PyXPCOMMethod_GetInterfaceCount(PyObject *self, PyObject *args)
00334 {
00335        if (!PyArg_ParseTuple(args, ":_GetInterfaceCount"))
00336               return NULL;
00337        return PyInt_FromLong(_PyXPCOM_GetInterfaceCount());
00338        // @comm If is occasionally a good idea to call this function before your Python program
00339        // terminates.  If this function returns non-zero, then you still have PythonCOM objects
00340        // alive in your program (possibly in global variables).
00341 }
00342 
00343 // @pymethod int|pythoncom|_GetGatewayCount|Retrieves the number of gateway objects currently in existance
00344 static PyObject *
00345 PyXPCOMMethod_GetGatewayCount(PyObject *self, PyObject *args)
00346 {
00347        // @comm This is the number of Python object that implement COM servers which
00348        // are still alive (ie, serving a client).  The only way to reduce this count
00349        // is to have the process which uses these PythonCOM servers release its references.
00350        if (!PyArg_ParseTuple(args, ":_GetGatewayCount"))
00351               return NULL;
00352        return PyInt_FromLong(_PyXPCOM_GetGatewayCount());
00353 }
00354 
00355 static PyObject *
00356 PyXPCOMMethod_NS_ShutdownXPCOM(PyObject *self, PyObject *args)
00357 {
00358        // @comm This is the number of Python object that implement COM servers which
00359        // are still alive (ie, serving a client).  The only way to reduce this count
00360        // is to have the process which uses these PythonCOM servers release its references.
00361        if (!PyArg_ParseTuple(args, ":NS_ShutdownXPCOM"))
00362               return NULL;
00363        nsresult nr;
00364        Py_BEGIN_ALLOW_THREADS;
00365        nr = NS_ShutdownXPCOM(nsnull);
00366        Py_END_ALLOW_THREADS;
00367 
00368        // Dont raise an exception - as we are probably shutting down
00369        // and dont really case - just return the status
00370        return PyInt_FromLong(nr);
00371 }
00372 
00373 static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
00374 
00375 // A hack to work around their magic constants!
00376 static PyObject *
00377 PyXPCOMMethod_GetProxyForObject(PyObject *self, PyObject *args)
00378 {
00379        PyObject *obQueue, *obIID, *obOb;
00380        int flags;
00381        if (!PyArg_ParseTuple(args, "OOOi", &obQueue, &obIID, &obOb, &flags))
00382               return NULL;
00383        nsIID iid;
00384        if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
00385               return NULL;
00386        nsCOMPtr<nsISupports> pob;
00387        if (!Py_nsISupports::InterfaceFromPyObject(obOb, iid, getter_AddRefs(pob), PR_FALSE))
00388               return NULL;
00389        nsIEventQueue *pQueue = NULL;
00390        nsIEventQueue *pQueueRelease = NULL;
00391 
00392        if (PyInt_Check(obQueue)) {
00393               pQueue = (nsIEventQueue *)PyInt_AsLong(obQueue);
00394        } else {
00395               if (!Py_nsISupports::InterfaceFromPyObject(obQueue, NS_GET_IID(nsIEventQueue), (nsISupports **)&pQueue, PR_TRUE))
00396                      return NULL;
00397               pQueueRelease = pQueue;
00398        }
00399 
00400        nsresult rv_proxy;
00401        nsISupports *presult = nsnull;
00402        Py_BEGIN_ALLOW_THREADS;
00403        nsCOMPtr<nsIProxyObjectManager> proxyMgr = 
00404                 do_GetService(kProxyObjectManagerCID, &rv_proxy);
00405 
00406        if ( NS_SUCCEEDED(rv_proxy) ) {
00407               rv_proxy = proxyMgr->GetProxyForObject(pQueue,
00408                             iid,
00409                             pob,
00410                             flags,
00411                             (void **)&presult);
00412        }
00413        if (pQueueRelease)
00414               pQueueRelease->Release();
00415        Py_END_ALLOW_THREADS;
00416 
00417        PyObject *result;
00418        if (NS_SUCCEEDED(rv_proxy) ) {
00419               result = Py_nsISupports::PyObjectFromInterface(presult, iid, PR_FALSE);
00420        } else {
00421               result = PyXPCOM_BuildPyException(rv_proxy);
00422        }
00423        return result;
00424 }
00425 
00426 PyObject *PyGetSpecialDirectory(PyObject *self, PyObject *args)
00427 {
00428        char *dirname;
00429        if (!PyArg_ParseTuple(args, "s:GetSpecialDirectory", &dirname))
00430               return NULL;
00431        nsIFile *file = NULL;
00432        nsresult r = NS_GetSpecialDirectory(dirname, &file);
00433        if ( NS_FAILED(r) )
00434               return PyXPCOM_BuildPyException(r);
00435        // returned object swallows our reference.
00436        return Py_nsISupports::PyObjectFromInterface(file, NS_GET_IID(nsIFile), PR_FALSE);
00437 }
00438 
00439 PyObject *AllocateBuffer(PyObject *self, PyObject *args)
00440 {
00441        int bufSize;
00442        if (!PyArg_ParseTuple(args, "i", &bufSize))
00443               return NULL;
00444        return PyBuffer_New(bufSize);
00445 }
00446 
00447 PyObject *LogWarning(PyObject *self, PyObject *args)
00448 {
00449        char *msg;
00450        if (!PyArg_ParseTuple(args, "s", &msg))
00451               return NULL;
00452        PyXPCOM_LogWarning("%s", msg);
00453        Py_INCREF(Py_None);
00454        return Py_None;
00455 }
00456 
00457 PyObject *LogError(PyObject *self, PyObject *args)
00458 {
00459        char *msg;
00460        if (!PyArg_ParseTuple(args, "s", &msg))
00461               return NULL;
00462        PyXPCOM_LogError("%s", msg);
00463        Py_INCREF(Py_None);
00464        return Py_None;
00465 }
00466 
00467 extern PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args);
00468 
00469 static struct PyMethodDef xpcom_methods[]=
00470 {
00471        {"GetComponentManager", PyXPCOMMethod_GetComponentManager, 1},
00472        {"NS_GetGlobalComponentManager", PyXPCOMMethod_NS_GetGlobalComponentManager, 1}, // deprecated
00473        {"XPTI_GetInterfaceInfoManager", PyXPCOMMethod_XPTI_GetInterfaceInfoManager, 1},
00474        {"XPTC_InvokeByIndex", PyXPCOMMethod_XPTC_InvokeByIndex, 1},
00475        {"GetServiceManager", PyXPCOMMethod_GetServiceManager, 1},
00476        {"GetGlobalServiceManager", PyXPCOMMethod_GetGlobalServiceManager, 1}, // deprecated
00477        {"IID", PyXPCOMMethod_IID, 1}, // IID is wrong - deprecated - not just IID, but CID, etc. 
00478        {"ID", PyXPCOMMethod_IID, 1}, // This is the official name.
00479        {"NS_ShutdownXPCOM", PyXPCOMMethod_NS_ShutdownXPCOM, 1},
00480        {"WrapObject", PyXPCOMMethod_WrapObject, 1},
00481        {"UnwrapObject", PyXPCOMMethod_UnwrapObject, 1},
00482        {"_GetInterfaceCount", PyXPCOMMethod_GetInterfaceCount, 1},
00483        {"_GetGatewayCount", PyXPCOMMethod_GetGatewayCount, 1},
00484        {"getProxyForObject", PyXPCOMMethod_GetProxyForObject, 1},
00485        {"GetProxyForObject", PyXPCOMMethod_GetProxyForObject, 1},
00486        {"GetSpecialDirectory", PyGetSpecialDirectory, 1},
00487        {"AllocateBuffer", AllocateBuffer, 1},
00488        {"LogWarning", LogWarning, 1},
00489        {"LogError", LogError, 1},
00490        { NULL }
00491 };
00492 
00494 // Other helpers/global functions.
00495 //
00496 PRBool PyXPCOM_Globals_Ensure()
00497 {
00498        PRBool rc = PR_TRUE;
00499 
00500 #ifndef PYXPCOM_USE_PYGILSTATE
00501        PyXPCOM_InterpreterState_Ensure();
00502 #endif
00503 
00504        // The exception object - we load it from .py code!
00505        if (PyXPCOM_Error == NULL) {
00506               rc = PR_FALSE;
00507               PyObject *mod = NULL;
00508 
00509               mod = PyImport_ImportModule("xpcom");
00510               if (mod!=NULL) {
00511                      PyXPCOM_Error = PyObject_GetAttrString(mod, "Exception");
00512                      Py_DECREF(mod);
00513               }
00514               rc = (PyXPCOM_Error != NULL);
00515        }
00516        if (!rc)
00517               return rc;
00518 
00519        static PRBool bHaveInitXPCOM = PR_FALSE;
00520        if (!bHaveInitXPCOM) {
00521               nsCOMPtr<nsIThread> thread_check;
00522               // xpcom appears to assert if already initialized
00523               // Is there an official way to determine this?
00524               if (NS_FAILED(nsIThread::GetMainThread(getter_AddRefs(thread_check)))) {
00525                      // not already initialized.
00526 #ifdef XP_WIN
00527                      // On Windows, we need to locate the Mozilla bin
00528                      // directory.  This by using locating a Moz DLL we depend
00529                      // on, and assume it lives in that bin dir.  Different
00530                      // moz build types (eg, xulrunner, suite) package
00531                      // XPCOM itself differently - but all appear to require
00532                      // nspr4.dll - so this is what we use.
00533                      char landmark[MAX_PATH+1];
00534                      HMODULE hmod = GetModuleHandle("nspr4.dll");
00535                      if (hmod==NULL) {
00536                             PyErr_SetString(PyExc_RuntimeError, "We dont appear to be linked against nspr4.dll.");
00537                             return PR_FALSE;
00538                      }
00539                      GetModuleFileName(hmod, landmark, sizeof(landmark)/sizeof(landmark[0]));
00540                      char *end = landmark + (strlen(landmark)-1);
00541                      while (end > landmark && *end != '\\')
00542                             end--;
00543                      if (end > landmark) *end = '\0';
00544 
00545                      nsCOMPtr<nsILocalFile> ns_bin_dir;
00546                      NS_ConvertASCIItoUCS2 strLandmark(landmark);
00547                      NS_NewLocalFile(strLandmark, PR_FALSE, getter_AddRefs(ns_bin_dir));
00548                      nsresult rv = NS_InitXPCOM2(nsnull, ns_bin_dir, nsnull);
00549 #else
00550                      // Elsewhere, Mozilla can find it itself (we hope!)
00551                      nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
00552 #endif // XP_WIN
00553                      if (NS_FAILED(rv)) {
00554                             PyErr_SetString(PyExc_RuntimeError, "The XPCOM subsystem could not be initialized");
00555                             return PR_FALSE;
00556                      }
00557               }
00558               // Even if xpcom was already init, we want to flag it as init!
00559               bHaveInitXPCOM = PR_TRUE;
00560        }
00561        return rc;
00562 }
00563 
00564 
00565 #define REGISTER_IID(t) { \
00566        PyObject *iid_ob = Py_nsIID::PyObjectFromIID(NS_GET_IID(t)); \
00567        PyDict_SetItemString(dict, "IID_"#t, iid_ob); \
00568        Py_DECREF(iid_ob); \
00569        }
00570 
00571 #define REGISTER_INT(val) { \
00572        PyObject *ob = PyInt_FromLong(val); \
00573        PyDict_SetItemString(dict, #val, ob); \
00574        Py_DECREF(ob); \
00575        }
00576 
00577 
00579 // The module init code.
00580 //
00581 extern "C" NS_EXPORT
00582 void 
00583 init_xpcom() {
00584        PyObject *oModule;
00585 
00586        // ensure the framework has valid state to work with.
00587        if (!PyXPCOM_Globals_Ensure())
00588               return;
00589 
00590        // Must force Python to start using thread locks
00591        PyEval_InitThreads();
00592 
00593        // Create the module and add the functions
00594        oModule = Py_InitModule("_xpcom", xpcom_methods);
00595 
00596        PyObject *dict = PyModule_GetDict(oModule);
00597        PyObject *pycom_Error = PyXPCOM_Error;
00598        if (pycom_Error == NULL || PyDict_SetItemString(dict, "error", pycom_Error) != 0)
00599        {
00600               PyErr_SetString(PyExc_MemoryError, "can't define error");
00601               return;
00602        }
00603        PyDict_SetItemString(dict, "IIDType", (PyObject *)&Py_nsIID::type);
00604 
00605        // register our entry point.
00606        PyObject *obFuncPtr = PyLong_FromVoidPtr((void *)&PyXPCOM_NSGetModule);
00607        if (obFuncPtr)
00608               PyDict_SetItemString(dict, 
00609                                            "_NSGetModule_FuncPtr", 
00610                                            obFuncPtr);
00611        Py_XDECREF(obFuncPtr);
00612 
00613        REGISTER_IID(nsISupports);
00614        REGISTER_IID(nsISupportsCString);
00615        REGISTER_IID(nsIModule);
00616        REGISTER_IID(nsIFactory);
00617        REGISTER_IID(nsIWeakReference);
00618        REGISTER_IID(nsISupportsWeakReference);
00619        REGISTER_IID(nsIClassInfo);
00620        REGISTER_IID(nsIServiceManager);
00621        REGISTER_IID(nsIComponentRegistrar);
00622        // Register our custom interfaces.
00623 
00624        Py_nsISupports::InitType();
00625        Py_nsIComponentManager::InitType(dict);
00626        Py_nsIInterfaceInfoManager::InitType(dict);
00627        Py_nsIEnumerator::InitType(dict);
00628        Py_nsISimpleEnumerator::InitType(dict);
00629        Py_nsIInterfaceInfo::InitType(dict);
00630        Py_nsIInputStream::InitType(dict);
00631        Py_nsIClassInfo::InitType(dict);
00632        Py_nsIVariant::InitType(dict);
00633        // for backward compatibility:
00634        Py_nsIComponentManagerObsolete::InitType(dict);
00635 
00636     // We have special support for proxies - may as well add their constants!
00637     REGISTER_INT(PROXY_SYNC);
00638     REGISTER_INT(PROXY_ASYNC);
00639     REGISTER_INT(PROXY_ALWAYS);
00640 }