summaryrefslogtreecommitdiffstats
path: root/src/libs/xpcom18a4/python/src
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/xpcom18a4/python/src')
-rw-r--r--src/libs/xpcom18a4/python/src/ErrorUtils.cpp483
-rw-r--r--src/libs/xpcom18a4/python/src/PyGBase.cpp852
-rw-r--r--src/libs/xpcom18a4/python/src/PyGInputStream.cpp173
-rw-r--r--src/libs/xpcom18a4/python/src/PyGModule.cpp297
-rw-r--r--src/libs/xpcom18a4/python/src/PyGStub.cpp180
-rw-r--r--src/libs/xpcom18a4/python/src/PyGWeakReference.cpp112
-rw-r--r--src/libs/xpcom18a4/python/src/PyIClassInfo.cpp181
-rw-r--r--src/libs/xpcom18a4/python/src/PyIComponentManager.cpp138
-rw-r--r--src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp203
-rw-r--r--src/libs/xpcom18a4/python/src/PyIEnumerator.cpp235
-rw-r--r--src/libs/xpcom18a4/python/src/PyIID.cpp410
-rw-r--r--src/libs/xpcom18a4/python/src/PyIInputStream.cpp190
-rw-r--r--src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp431
-rw-r--r--src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp206
-rw-r--r--src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp202
-rw-r--r--src/libs/xpcom18a4/python/src/PyISupports.cpp621
-rw-r--r--src/libs/xpcom18a4/python/src/PyIVariant.cpp231
-rw-r--r--src/libs/xpcom18a4/python/src/PyXPCOM.h1036
-rw-r--r--src/libs/xpcom18a4/python/src/PyXPCOM_std.h56
-rw-r--r--src/libs/xpcom18a4/python/src/Pyxpt_info.cpp197
-rw-r--r--src/libs/xpcom18a4/python/src/TypeObject.cpp457
-rw-r--r--src/libs/xpcom18a4/python/src/VariantUtils.cpp3112
-rw-r--r--src/libs/xpcom18a4/python/src/dllmain.cpp352
-rw-r--r--src/libs/xpcom18a4/python/src/loader/pyloader.cpp435
-rw-r--r--src/libs/xpcom18a4/python/src/module/_xpcom.cpp950
-rw-r--r--src/libs/xpcom18a4/python/src/readme.html99
26 files changed, 11839 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/python/src/ErrorUtils.cpp b/src/libs/xpcom18a4/python/src/ErrorUtils.cpp
new file mode 100644
index 00000000..9400799b
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/ErrorUtils.cpp
@@ -0,0 +1,483 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include "nsReadableUtils.h"
+#include <nsIConsoleService.h>
+#ifdef VBOX
+# include <nsIExceptionService.h>
+# include <iprt/err.h>
+# include <iprt/string.h>
+#endif
+#include "nspr.h" // PR_fprintf
+
+static char *PyTraceback_AsString(PyObject *exc_tb);
+
+// The internal helper that actually moves the
+// formatted string to the target!
+
+// Only used in really bad situations!
+static void _PanicErrorWrite(const char *msg)
+{
+ nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+ if (consoleService)
+ consoleService->LogStringMessage(NS_ConvertASCIItoUCS2(msg).get());
+ PR_fprintf(PR_STDERR,"%s\n", msg);
+}
+
+// Called when our "normal" error logger fails.
+static void HandleLogError(const char *pszMessageText)
+{
+ nsCAutoString streamout;
+
+ _PanicErrorWrite("Failed to log an error record");
+ if (PyXPCOM_FormatCurrentException(streamout))
+ _PanicErrorWrite(streamout.get());
+ _PanicErrorWrite("Original error follows:");
+ _PanicErrorWrite(pszMessageText);
+}
+
+static const char *LOGGER_WARNING = "warning";
+static const char *LOGGER_ERROR = "error";
+static const char *LOGGER_DEBUG = "debug";
+
+// Our "normal" error logger - calls back to the logging module.
+void DoLogMessage(const char *methodName, const char *pszMessageText)
+{
+ // We use the logging module now. Originally this code called
+ // the logging module directly by way of the C API's
+ // PyImport_ImportModule/PyObject_CallMethod etc. However, this
+ // causes problems when there is no Python caller on the stack -
+ // the logging module's findCaller method fails with a None frame.
+ // We now work around this by calling PyRun_SimpleString - this
+ // causes a new frame to be created for executing the compiled
+ // string, and the logging module no longer fails.
+ // XXX - this implementation is less than ideal - findCaller now
+ // returns ("<string>", 2). Ideally we would compile with a
+ // filename something similar to "<pydom error reporter>".
+
+ // But this also means we need a clear error state...
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
+// We will execute:
+// import logging
+// logging.getLogger('xpcom').{warning/error/etc}("%s", {msg_text})
+ nsCAutoString c("import logging\nlogging.getLogger('xpcom').");
+ c += methodName;
+ c += "('%s', ";
+ // Pull a trick to ensure a valid string - use Python repr!
+#if PY_MAJOR_VERSION <= 2
+ PyObject *obMessage = PyString_FromString(pszMessageText);
+#else
+ PyObject *obMessage = PyUnicode_FromString(pszMessageText);
+#endif
+ if (obMessage) {
+ PyObject *repr = PyObject_Repr(obMessage);
+ if (repr) {
+#if PY_MAJOR_VERSION <= 2
+ c += PyString_AsString(repr);
+#else
+ c += PyUnicode_AsUTF8(repr);
+#endif
+ Py_DECREF(repr);
+ }
+ Py_DECREF(obMessage);
+ }
+ c += ")\n";
+ if (PyRun_SimpleString(c.get()) != 0) {
+ HandleLogError(pszMessageText);
+ }
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+}
+
+void LogMessage(const char *methodName, const char *pszMessageText)
+{
+ // Be careful to save and restore the Python exception state
+ // before calling back to Python, or we lose the original error.
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
+ DoLogMessage(methodName, pszMessageText);
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+}
+
+
+void LogMessage(const char *methodName, nsACString &text)
+{
+ char *c = ToNewCString(text);
+ LogMessage(methodName, c);
+ nsCRT::free(c);
+}
+
+// A helper for the various logging routines.
+static void VLogF(const char *methodName, const char *fmt, va_list argptr)
+{
+ char buff[512];
+#ifdef VBOX /* Enable the use of VBox formatting types. */
+ RTStrPrintfV(buff, sizeof(buff), fmt, argptr);
+#else
+ // Use safer NS_ functions.
+ PR_vsnprintf(buff, sizeof(buff), fmt, argptr);
+#endif
+
+ LogMessage(methodName, buff);
+}
+
+PRBool PyXPCOM_FormatCurrentException(nsCString &streamout)
+{
+ PRBool ok = PR_FALSE;
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
+ PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
+ if (exc_typ) {
+ ok = PyXPCOM_FormatGivenException(streamout, exc_typ, exc_val,
+ exc_tb);
+ }
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+ return ok;
+}
+
+PRBool PyXPCOM_FormatGivenException(nsCString &streamout,
+ PyObject *exc_typ, PyObject *exc_val,
+ PyObject *exc_tb)
+{
+ if (!exc_typ)
+ return PR_FALSE;
+ streamout += "\n";
+
+ if (exc_tb) {
+ const char *szTraceback = PyTraceback_AsString(exc_tb);
+ if (szTraceback == NULL)
+ streamout += "Can't get the traceback info!";
+ else {
+ streamout += "Traceback (most recent call last):\n";
+ streamout += szTraceback;
+ PyMem_Free((void *)szTraceback);
+ }
+ }
+ PyObject *temp = PyObject_Str(exc_typ);
+ if (temp) {
+#if PY_MAJOR_VERSION <= 2
+ streamout += PyString_AsString(temp);
+#else
+ streamout += PyUnicode_AsUTF8(temp);
+#endif
+ Py_DECREF(temp);
+ } else
+ streamout += "Can't convert exception to a string!";
+ streamout += ": ";
+ if (exc_val != NULL) {
+ temp = PyObject_Str(exc_val);
+ if (temp) {
+#if PY_MAJOR_VERSION <= 2
+ streamout += PyString_AsString(temp);
+#else
+ streamout += PyUnicode_AsUTF8(temp);
+#endif
+ Py_DECREF(temp);
+ } else
+ streamout += "Can't convert exception value to a string!";
+ }
+ return PR_TRUE;
+}
+
+void PyXPCOM_LogError(const char *fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+ // NOTE: It is tricky to use logger.exception here - the exception
+ // state when called back from the C code is clear. Only Python 2.4
+ // and later allows an explicit exc_info tuple().
+
+ // Don't use VLogF here, instead arrange for exception info and
+ // traceback to be in the same buffer.
+ char buff[512];
+ PR_vsnprintf(buff, sizeof(buff), fmt, marker);
+ // If we have a Python exception, also log that:
+ nsCAutoString streamout(buff);
+ if (PyXPCOM_FormatCurrentException(streamout)) {
+ LogMessage(LOGGER_ERROR, streamout);
+ }
+ va_end(marker);
+}
+
+void PyXPCOM_LogWarning(const char *fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+ VLogF(LOGGER_WARNING, fmt, marker);
+ va_end(marker);
+}
+
+void PyXPCOM_Log(const char *level, const nsCString &msg)
+{
+ DoLogMessage(level, msg.get());
+}
+
+#ifdef DEBUG
+void PyXPCOM_LogDebug(const char *fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+ VLogF(LOGGER_DEBUG, fmt, marker);
+ va_end(marker);
+}
+#endif
+
+#ifdef VBOX
+PyObject *PyXPCOM_BuildErrorMessage(nsresult r)
+{
+ char msg[512];
+ bool gotMsg = false;
+
+ if (!gotMsg)
+ {
+ nsresult rc;
+ nsCOMPtr <nsIExceptionService> es;
+ es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
+ if (NS_SUCCEEDED (rc))
+ {
+ nsCOMPtr <nsIExceptionManager> em;
+ rc = es->GetCurrentExceptionManager (getter_AddRefs (em));
+ if (NS_SUCCEEDED (rc))
+ {
+ nsCOMPtr <nsIException> ex;
+ rc = em->GetExceptionFromProvider(r, NULL, getter_AddRefs (ex));
+ if (NS_SUCCEEDED (rc) && ex)
+ {
+ nsXPIDLCString emsg;
+ ex->GetMessage(getter_Copies(emsg));
+ PR_snprintf(msg, sizeof(msg), "%s",
+ emsg.get());
+ gotMsg = true;
+ }
+ }
+ }
+ }
+
+ if (!gotMsg)
+ {
+ const RTCOMERRMSG* pMsg = RTErrCOMGet(r);
+ if (strncmp(pMsg->pszMsgFull, "Unknown", 7) != 0)
+ {
+ PR_snprintf(msg, sizeof(msg), "%s (%s)",
+ pMsg->pszMsgFull, pMsg->pszDefine);
+ gotMsg = true;
+ }
+ }
+
+ if (!gotMsg)
+ {
+ PR_snprintf(msg, sizeof(msg), "Error 0x%x in module 0x%x",
+ NS_ERROR_GET_CODE(r), NS_ERROR_GET_MODULE(r));
+ }
+ PyObject *evalue = Py_BuildValue("is", r, msg);
+ return evalue;
+}
+#endif
+
+PyObject *PyXPCOM_BuildPyException(nsresult r)
+{
+#ifndef VBOX
+ // Need the message etc.
+ PyObject *evalue = Py_BuildValue("i", r);
+#else
+ PyObject *evalue = PyXPCOM_BuildErrorMessage(r);
+#endif
+ PyErr_SetObject(PyXPCOM_Error, evalue);
+ Py_XDECREF(evalue);
+ return NULL;
+}
+
+nsresult PyXPCOM_SetCOMErrorFromPyException()
+{
+ if (!PyErr_Occurred())
+ // No error occurred
+ return NS_OK;
+ nsresult rv = NS_ERROR_FAILURE;
+ if (PyErr_ExceptionMatches(PyExc_MemoryError))
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ // todo:
+ // * Set an exception using the exception service.
+
+ // Once we have returned to the xpcom caller, we don't want to leave a
+ // Python exception pending - it may get noticed when the next call
+ // is made on the same thread.
+ PyErr_Clear();
+ return rv;
+}
+
+/* Obtains a string from a Python traceback.
+ This is the exact same string as "traceback.print_exc" would return.
+
+ Pass in a Python traceback object (probably obtained from PyErr_Fetch())
+ Result is a string which must be free'd using PyMem_Free()
+*/
+#define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;}
+
+char *PyTraceback_AsString(PyObject *exc_tb)
+{
+ const char *errMsg = NULL; /* holds a local error message */
+ char *result = NULL; /* a valid, allocated result. */
+ PyObject *modStringIO = NULL;
+ PyObject *modTB = NULL;
+ PyObject *obFuncStringIO = NULL;
+ PyObject *obStringIO = NULL;
+ PyObject *obFuncTB = NULL;
+ PyObject *argsTB = NULL;
+ PyObject *obResult = NULL;
+
+#if PY_MAJOR_VERSION <= 2
+ /* Import the modules we need - cStringIO and traceback */
+ modStringIO = PyImport_ImportModule("cStringIO");
+ if (modStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant import cStringIO\n");
+
+ modTB = PyImport_ImportModule("traceback");
+ if (modTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant import traceback\n");
+ /* Construct a cStringIO object */
+ obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
+ if (obFuncStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant find cStringIO.StringIO\n");
+ obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
+ if (obStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cStringIO.StringIO() failed\n");
+#else
+ /* Import the modules we need - io and traceback */
+ modStringIO = PyImport_ImportModule("io");
+ if (modStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant import io\n");
+
+ modTB = PyImport_ImportModule("traceback");
+ if (modTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant import traceback\n");
+ /* Construct a StringIO object */
+ obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
+ if (obFuncStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant find io.StringIO\n");
+ obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
+ if (obStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("io.StringIO() failed\n");
+#endif
+ /* Get the traceback.print_exception function, and call it. */
+ obFuncTB = PyObject_GetAttrString(modTB, "print_tb");
+ if (obFuncTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant find traceback.print_tb\n");
+
+ argsTB = Py_BuildValue("OOO",
+ exc_tb ? exc_tb : Py_None,
+ Py_None,
+ obStringIO);
+ if (argsTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant make print_tb arguments\n");
+
+ obResult = PyObject_CallObject(obFuncTB, argsTB);
+ if (obResult==NULL)
+ TRACEBACK_FETCH_ERROR("traceback.print_tb() failed\n");
+ /* Now call the getvalue() method in the StringIO instance */
+ Py_DECREF(obFuncStringIO);
+ obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
+ if (obFuncStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant find getvalue function\n");
+ Py_DECREF(obResult);
+ obResult = PyObject_CallObject(obFuncStringIO, NULL);
+ if (obResult==NULL)
+ TRACEBACK_FETCH_ERROR("getvalue() failed.\n");
+
+ /* And it should be a string all ready to go - duplicate it. */
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(obResult))
+#else
+ if (!PyUnicode_Check(obResult))
+#endif
+ TRACEBACK_FETCH_ERROR("getvalue() did not return a string\n");
+
+ { // a temp scope so I can use temp locals.
+#if PY_MAJOR_VERSION <= 2
+ char *tempResult = PyString_AsString(obResult);
+#else
+ /* PyUnicode_AsUTF8() is const char * as of Python 3.7, char * earlier. */
+ const char *tempResult = (const char *)PyUnicode_AsUTF8(obResult);
+#endif
+ result = (char *)PyMem_Malloc(strlen(tempResult)+1);
+ if (result==NULL)
+ TRACEBACK_FETCH_ERROR("memory error duplicating the traceback string\n");
+
+ strcpy(result, tempResult);
+ } // end of temp scope.
+done:
+ /* All finished - first see if we encountered an error */
+ if (result==NULL && errMsg != NULL) {
+ result = (char *)PyMem_Malloc(strlen(errMsg)+1);
+ if (result != NULL)
+ /* if it does, not much we can do! */
+ strcpy(result, errMsg);
+ }
+ Py_XDECREF(modStringIO);
+ Py_XDECREF(modTB);
+ Py_XDECREF(obFuncStringIO);
+ Py_XDECREF(obStringIO);
+ Py_XDECREF(obFuncTB);
+ Py_XDECREF(argsTB);
+ Py_XDECREF(obResult);
+ return result;
+}
+
+// See comments in PyXPCOM.h for why we need this!
+void PyXPCOM_MakePendingCalls()
+{
+ while (1) {
+ int rc = Py_MakePendingCalls();
+ if (rc == 0)
+ break;
+ // An exception - just report it as normal.
+ // Note that a traceback is very unlikely!
+ PyXPCOM_LogError("Unhandled exception detected before entering Python.\n");
+ PyErr_Clear();
+ // And loop around again until we are told everything is done!
+ }
+}
diff --git a/src/libs/xpcom18a4/python/src/PyGBase.cpp b/src/libs/xpcom18a4/python/src/PyGBase.cpp
new file mode 100644
index 00000000..e73b2a6d
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyGBase.cpp
@@ -0,0 +1,852 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// PyGBase.cpp - implementation of the PyG_Base class
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIModule.h>
+#include <nsIComponentLoader.h>
+#include <nsIInputStream.h>
+
+static PRInt32 cGateways = 0;
+PRInt32 _PyXPCOM_GetGatewayCount(void)
+{
+ return cGateways;
+}
+
+extern PyG_Base *MakePyG_nsIModule(PyObject *);
+extern PyG_Base *MakePyG_nsIComponentLoader(PyObject *instance);
+extern PyG_Base *MakePyG_nsIInputStream(PyObject *instance);
+
+static char *PyXPCOM_szDefaultGatewayAttributeName = (char*)"_com_instance_default_gateway_";
+PyG_Base *GetDefaultGateway(PyObject *instance);
+void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
+PRBool CheckDefaultGateway(PyObject *real_inst, REFNSIID iid, nsISupports **ret_gateway);
+
+/*static*/ nsresult
+PyG_Base::CreateNew(PyObject *pPyInstance, const nsIID &iid, void **ppResult)
+{
+ NS_PRECONDITION(ppResult && *ppResult==NULL, "NULL or uninitialized pointer");
+ if (ppResult==nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ PyG_Base *ret;
+ // Hack for few extra gateways we support.
+ if (iid.Equals(NS_GET_IID(nsIModule)))
+ ret = MakePyG_nsIModule(pPyInstance);
+ else if (iid.Equals(NS_GET_IID(nsIComponentLoader)))
+ ret = MakePyG_nsIComponentLoader(pPyInstance);
+ else if (iid.Equals(NS_GET_IID(nsIInputStream)))
+ ret = MakePyG_nsIInputStream(pPyInstance);
+ else
+ ret = new PyXPCOM_XPTStub(pPyInstance, iid);
+ if (ret==nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ ret->AddRef(); // The first reference for the caller.
+ *ppResult = ret->ThisAsIID(iid);
+ NS_ABORT_IF_FALSE(*ppResult != NULL, "ThisAsIID() gave NULL, but we know it supports it!");
+ return *ppResult ? NS_OK : NS_ERROR_FAILURE;
+}
+
+PyG_Base::PyG_Base(PyObject *instance, const nsIID &iid)
+{
+ // Note that "instance" is the _policy_ instance!!
+ PR_AtomicIncrement(&cGateways);
+ m_pBaseObject = GetDefaultGateway(instance);
+ // m_pWeakRef is an nsCOMPtr and needs no init.
+
+ NS_ABORT_IF_FALSE(!(iid.Equals(NS_GET_IID(nsISupportsWeakReference)) || iid.Equals(NS_GET_IID(nsIWeakReference))),"Should not be creating gateways with weak-ref interfaces");
+ m_iid = iid;
+ m_pPyObject = instance;
+ NS_PRECONDITION(instance, "NULL PyObject for PyXPCOM_XPTStub!");
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ // If XPCOM reference count logging is enabled, then allow us to give the Python class.
+ PyObject *realInstance = PyObject_GetAttrString(instance, "_obj_");
+ PyObject *r = PyObject_Repr(realInstance);
+ const char *szRepr;
+ if (r==NULL) {
+ PyXPCOM_LogError("Getting the __repr__ of the object failed");
+ PyErr_Clear();
+ szRepr = "(repr failed!)";
+ }
+ else
+#if PY_MAJOR_VERSION <= 2
+ szRepr = PyString_AsString(r);
+#else
+ szRepr = PyUnicode_AsUTF8(r);
+#endif
+ if (szRepr==NULL) szRepr = "";
+ int reprOffset = *szRepr=='<' ? 1 : 0;
+ static const char *reprPrefix = "component:";
+ if (strncmp(reprPrefix, szRepr+reprOffset, strlen(reprPrefix)) == 0)
+ reprOffset += strlen(reprPrefix);
+ strncpy(refcntLogRepr, szRepr + reprOffset, sizeof(refcntLogRepr)-1);
+ refcntLogRepr[sizeof(refcntLogRepr)-1] = '\0';
+ // See if we should get rid of the " at 0x12345" portion.
+ char *lastPos = strstr(refcntLogRepr, " at ");
+ if (lastPos) *lastPos = '\0';
+ Py_XDECREF(realInstance);
+ Py_XDECREF(r);
+#endif // NS_BUILD_REFCNT_LOGGING
+
+#ifdef DEBUG_LIFETIMES
+ {
+ char *iid_repr;
+ nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
+ if (iim!=nsnull)
+ iim->GetNameForIID(&iid, &iid_repr);
+ PyObject *real_instance = PyObject_GetAttrString(instance, "_obj_");
+ PyObject *real_repr = PyObject_Repr(real_instance);
+
+ PYXPCOM_LOG_DEBUG("PyG_Base created at %p\n instance_repr=%s\n IID=%s\n", this, PyString_AsString(real_repr), iid_repr);
+ nsMemory::Free(iid_repr);
+ Py_XDECREF(real_instance);
+ Py_XDECREF(real_repr);
+ }
+#endif // DEBUG_LIFETIMES
+ Py_XINCREF(instance); // instance should never be NULL - but whats an X between friends!
+
+ PyXPCOM_DLLAddRef();
+
+#ifdef DEBUG_FULL
+ LogF("PyGatewayBase: created %s", m_pPyObject ? PyXPCOM_ObTypeName(m_pPyObject) : "<NULL>");
+#endif
+}
+
+PyG_Base::~PyG_Base()
+{
+ PR_AtomicDecrement(&cGateways);
+#ifdef DEBUG_LIFETIMES
+ PYXPCOM_LOG_DEBUG("PyG_Base: deleted %p", this);
+#endif
+ if ( m_pPyObject ) {
+ CEnterLeavePython celp;
+ Py_DECREF(m_pPyObject);
+ }
+ if (m_pBaseObject)
+ m_pBaseObject->Release();
+ if (m_pWeakRef) {
+ // Need to ensure some other thread isnt doing a QueryReferent on
+ // our weak reference at the same time
+ CEnterLeaveXPCOMFramework _celf;
+ PyXPCOM_GatewayWeakReference *p = (PyXPCOM_GatewayWeakReference *)(nsISupports *)m_pWeakRef;
+ p->m_pBase = nsnull;
+ m_pWeakRef = nsnull;
+ }
+ PyXPCOM_DLLRelease();
+}
+
+// Get the correct interface pointer for this object given the IID.
+void *PyG_Base::ThisAsIID( const nsIID &iid )
+{
+ if (this==NULL) return NULL;
+ if (iid.Equals(NS_GET_IID(nsISupports)))
+ return (nsISupports *)(nsIInternalPython *)this;
+ if (iid.Equals(NS_GET_IID(nsISupportsWeakReference)))
+ return (nsISupportsWeakReference *)this;
+ if (iid.Equals(NS_GET_IID(nsIInternalPython)))
+ return (nsISupports *)(nsIInternalPython *)this;
+ return NULL;
+}
+
+// Call back into Python, passing a Python instance, and get back
+// an interface object that wraps the instance.
+/*static*/ PRBool
+PyG_Base::AutoWrapPythonInstance(PyObject *ob, const nsIID &iid, nsISupports **ppret)
+{
+ NS_PRECONDITION(ppret!=NULL, "null pointer when wrapping a Python instance!");
+ NS_PRECONDITION(ob && PyObject_HasAttrString(ob, "__class__"),
+ "AutoWrapPythonInstance is expecting an non-NULL instance!");
+ PRBool ok = PR_FALSE;
+ // XXX - todo - this static object leaks! (but Python on Windows leaks 2000+ objects as it is ;-)
+ static PyObject *func = NULL; // fetch this once and remember!
+ PyObject *obIID = NULL;
+ PyObject *wrap_ret = NULL;
+ PyObject *args = NULL;
+ if (func==NULL) { // not thread-safe, but nothing bad can happen, except an extra reference leak
+ PyObject *mod = PyImport_ImportModule("xpcom.server");
+ if (mod)
+ func = PyObject_GetAttrString(mod, "WrapObject");
+ Py_XDECREF(mod);
+ if (func==NULL) goto done;
+ }
+ // See if the instance has previously been wrapped.
+ if (CheckDefaultGateway(ob, iid, ppret)) {
+ ok = PR_TRUE; // life is good!
+ } else {
+ PyErr_Clear();
+
+ obIID = Py_nsIID::PyObjectFromIID(iid);
+ if (obIID==NULL) goto done;
+ args = Py_BuildValue("OOzi", ob, obIID, NULL, 0);
+ if (args==NULL) goto done;
+ wrap_ret = PyEval_CallObject(func, args);
+ if (wrap_ret==NULL) goto done;
+ ok = Py_nsISupports::InterfaceFromPyObject(wrap_ret, iid, ppret, PR_FALSE, PR_FALSE);
+#ifdef DEBUG
+ if (ok)
+ // Check we _now_ have a default gateway
+ {
+ nsISupports *temp = NULL;
+ NS_ABORT_IF_FALSE(CheckDefaultGateway(ob, iid, &temp), "Auto-wrapped object didnt get a default gateway!");
+ if (temp) temp->Release();
+ }
+#endif
+ }
+done:
+// Py_XDECREF(func); -- func is static for performance reasons.
+ Py_XDECREF(obIID);
+ Py_XDECREF(wrap_ret);
+ Py_XDECREF(args);
+ return ok;
+}
+
+// Call back into Python, passing a raw nsIInterface object, getting back
+// the object to actually use as the gateway parameter for this interface.
+// For example, it is expected that the policy will wrap the interface
+// object in one of the xpcom.client.Interface objects, allowing
+// natural usage of the interface from Python clients.
+// Note that piid will usually be NULL - this is because the runtime
+// reflection interfaces dont provide this information to me.
+// In this case, the Python code may choose to lookup the complete
+// interface info to obtain the IID.
+// It is expected (but should not be assumed) that the method info
+// or the IID will be NULL.
+// Worst case, the code should provide a wrapper for the nsiSupports interface,
+// so at least the user can simply QI the object.
+PyObject *
+PyG_Base::MakeInterfaceParam(nsISupports *pis,
+ const nsIID *piid,
+ int methodIndex /* = -1 */,
+ const XPTParamDescriptor *d /* = NULL */,
+ int paramIndex /* = -1 */)
+{
+ if (pis==NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ // This condition is true today, but not necessarily so.
+ // But if it ever triggers, the poor Python code has no real hope
+ // of returning something useful, so we should at least do our
+ // best to provide the useful data.
+ NS_WARN_IF_FALSE( ((piid != NULL) ^ (d != NULL)) == 1, "No information on the interface available - Python's gunna have a hard time doing much with it!");
+ PyObject *obIID = NULL;
+ PyObject *obISupports = NULL;
+ PyObject *obParamDesc = NULL;
+ PyObject *result = NULL;
+
+ // get the basic interface first, as if we fail, we can try and use this.
+ // If we don't know the IID, we must explicitly query for nsISupports.
+ nsCOMPtr<nsISupports> piswrap;
+ nsIID iid_check;
+ if (piid) {
+ iid_check = *piid;
+ piswrap = pis;
+ } else {
+ /* HACK ALERT! Dropping the python interpreter lock here while
+ doing QueryInterface because it may involve IPC to a python
+ object in the same interpreter and deadlock. Not at all
+ sure if this is a good idea or not for the internal PyXPCOM
+ state, but it might fix the deadloock... Hoping for the best. */
+ Py_BEGIN_ALLOW_THREADS;
+ iid_check = NS_GET_IID(nsISupports);
+ pis->QueryInterface(iid_check, getter_AddRefs(piswrap));
+ Py_END_ALLOW_THREADS;
+ }
+
+ obISupports = Py_nsISupports::PyObjectFromInterface(piswrap, iid_check, PR_FALSE);
+ if (!obISupports)
+ goto done;
+ if (piid==NULL) {
+ obIID = Py_None;
+ Py_INCREF(Py_None);
+ } else
+ obIID = Py_nsIID::PyObjectFromIID(*piid);
+ if (obIID==NULL)
+ goto done;
+ obParamDesc = PyObject_FromXPTParamDescriptor(d);
+ if (obParamDesc==NULL)
+ goto done;
+
+ result = PyObject_CallMethod(m_pPyObject,
+ (char*)"_MakeInterfaceParam_",
+ (char*)"OOiOi",
+ obISupports,
+ obIID,
+ methodIndex,
+ obParamDesc,
+ paramIndex);
+done:
+ if (PyErr_Occurred()) {
+ NS_WARN_IF_FALSE(result==NULL, "Have an error, but also a result!");
+ PyXPCOM_LogError("Wrapping an interface object for the gateway failed\n");
+ }
+ Py_XDECREF(obIID);
+ Py_XDECREF(obParamDesc);
+ if (result==NULL) { // we had an error.
+ PyErr_Clear(); // but are not reporting it back to Python itself!
+ // return our obISupports. If NULL, we are really hosed and nothing we can do.
+ return obISupports;
+ }
+ // Dont need to return this - we have a better result.
+ Py_XDECREF(obISupports);
+ return result;
+}
+
+NS_IMETHODIMP
+PyG_Base::QueryInterface(REFNSIID iid, void** ppv)
+{
+#ifdef PYXPCOM_DEBUG_FULL
+ {
+ char *sziid = iid.ToString();
+ LogF("PyGatewayBase::QueryInterface: %s", sziid);
+ Allocator::Free(sziid);
+ }
+#endif
+ NS_PRECONDITION(ppv, "NULL pointer");
+ if (ppv==nsnull)
+ return NS_ERROR_NULL_POINTER;
+ *ppv = nsnull;
+ // If one of our native interfaces (but NOT nsISupports if we have a base)
+ // return this.
+ // It is important is that nsISupports come from the base object
+ // to ensure that we live by XPCOM identity rules (other interfaces need
+ // not abide by this rule - only nsISupports.)
+ if ( (m_pBaseObject==NULL || !iid.Equals(NS_GET_IID(nsISupports)))
+ && (*ppv=ThisAsIID(iid)) != NULL ) {
+ AddRef();
+ return NS_OK;
+ }
+ // If we have a "base object", then we need to delegate _every_ remaining
+ // QI to it.
+ if (m_pBaseObject != NULL)
+ return m_pBaseObject->QueryInterface(iid, ppv);
+
+ // Call the Python policy to see if it (says it) supports the interface
+ PRBool supports = PR_FALSE;
+ { // temp scope for Python lock
+ CEnterLeavePython celp;
+
+ PyObject * ob = Py_nsIID::PyObjectFromIID(iid);
+ // must say this is an 'internal' call, else we recurse QI into
+ // oblivion.
+ PyObject * this_interface_ob = Py_nsISupports::PyObjectFromInterface(
+ (nsXPTCStubBase *)this,
+ iid, PR_FALSE, PR_TRUE);
+ if ( !ob || !this_interface_ob) {
+ Py_XDECREF(ob);
+ Py_XDECREF(this_interface_ob);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ PyObject *result = PyObject_CallMethod(m_pPyObject, (char*)"_QueryInterface_",
+ (char*)"OO",
+ this_interface_ob, ob);
+ Py_DECREF(ob);
+ Py_DECREF(this_interface_ob);
+
+ if ( result ) {
+ if (Py_nsISupports::InterfaceFromPyObject(result, iid, (nsISupports **)ppv, PR_TRUE)) {
+ // If OK, but NULL, _QI_ returned None, which simply means
+ // "no such interface"
+ supports = (*ppv!=NULL);
+ // result has been QI'd and AddRef'd all ready for return.
+ } else {
+ // Dump this message and any Python exception before
+ // reporting the fact that QI failed - this error
+ // may provide clues!
+ PyXPCOM_LogError("The _QueryInterface_ method returned an object of type '%s', but an interface was expected\n", PyXPCOM_ObTypeName(result));
+ // supports remains false
+ }
+ Py_DECREF(result);
+ } else {
+ NS_ABORT_IF_FALSE(PyErr_Occurred(), "Got NULL result, but no Python error flagged!");
+ NS_WARN_IF_FALSE(!supports, "Have failure with success flag set!");
+ PyXPCOM_LogError("The _QueryInterface_ processing failed.\n");
+ // supports remains false.
+ // We have reported the error, and are returning to COM,
+ // so we should clear it.
+ PyErr_Clear();
+ }
+ } // end of temp scope for Python lock - lock released here!
+ if ( !supports )
+ return NS_ERROR_NO_INTERFACE;
+ return NS_OK;
+}
+
+nsrefcnt
+PyG_Base::AddRef(void)
+{
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicIncrement((PRInt32*)&mRefCnt);
+#ifdef NS_BUILD_REFCNT_LOGGING
+ // If we have no pBaseObject, then we need to ignore them
+ if (m_pBaseObject == NULL)
+ NS_LOG_ADDREF(this, cnt, refcntLogRepr, sizeof(*this));
+#endif
+ return cnt;
+}
+
+nsrefcnt
+PyG_Base::Release(void)
+{
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicDecrement((PRInt32*)&mRefCnt);
+#ifdef NS_BUILD_REFCNT_LOGGING
+ if (m_pBaseObject == NULL)
+ NS_LOG_RELEASE(this, cnt, refcntLogRepr);
+#endif
+ if ( cnt == 0 )
+ delete this;
+ return cnt;
+}
+
+NS_IMETHODIMP
+PyG_Base::GetWeakReference(nsIWeakReference **ret)
+{
+ // always delegate back to the "base" gateway for the object, as this tear-off
+ // interface may not live as long as the base. So we recurse back to the base.
+ if (m_pBaseObject) {
+ NS_PRECONDITION(m_pWeakRef == nsnull, "Not a base object, but do have a weak-ref!");
+ return m_pBaseObject->GetWeakReference(ret);
+ }
+ NS_PRECONDITION(ret, "null pointer");
+ if (ret==nsnull) return NS_ERROR_INVALID_POINTER;
+ if (!m_pWeakRef) {
+ // First query for a weak reference - create it.
+ // XXX - this looks like it needs thread safety!?
+ m_pWeakRef = new PyXPCOM_GatewayWeakReference(this);
+ NS_ABORT_IF_FALSE(m_pWeakRef, "Shouldn't be able to fail creating a weak reference!");
+ if (!m_pWeakRef)
+ return NS_ERROR_UNEXPECTED;
+ }
+ *ret = m_pWeakRef;
+ (*ret)->AddRef();
+ return NS_OK;
+}
+
+nsresult PyG_Base::HandleNativeGatewayError(const char *szMethodName)
+{
+ nsresult rc = NS_OK;
+ if (PyErr_Occurred()) {
+ // The error handling - fairly involved, but worth it as
+ // good error reporting is critical for users to know WTF
+ // is going on - especially with TypeErrors etc in their
+ // return values (ie, after the Python code has successfully
+ // exited, but we encountered errors unpacking their
+ // result values for the COM caller - there is literally no
+ // way to catch these exceptions from Python code, as their
+ // is no Python function directly on the call-stack)
+
+ // First line of attack in an error is to call-back on the policy.
+ // If the callback of the error handler succeeds and returns an
+ // integer (for the nsresult), we take no further action.
+
+ // If this callback fails, we log _2_ exceptions - the error
+ // handler error, and the original error.
+
+ PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing!
+ PyObject *exc_typ, *exc_val, *exc_tb;
+ PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
+
+ PyObject *err_result = PyObject_CallMethod(m_pPyObject,
+ (char*)"_GatewayException_",
+ (char*)"z(OOO)",
+ szMethodName,
+ exc_typ ? exc_typ : Py_None, // should never be NULL, but defensive programming...
+ exc_val ? exc_val : Py_None, // may well be NULL.
+ exc_tb ? exc_tb : Py_None); // may well be NULL.
+ if (err_result == NULL) {
+ PyXPCOM_LogError("The exception handler _CallMethodException_ failed!\n");
+ } else if (err_result == Py_None) {
+ // The exception handler has chosen not to do anything with
+ // this error, so we still need to print it!
+ ;
+ } else if (PyInt_Check(err_result)) {
+ // The exception handler has given us the nresult.
+ rc = PyInt_AsLong(err_result);
+ bProcessMainError = PR_FALSE;
+ } else {
+ // The exception handler succeeded, but returned other than
+ // int or None.
+ PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", PyXPCOM_ObTypeName(err_result));
+ }
+ Py_XDECREF(err_result);
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+ if (bProcessMainError) {
+ PyXPCOM_LogError("The function '%s' failed\n", szMethodName);
+ rc = PyXPCOM_SetCOMErrorFromPyException();
+ }
+ PyErr_Clear();
+ }
+ return rc;
+}
+
+static nsresult do_dispatch(
+ PyObject *pPyObject,
+ PyObject **ppResult,
+ const char *szMethodName,
+ const char *szFormat,
+ va_list va
+ )
+{
+ NS_PRECONDITION(ppResult, "Must provide a result buffer");
+ *ppResult = nsnull;
+ // Build the Invoke arguments...
+ PyObject *args = NULL;
+ PyObject *method = NULL;
+ PyObject *real_ob = NULL;
+ nsresult ret = NS_ERROR_FAILURE;
+ if ( szFormat )
+ args = Py_VaBuildValue((char *)szFormat, va);
+ else
+ args = PyTuple_New(0);
+ if ( !args )
+ goto done;
+
+ // make sure a tuple.
+ if ( !PyTuple_Check(args) ) {
+ PyObject *a = PyTuple_New(1);
+ if ( a == NULL )
+ {
+ Py_DECREF(args);
+ goto done;
+ }
+ PyTuple_SET_ITEM(a, 0, args);
+ args = a;
+ }
+ // Bit to a hack here to maintain the use of a policy.
+ // We actually get the policies underlying object
+ // to make the call on.
+ real_ob = PyObject_GetAttrString(pPyObject, "_obj_");
+ if (real_ob == NULL) {
+ PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute.");
+ goto done;
+ }
+ method = PyObject_GetAttrString(real_ob, (char *)szMethodName);
+ if ( !method ) {
+ PyErr_Clear();
+ ret = NS_PYXPCOM_NO_SUCH_METHOD;
+ goto done;
+ }
+ // Make the call
+ *ppResult = PyEval_CallObject(method, args);
+ ret = *ppResult ? NS_OK : NS_ERROR_FAILURE;
+done:
+ Py_XDECREF(method);
+ Py_XDECREF(real_ob);
+ Py_XDECREF(args);
+ return ret;
+}
+
+
+nsresult PyG_Base::InvokeNativeViaPolicyInternal(
+ const char *szMethodName,
+ PyObject **ppResult,
+ const char *szFormat,
+ va_list va
+ )
+{
+ if ( m_pPyObject == NULL || szMethodName == NULL )
+ return NS_ERROR_NULL_POINTER;
+
+ PyObject *temp = nsnull;
+ if (ppResult == nsnull)
+ ppResult = &temp;
+ nsresult nr = do_dispatch(m_pPyObject, ppResult, szMethodName, szFormat, va);
+
+ // If temp is NULL, they provided a buffer, and we dont touch it.
+ // If not NULL, *ppResult = temp, and _we_ do own it.
+ Py_XDECREF(temp);
+ return nr;
+}
+
+nsresult PyG_Base::InvokeNativeViaPolicy(
+ const char *szMethodName,
+ PyObject **ppResult /* = NULL */,
+ const char *szFormat /* = NULL */,
+ ...
+ )
+{
+ va_list va;
+ va_start(va, szFormat);
+ nsresult nr = InvokeNativeViaPolicyInternal(szMethodName, ppResult, szFormat, va);
+ va_end(va);
+
+ if (nr == NS_PYXPCOM_NO_SUCH_METHOD) {
+ // Only problem was missing method.
+ PyErr_Format(PyExc_AttributeError, "The object does not have a '%s' function.", szMethodName);
+ }
+ return nr == NS_OK ? NS_OK : HandleNativeGatewayError(szMethodName);
+}
+
+nsresult PyG_Base::InvokeNativeGetViaPolicy(
+ const char *szPropertyName,
+ PyObject **ppResult /* = NULL */
+ )
+{
+ PyObject *ob_ret = NULL;
+ nsresult ret = NS_OK;
+ PyObject *real_ob = NULL;
+ if ( m_pPyObject == NULL || szPropertyName == NULL )
+ return NS_ERROR_NULL_POINTER;
+ // First see if we have a method of that name.
+ char buf[256];
+ strcpy(buf, "get_");
+ strncat(buf, szPropertyName, sizeof(buf)*sizeof(buf[0])-strlen(buf)-1);
+ buf[sizeof(buf)/sizeof(buf[0])-1] = '\0';
+ ret = InvokeNativeViaPolicyInternal(buf, ppResult, nsnull, nsnull);
+ if (ret == NS_PYXPCOM_NO_SUCH_METHOD) {
+ // No method of that name - just try a property.
+ // Bit to a hack here to maintain the use of a policy.
+ // We actually get the policies underlying object
+ // to make the call on.
+ real_ob = PyObject_GetAttrString(m_pPyObject, "_obj_");
+ if (real_ob == NULL) {
+ PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute.");
+ ret = HandleNativeGatewayError(szPropertyName);
+ goto done;
+ }
+ ob_ret = PyObject_GetAttrString(real_ob, (char *)szPropertyName);
+ if (ob_ret==NULL) {
+ PyErr_Format(PyExc_AttributeError,
+ "The object does not have a 'get_%s' function, or a '%s attribute.",
+ szPropertyName, szPropertyName);
+ } else {
+ ret = NS_OK;
+ if (ppResult)
+ *ppResult = ob_ret;
+ else
+ Py_XDECREF(ob_ret);
+ }
+ }
+ if (ret != NS_OK)
+ ret = HandleNativeGatewayError(szPropertyName);
+
+done:
+ Py_XDECREF(real_ob);
+ return ret;
+}
+
+nsresult PyG_Base::InvokeNativeSetViaPolicy(
+ const char *szPropertyName,
+ ...
+ )
+{
+ if ( m_pPyObject == NULL || szPropertyName == NULL )
+ return NS_ERROR_NULL_POINTER;
+ nsresult ret = NS_OK;
+ PyObject *real_ob = NULL;
+ char buf[256];
+ strcpy(buf, "set_");
+ strncat(buf, szPropertyName, sizeof(buf)*sizeof(buf[0])-strlen(buf)-1);
+ buf[sizeof(buf)/sizeof(buf[0])-1] = '\0';
+ va_list va;
+ va_start(va, szPropertyName);
+ ret = InvokeNativeViaPolicyInternal(buf, NULL, "O", va);
+ va_end(va);
+ if (ret == NS_PYXPCOM_NO_SUCH_METHOD) {
+ // No method of that name - just try a property.
+ // Bit to a hack here to maintain the use of a policy.
+ // We actually get the policies underlying object
+ // to make the call on.
+ real_ob = PyObject_GetAttrString(m_pPyObject, "_obj_");
+ if (real_ob == NULL) {
+ PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute.");
+ ret = HandleNativeGatewayError(szPropertyName);
+ goto done;
+ }
+ va_list va2;
+ va_start(va2, szPropertyName);
+ PyObject *arg = va_arg( va2, PyObject *);
+ va_end(va2);
+ if (PyObject_SetAttrString(real_ob, (char *)szPropertyName, arg) == 0)
+ ret = NS_OK;
+ else {
+ PyErr_Format(PyExc_AttributeError,
+ "The object does not have a 'set_%s' function, or a '%s attribute.",
+ szPropertyName, szPropertyName);
+ }
+ }
+ if (ret != NS_OK)
+ ret = HandleNativeGatewayError(szPropertyName);
+done:
+ Py_XDECREF(real_ob);
+ return ret;
+}
+
+// Get at the underlying Python object.
+PyObject *PyG_Base::UnwrapPythonObject(void)
+{
+ Py_INCREF(m_pPyObject);
+ return m_pPyObject;
+}
+/******************************************************
+
+ Some special support to help with object identity.
+
+ In the simplest case, assume a Python XPCOM object is
+ supporting a function "nsIWhatever GetWhatever()",
+ so implements it as:
+ return self
+ it is almost certain they intend returning
+ the same COM OBJECT to the caller! Thus, if a user of this COM
+ object does:
+
+ p1 = foo.GetWhatever();
+ p2 = foo.GetWhatever();
+
+ We almost certainly expect p1==p2==foo.
+
+ We previously _did_ have special support for the "self"
+ example above, but this implements a generic scheme that
+ works for _all_ objects.
+
+ Whenever we are asked to "AutoWrap" a Python object, the
+ first thing we do is see if it has been auto-wrapped before.
+
+ If not, we create a new wrapper, then make a COM weak reference
+ to that wrapper, and store it directly back into the instance
+ we are auto-wrapping! The use of a weak-reference prevents
+ cycles.
+
+ The existance of this attribute in an instance indicates if it
+ has been previously auto-wrapped.
+
+ If it _has_ previously been auto-wrapped, we de-reference the
+ weak reference, and use that gateway.
+
+*********************************************************************/
+
+PyG_Base *GetDefaultGateway(PyObject *policy)
+{
+ // NOTE: Instance is the policy, not the real instance
+ PyObject *instance = PyObject_GetAttrString(policy, "_obj_");
+ if (instance == nsnull)
+ return nsnull;
+ PyObject *ob_existing_weak = PyObject_GetAttrString(instance, PyXPCOM_szDefaultGatewayAttributeName);
+ Py_DECREF(instance);
+ if (ob_existing_weak != NULL) {
+ PRBool ok = PR_TRUE;
+ nsCOMPtr<nsIWeakReference> pWeakRef;
+ ok = NS_SUCCEEDED(Py_nsISupports::InterfaceFromPyObject(ob_existing_weak,
+ NS_GET_IID(nsIWeakReference),
+ getter_AddRefs(pWeakRef),
+ PR_FALSE));
+ Py_DECREF(ob_existing_weak);
+ nsISupports *pip;
+ if (ok) {
+ nsresult nr = pWeakRef->QueryReferent( NS_GET_IID(nsIInternalPython), (void **)&pip);
+ if (NS_FAILED(nr))
+ return nsnull;
+ return (PyG_Base *)(nsIInternalPython *)pip;
+ }
+ } else
+ PyErr_Clear();
+ return nsnull;
+}
+
+PRBool CheckDefaultGateway(PyObject *real_inst, REFNSIID iid, nsISupports **ret_gateway)
+{
+ NS_ABORT_IF_FALSE(real_inst, "Did not have an _obj_ attribute");
+ if (real_inst==NULL) {
+ PyErr_Clear();
+ return PR_FALSE;
+ }
+ PyObject *ob_existing_weak = PyObject_GetAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName);
+ if (ob_existing_weak != NULL) {
+ // We have an existing default, but as it is a weak reference, it
+ // may no longer be valid. Check it.
+ PRBool ok = PR_TRUE;
+ nsCOMPtr<nsIWeakReference> pWeakRef;
+ ok = NS_SUCCEEDED(Py_nsISupports::InterfaceFromPyObject(ob_existing_weak,
+ NS_GET_IID(nsIWeakReference),
+ getter_AddRefs(pWeakRef),
+ PR_FALSE));
+ Py_DECREF(ob_existing_weak);
+ if (ok) {
+ Py_BEGIN_ALLOW_THREADS;
+ ok = NS_SUCCEEDED(pWeakRef->QueryReferent( iid, (void **)(ret_gateway)));
+ Py_END_ALLOW_THREADS;
+ }
+ if (!ok) {
+ // We have the attribute, but not valid - wipe it
+ // before restoring it.
+ if (0 != PyObject_DelAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName))
+ PyErr_Clear();
+ }
+ return ok;
+ }
+ PyErr_Clear();
+ return PR_FALSE;
+}
+
+void AddDefaultGateway(PyObject *instance, nsISupports *gateway)
+{
+ // NOTE: Instance is the _policy_!
+ PyObject *real_inst = PyObject_GetAttrString(instance, "_obj_");
+ NS_ABORT_IF_FALSE(real_inst, "Could not get the '_obj_' element");
+ if (!real_inst) return;
+ if (!PyObject_HasAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName)) {
+ nsCOMPtr<nsISupportsWeakReference> swr( do_QueryInterface((nsISupportsWeakReference *)(gateway)) );
+ NS_ABORT_IF_FALSE(swr, "Our gateway failed with a weak reference query");
+ // Create the new default gateway - get a weak reference for our gateway.
+ if (swr) {
+ nsCOMPtr<nsIWeakReference> pWeakReference;
+ swr->GetWeakReference( getter_AddRefs(pWeakReference) );
+ if (pWeakReference) {
+ PyObject *ob_new_weak = Py_nsISupports::PyObjectFromInterface(pWeakReference,
+ NS_GET_IID(nsIWeakReference),
+ PR_FALSE ); /* bMakeNicePyObject */
+ // pWeakReference reference consumed.
+ if (ob_new_weak) {
+ PyObject_SetAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName, ob_new_weak);
+ Py_DECREF(ob_new_weak);
+ }
+ }
+ }
+ }
+ Py_DECREF(real_inst);
+}
diff --git a/src/libs/xpcom18a4/python/src/PyGInputStream.cpp b/src/libs/xpcom18a4/python/src/PyGInputStream.cpp
new file mode 100644
index 00000000..d7c27043
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyGInputStream.cpp
@@ -0,0 +1,173 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// PyGInputStream.cpp
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written October 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIInputStream.h>
+
+class PyG_nsIInputStream : public PyG_Base, public nsIInputStream
+{
+public:
+ PyG_nsIInputStream(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIInputStream)) {;}
+ PYGATEWAY_BASE_SUPPORT(nsIInputStream, PyG_Base);
+
+ NS_IMETHOD Close(void);
+ NS_IMETHOD Available(PRUint32 *_retval);
+ NS_IMETHOD Read(char * buf, PRUint32 count, PRUint32 *_retval);
+ NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval);
+ NS_IMETHOD IsNonBlocking(PRBool *aNonBlocking);
+};
+
+
+PyG_Base *MakePyG_nsIInputStream(PyObject *instance)
+{
+ return new PyG_nsIInputStream(instance);
+}
+
+NS_IMETHODIMP
+PyG_nsIInputStream::Close()
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "close";
+ return InvokeNativeViaPolicy(methodName, NULL);
+}
+
+NS_IMETHODIMP
+PyG_nsIInputStream::Available(PRUint32 *_retval)
+{
+ NS_PRECONDITION(_retval, "null pointer");
+ CEnterLeavePython _celp;
+ PyObject *ret;
+ const char *methodName = "available";
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret);
+ if (NS_SUCCEEDED(nr)) {
+ *_retval = PyInt_AsLong(ret);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ Py_XDECREF(ret);
+ }
+ return nr;
+}
+
+NS_IMETHODIMP
+PyG_nsIInputStream::Read(char * buf, PRUint32 count, PRUint32 *_retval)
+{
+ NS_PRECONDITION(_retval, "null pointer");
+ NS_PRECONDITION(buf, "null pointer");
+ CEnterLeavePython _celp;
+ PyObject *ret;
+ const char *methodName = "read";
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "i", count);
+ if (NS_SUCCEEDED(nr)) {
+#if 0 /* VBox: new buffer protocol (though I could use it for Py_LIMITED_API and ditch the warning, but cpython specific) */
+ Py_buffer py_view;
+ if (PyObject_GetBuffer(ret, &py_view, PyBUF_SIMPLE) == 0) {
+ if (py_view.len <= count) {
+ count = py_view.len;
+ } else {
+ PyXPCOM_LogWarning("nsIInputStream::read() was asked for %d bytes, but the string returned is %d bytes - truncating!\n", count, py_size);
+ }
+ memcpy(buf, py_view.py_buf, count);
+ PyBuffer_Release(&py_view);
+ *_retval = count;
+ } else {
+ PyErr_Format(PyExc_TypeError, "nsIInputStream::read() method must return a buffer object - not a '%s' object", PyXPCOM_ObTypeName(ret));
+ nr = HandleNativeGatewayError(methodName);
+ }
+#else /* Old protocol: */
+# ifndef VBOX /* unsafe cast on 64-bit hosts. */
+ PRUint32 py_size;
+ const void *py_buf;
+ if (PyObject_AsReadBuffer(ret, &py_buf, (Py_ssize_t*)&py_size)!=0) {
+# else /* VBOX */
+ const void *py_buf;
+# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
+ Py_ssize_t py_size;
+# else
+ int py_size;
+# endif
+ if (PyObject_AsReadBuffer(ret, &py_buf, &py_size)!=0) {
+# endif /* VBOX */
+ PyErr_Format(PyExc_TypeError, "nsIInputStream::read() method must return a buffer object - not a '%s' object", PyXPCOM_ObTypeName(ret));
+ nr = HandleNativeGatewayError(methodName);
+ } else {
+ if (py_size > count) {
+ PyXPCOM_LogWarning("nsIInputStream::read() was asked for %d bytes, but the string returned is %d bytes - truncating!\n", count, py_size);
+ py_size = count;
+ }
+ memcpy(buf, py_buf, py_size);
+ *_retval = py_size;
+ }
+#endif
+ }
+ return nr;
+}
+
+
+NS_IMETHODIMP
+PyG_nsIInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
+{
+ NS_WARNING("ReadSegments() not implemented!!!");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+PyG_nsIInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ NS_PRECONDITION(aNonBlocking, "null pointer");
+ CEnterLeavePython _celp;
+ PyObject *ret;
+ const char *methodName = "isNonBlocking";
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret);
+ if (NS_SUCCEEDED(nr)) {
+ *aNonBlocking = PyInt_AsLong(ret);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ Py_XDECREF(ret);
+ }
+ return nr;
+}
diff --git a/src/libs/xpcom18a4/python/src/PyGModule.cpp b/src/libs/xpcom18a4/python/src/PyGModule.cpp
new file mode 100644
index 00000000..599e0f87
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyGModule.cpp
@@ -0,0 +1,297 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+// Unfortunately, we can not use an XPConnect object for
+// the nsiModule and nsiComponentLoader interfaces.
+// As XPCOM shuts down, it shuts down the interface manager before
+// it releases all the modules. This is a bit of a problem for
+// us, as it means we can't get runtime info on the interface at shutdown time.
+
+#include "PyXPCOM_std.h"
+#include <nsIModule.h>
+#include <nsIComponentLoader.h>
+
+class PyG_nsIModule : public PyG_Base, public nsIModule
+{
+public:
+ PyG_nsIModule(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIModule)) {;}
+ PYGATEWAY_BASE_SUPPORT(nsIModule, PyG_Base);
+
+ NS_DECL_NSIMODULE
+};
+
+PyG_Base *MakePyG_nsIModule(PyObject *instance)
+{
+ return new PyG_nsIModule(instance);
+}
+
+
+// Create a factory object for creating instances of aClass.
+NS_IMETHODIMP
+PyG_nsIModule::GetClassObject(nsIComponentManager *aCompMgr,
+ const nsCID& aClass,
+ const nsIID& aIID,
+ void** r_classObj)
+{
+ NS_PRECONDITION(r_classObj, "null pointer");
+ *r_classObj = nsnull;
+ CEnterLeavePython _celp;
+ PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
+ PyObject *iid = Py_nsIID::PyObjectFromIID(aIID);
+ PyObject *clsid = Py_nsIID::PyObjectFromIID(aClass);
+ const char *methodName = "getClassObject";
+ PyObject *ret = NULL;
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "OOO", cm, clsid, iid);
+ Py_XDECREF(cm);
+ Py_XDECREF(iid);
+ Py_XDECREF(clsid);
+ if (NS_SUCCEEDED(nr)) {
+ nr = Py_nsISupports::InterfaceFromPyObject(ret, aIID, (nsISupports **)r_classObj, PR_FALSE);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ }
+ if (NS_FAILED(nr)) {
+ NS_ABORT_IF_FALSE(*r_classObj==NULL, "returning error result with an interface - probable leak!");
+ }
+ Py_XDECREF(ret);
+ return nr;
+}
+
+NS_IMETHODIMP
+PyG_nsIModule::RegisterSelf(nsIComponentManager *aCompMgr,
+ nsIFile* aPath,
+ const char* registryLocation,
+ const char* componentType)
+{
+ NS_PRECONDITION(aCompMgr, "null pointer");
+ NS_PRECONDITION(aPath, "null pointer");
+ CEnterLeavePython _celp;
+ PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
+ PyObject *path = PyObject_FromNSInterface(aPath, NS_GET_IID(nsIFile));
+ const char *methodName = "registerSelf";
+ nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOzz", cm, path, registryLocation, componentType);
+ Py_XDECREF(cm);
+ Py_XDECREF(path);
+ return nr;
+}
+
+NS_IMETHODIMP
+PyG_nsIModule::UnregisterSelf(nsIComponentManager* aCompMgr,
+ nsIFile* aPath,
+ const char* registryLocation)
+{
+ NS_PRECONDITION(aCompMgr, "null pointer");
+ NS_PRECONDITION(aPath, "null pointer");
+ CEnterLeavePython _celp;
+ PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
+ PyObject *path = PyObject_FromNSInterface(aPath, NS_GET_IID(nsIFile));
+ const char *methodName = "unregisterSelf";
+ nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOz", cm, path, registryLocation);
+ Py_XDECREF(cm);
+ Py_XDECREF(path);
+ return nr;
+}
+
+NS_IMETHODIMP
+PyG_nsIModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload)
+{
+ NS_PRECONDITION(aCompMgr, "null pointer");
+ NS_PRECONDITION(okToUnload, "null pointer");
+ CEnterLeavePython _celp;
+ // we are shutting down - don't ask for a nice wrapped object.
+ PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager), PR_FALSE);
+ const char *methodName = "canUnload";
+ PyObject *ret = NULL;
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "O", cm);
+ Py_XDECREF(cm);
+ if (NS_SUCCEEDED(nr)) {
+ *okToUnload = PyInt_AsLong(ret);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ }
+ Py_XDECREF(ret);
+ return nr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
+class PyG_nsIComponentLoader : public PyG_Base, public nsIComponentLoader
+{
+public:
+ PyG_nsIComponentLoader(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIComponentLoader)) {;}
+ PYGATEWAY_BASE_SUPPORT(nsIComponentLoader, PyG_Base);
+
+ NS_DECL_NSICOMPONENTLOADER
+};
+
+PyG_Base *MakePyG_nsIComponentLoader(PyObject *instance)
+{
+ return new PyG_nsIComponentLoader(instance);
+}
+
+/* nsIFactory getFactory (in nsIIDRef aCID, in string aLocation, in string aType); */
+NS_IMETHODIMP PyG_nsIComponentLoader::GetFactory(const nsIID & aCID, const char *aLocation, const char *aType, nsIFactory **_retval)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "getFactory";
+ PyObject *iid = Py_nsIID::PyObjectFromIID(aCID);
+ PyObject *ret = NULL;
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "Ozz",
+ iid,
+ aLocation,
+ aType);
+ Py_XDECREF(iid);
+ if (NS_SUCCEEDED(nr)) {
+ Py_nsISupports::InterfaceFromPyObject(ret, NS_GET_IID(nsIFactory), (nsISupports **)_retval, PR_FALSE);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ }
+ Py_XDECREF(ret);
+ return nr;
+}
+
+/* void init (in nsIComponentManager aCompMgr, in nsISupports aRegistry); */
+NS_IMETHODIMP PyG_nsIComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aRegistry)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "init";
+ PyObject *c = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
+ PyObject *r = PyObject_FromNSInterface(aRegistry, NS_GET_IID(nsISupports));
+ nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OO", c, r);
+ Py_XDECREF(c);
+ Py_XDECREF(r);
+ return nr;
+}
+
+/* void onRegister (in nsIIDRef aCID, in string aType, in string aClassName, in string aContractID, in string aLocation, in boolean aReplace, in boolean aPersist); */
+NS_IMETHODIMP PyG_nsIComponentLoader::OnRegister(const nsIID & aCID, const char *aType, const char *aClassName, const char *aContractID, const char *aLocation, PRBool aReplace, PRBool aPersist)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "onRegister";
+ PyObject *iid = Py_nsIID::PyObjectFromIID(aCID);
+ nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "Ossssii",
+ iid,
+ aType,
+ aClassName,
+ aContractID,
+ aLocation,
+ aReplace,
+ aPersist);
+ Py_XDECREF(iid);
+ return nr;
+}
+
+/* void autoRegisterComponents (in long aWhen, in nsIFile aDirectory); */
+NS_IMETHODIMP PyG_nsIComponentLoader::AutoRegisterComponents(PRInt32 aWhen, nsIFile *aDirectory)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "autoRegisterComponents";
+ PyObject *c = PyObject_FromNSInterface(aDirectory, NS_GET_IID(nsIFile));
+ nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "iO", aWhen, c);
+ Py_XDECREF(c);
+ return nr;
+}
+
+/* boolean autoRegisterComponent (in long aWhen, in nsIFile aComponent); */
+NS_IMETHODIMP PyG_nsIComponentLoader::AutoRegisterComponent(PRInt32 aWhen, nsIFile *aComponent, PRBool *_retval)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "autoRegisterComponent";
+ PyObject *ret = NULL;
+ PyObject *c = PyObject_FromNSInterface(aComponent, NS_GET_IID(nsIFile));
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "iO", aWhen, c);
+ Py_XDECREF(c);
+ if (NS_SUCCEEDED(nr)) {
+ *_retval = PyInt_AsLong(ret);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ }
+ Py_XDECREF(ret);
+ return nr;
+}
+
+/* boolean autoUnregisterComponent (in long aWhen, in nsIFile aComponent); */
+NS_IMETHODIMP PyG_nsIComponentLoader::AutoUnregisterComponent(PRInt32 aWhen, nsIFile *aComponent, PRBool *_retval)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "autoUnregisterComponent";
+ PyObject *ret = NULL;
+ PyObject *c = PyObject_FromNSInterface(aComponent, NS_GET_IID(nsIFile));
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "iO", aWhen, c);
+ Py_XDECREF(c);
+ if (NS_SUCCEEDED(nr)) {
+ *_retval = PyInt_AsLong(ret);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ }
+ Py_XDECREF(ret);
+ return nr;
+}
+
+/* boolean registerDeferredComponents (in long aWhen); */
+NS_IMETHODIMP PyG_nsIComponentLoader::RegisterDeferredComponents(PRInt32 aWhen, PRBool *_retval)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "registerDeferredComponents";
+ PyObject *ret = NULL;
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "i", aWhen);
+ if (NS_SUCCEEDED(nr)) {
+ *_retval = PyInt_AsLong(ret);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ }
+ Py_XDECREF(ret);
+ return nr;
+}
+
+/* void unloadAll (in long aWhen); */
+NS_IMETHODIMP PyG_nsIComponentLoader::UnloadAll(PRInt32 aWhen)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "unloadAll";
+ return InvokeNativeViaPolicy(methodName, NULL, "i", aWhen);
+}
diff --git a/src/libs/xpcom18a4/python/src/PyGStub.cpp b/src/libs/xpcom18a4/python/src/PyGStub.cpp
new file mode 100644
index 00000000..6f219333
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyGStub.cpp
@@ -0,0 +1,180 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// PyXPTStub - the stub for implementing interfaces.
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIInterfaceInfoManager.h>
+
+void *PyXPCOM_XPTStub::ThisAsIID(const nsIID &iid)
+{
+ if (iid.Equals(NS_GET_IID(nsISupports)))
+ return (nsISupports *)(nsXPTCStubBase *)this;
+ else if (iid.Equals(m_iid))
+ return (nsISupports *)(nsXPTCStubBase *)this;
+ else
+ return PyG_Base::ThisAsIID(iid);
+}
+
+
+NS_IMETHODIMP
+PyXPCOM_XPTStub::GetInterfaceInfo(nsIInterfaceInfo** info)
+{
+ NS_PRECONDITION(info, "NULL pointer");
+ if (info==nsnull)
+ return NS_ERROR_NULL_POINTER;
+ // Simply get the XPCOM runtime to provide this
+ // (but there must be some reason why they dont get it themselves!?
+ // Maybe because they dont know the IID?
+ nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
+ NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+ NS_ABORT_IF_FALSE(iim != nsnull, "Cant get interface from IIM!");
+ if (iim==nsnull)
+ return NS_ERROR_FAILURE;
+
+ return iim->GetInfoForIID( &m_iid, info);
+}
+
+// call this method and return result
+NS_IMETHODIMP
+PyXPCOM_XPTStub::CallMethod(PRUint16 methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant* params)
+{
+ nsresult rc = NS_ERROR_FAILURE;
+ NS_PRECONDITION(info, "NULL methodinfo pointer");
+ NS_PRECONDITION(params, "NULL variant pointer");
+ CEnterLeavePython _celp;
+ PyObject *obParams = NULL;
+ PyObject *result = NULL;
+ PyObject *obThisObject = NULL;
+ PyObject *obMI = PyObject_FromXPTMethodDescriptor(info);
+ PyXPCOM_GatewayVariantHelper arg_helper(this, methodIndex, info, params);
+ if (obMI==NULL)
+ goto done;
+ // base object is passed raw.
+ obThisObject = PyObject_FromNSInterface((nsXPTCStubBase *)this,
+ m_iid, PR_FALSE);
+ obParams = arg_helper.MakePyArgs();
+ if (obParams==NULL)
+ goto done;
+ result = PyObject_CallMethod(m_pPyObject,
+ (char*)"_CallMethod_",
+ (char*)"OiOO",
+ obThisObject,
+ (int)methodIndex,
+ obMI,
+ obParams);
+ if (result!=NULL) {
+ rc = arg_helper.ProcessPythonResult(result);
+ // Use an xor to check failure && pyerr, or !failure && !pyerr.
+ NS_ABORT_IF_FALSE( ((NS_FAILED(rc)!=0)^(PyErr_Occurred()!=0)) == 0, "We must have failure with a Python error, or success without a Python error.");
+ }
+done:
+ if (PyErr_Occurred()) {
+ // The error handling - fairly involved, but worth it as
+ // good error reporting is critical for users to know WTF
+ // is going on - especially with TypeErrors etc in their
+ // return values (ie, after the Python code has successfully
+ // exited, but we encountered errors unpacking the
+ // result values for the COM caller - there is literally no
+ // way to catch these exceptions from Python code, as their
+ // is no Python function on the call-stack)
+
+ // First line of attack in an error is to call-back on the policy.
+ // If the callback of the error handler succeeds and returns an
+ // integer (for the nsresult), we take no further action.
+
+ // If this callback fails, we log _2_ exceptions - the error handler
+ // error, and the original error.
+
+ PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing!
+ PyObject *exc_typ, *exc_val, *exc_tb;
+ PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
+ PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
+
+ PyObject *err_result = PyObject_CallMethod(m_pPyObject,
+ (char*)"_CallMethodException_",
+ (char*)"OiOO(OOO)",
+ obThisObject,
+ (int)methodIndex,
+ obMI,
+ obParams,
+ exc_typ ? exc_typ : Py_None, // should never be NULL, but defensive programming...
+ exc_val ? exc_val : Py_None, // may well be NULL.
+ exc_tb ? exc_tb : Py_None); // may well be NULL.
+ if (err_result == NULL) {
+ PyXPCOM_LogError("The exception handler _CallMethodException_ failed!\n");
+ } else if (err_result == Py_None) {
+ // The exception handler has chosen not to do anything with
+ // this error, so we still need to print it!
+ ;
+ } else if (PyInt_Check(err_result)) {
+ // The exception handler has given us the nresult.
+ rc = PyInt_AsLong(err_result);
+ bProcessMainError = PR_FALSE;
+ } else {
+ // The exception handler succeeded, but returned other than
+ // int or None.
+ PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", PyXPCOM_ObTypeName(err_result));
+ }
+ Py_XDECREF(err_result);
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+ if (bProcessMainError) {
+ PyXPCOM_LogError("The function '%s' failed\n", info->GetName());
+ rc = PyXPCOM_SetCOMErrorFromPyException();
+ }
+ // else everything is already setup,
+ // just clear the Python error state.
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(obMI);
+ Py_XDECREF(obParams);
+ Py_XDECREF(obThisObject);
+ Py_XDECREF(result);
+ return rc;
+}
diff --git a/src/libs/xpcom18a4/python/src/PyGWeakReference.cpp b/src/libs/xpcom18a4/python/src/PyGWeakReference.cpp
new file mode 100644
index 00000000..e5254acc
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyGWeakReference.cpp
@@ -0,0 +1,112 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// PyGWeakReference - implements weak references for gateways.
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written November 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+
+PyXPCOM_GatewayWeakReference::PyXPCOM_GatewayWeakReference( PyG_Base *base )
+{
+ m_pBase = base;
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ // bloat view uses 40 chars - stick "(WR)" at the end of this position.
+ strncpy(refcntLogRepr, m_pBase->refcntLogRepr, sizeof(refcntLogRepr));
+ refcntLogRepr[sizeof(refcntLogRepr)-1] = '\0';
+ char *dest = refcntLogRepr + ((strlen(refcntLogRepr) > 36) ? 36 : strlen(refcntLogRepr));
+ strcpy(dest, "(WR)");
+#endif // NS_BUILD_REFCNT_LOGGING
+}
+
+PyXPCOM_GatewayWeakReference::~PyXPCOM_GatewayWeakReference()
+{
+ // Simply zap my reference to the gateway!
+ // No need to zap my gateway's reference to me, as
+ // it already holds a reference, so if we are destructing,
+ // then it can't possibly hold one.
+ m_pBase = NULL;
+}
+
+nsrefcnt
+PyXPCOM_GatewayWeakReference::AddRef(void)
+{
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicIncrement((PRInt32*)&mRefCnt);
+#ifdef NS_BUILD_REFCNT_LOGGING
+ NS_LOG_ADDREF(this, cnt, refcntLogRepr, sizeof(*this));
+#endif
+ return cnt;
+}
+
+nsrefcnt
+PyXPCOM_GatewayWeakReference::Release(void)
+{
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicDecrement((PRInt32*)&mRefCnt);
+#ifdef NS_BUILD_REFCNT_LOGGING
+ NS_LOG_RELEASE(this, cnt, refcntLogRepr);
+#endif
+ if ( cnt == 0 )
+ delete this;
+ return cnt;
+}
+
+NS_IMPL_THREADSAFE_QUERY_INTERFACE1(PyXPCOM_GatewayWeakReference, nsIWeakReference)
+
+NS_IMETHODIMP
+PyXPCOM_GatewayWeakReference::QueryReferent(REFNSIID iid, void * *ret)
+{
+ {
+ // Temp scope for lock. We can't hold the lock during
+ // a QI, as this may itself need the lock.
+ // Make sure our object isn't dieing right now on another thread.
+ CEnterLeaveXPCOMFramework _celf;
+ if (m_pBase == NULL)
+ return NS_ERROR_NULL_POINTER;
+ m_pBase->AddRef(); // Can't die while we have a ref.
+ } // end of lock scope - lock unlocked.
+ nsresult nr = m_pBase->QueryInterface(iid, ret);
+ m_pBase->Release();
+ return nr;
+}
diff --git a/src/libs/xpcom18a4/python/src/PyIClassInfo.cpp b/src/libs/xpcom18a4/python/src/PyIClassInfo.cpp
new file mode 100644
index 00000000..6d0f499d
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIClassInfo.cpp
@@ -0,0 +1,181 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp. Portions created by ActiveState Tool Corp. are Copyright (C) 2001 ActiveState Tool Corp. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2001 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2001, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include "nsIClassInfo.h"
+
+static nsIClassInfo *_GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsIClassInfo);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIClassInfo *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *PyGetInterfaces(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ nsIClassInfo *pI = _GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID** iidArray = nsnull;
+ PRUint32 iidCount = 0;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetInterfaces(&iidCount, &iidArray);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ PyObject *ret = PyTuple_New(iidCount);
+ if (ret==NULL)
+ return NULL;
+ for (PRUint32 i=0;i<iidCount;i++)
+ PyTuple_SET_ITEM( ret, i, Py_nsIID::PyObjectFromIID(*(iidArray[i])) );
+ return ret;
+}
+
+static PyObject *PyGetHelperForLanguage(PyObject *self, PyObject *args)
+{
+ PRUint32 language = nsIProgrammingLanguage::PYTHON;
+ if (!PyArg_ParseTuple(args, "|i", &language))
+ return NULL;
+ nsIClassInfo *pI = _GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsresult r;
+ nsCOMPtr<nsISupports> pi;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetHelperForLanguage(language, getter_AddRefs(pi));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsISupports));
+}
+
+static PyObject *MakeStringOrNone(char *v)
+{
+ if (v)
+#if PY_MAJOR_VERSION <= 2
+ return PyString_FromString(v);
+#else
+ return PyUnicode_FromString(v);
+#endif
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#define GETATTR_CHECK_RESULT(nr) if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr)
+
+PyObject *
+Py_nsIClassInfo::getattr(const char *name)
+{
+ nsIClassInfo *pI = _GetI(this);
+ if (pI==NULL)
+ return NULL;
+
+ nsresult nr;
+ PyObject *ret = NULL;
+ if (strcmp(name, "contractID")==0) {
+ char *str_ret = NULL;
+ Py_BEGIN_ALLOW_THREADS;
+ nr = pI->GetContractID(&str_ret);
+ Py_END_ALLOW_THREADS;
+ GETATTR_CHECK_RESULT(nr);
+ ret = MakeStringOrNone(str_ret);
+ nsMemory::Free(str_ret);
+ } else if (strcmp(name, "classDescription")==0) {
+ char *str_ret = NULL;
+ Py_BEGIN_ALLOW_THREADS;
+ nr = pI->GetClassDescription(&str_ret);
+ Py_END_ALLOW_THREADS;
+ GETATTR_CHECK_RESULT(nr);
+ ret = MakeStringOrNone(str_ret);
+ nsMemory::Free(str_ret);
+ } else if (strcmp(name, "classID")==0) {
+ nsIID *iid = NULL;
+ Py_BEGIN_ALLOW_THREADS;
+ nr = pI->GetClassID(&iid);
+ Py_END_ALLOW_THREADS;
+ GETATTR_CHECK_RESULT(nr);
+ ret = Py_nsIID::PyObjectFromIID(*iid);
+ nsMemory::Free(iid);
+ } else if (strcmp(name, "implementationLanguage")==0) {
+ PRUint32 i;
+ Py_BEGIN_ALLOW_THREADS;
+ nr = pI->GetImplementationLanguage(&i);
+ Py_END_ALLOW_THREADS;
+ GETATTR_CHECK_RESULT(nr);
+ ret = PyInt_FromLong(i);
+ } else {
+ ret = Py_nsISupports::getattr(name);
+ }
+ return ret;
+}
+
+int
+Py_nsIClassInfo::setattr(const char *name, PyObject *v)
+{
+ return Py_nsISupports::setattr(name, v);
+
+}
+
+struct PyMethodDef
+PyMethods_IClassInfo[] =
+{
+ { "getInterfaces", PyGetInterfaces, 1},
+ { "GetInterfaces", PyGetInterfaces, 1},
+ { "getHelperForLanguage", PyGetHelperForLanguage, 1},
+ { "GetHelperForLanguage", PyGetHelperForLanguage, 1},
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyIComponentManager.cpp b/src/libs/xpcom18a4/python/src/PyIComponentManager.cpp
new file mode 100644
index 00000000..c3b89112
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIComponentManager.cpp
@@ -0,0 +1,138 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+
+static nsIComponentManager *GetI(PyObject *self) {
+ static const nsIID iid = NS_GET_IID(nsIComponentManager);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return NS_STATIC_CAST(nsIComponentManager*, Py_nsISupports::GetI(self));
+}
+
+static PyObject *PyCreateInstanceByContractID(PyObject *self, PyObject *args)
+{
+ // second arg to CreateInstanceByContractID is a "delegate" - we
+ // aren't sure of the semantics of this yet and it seems rarely used,
+ // so we just punt for now.
+ char *pid, *notyet = NULL;
+ PyObject *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "s|zO", &pid, &notyet, &obIID))
+ return NULL;
+ if (notyet != NULL) {
+ PyErr_SetString(PyExc_ValueError, "2nd arg must be none");
+ return NULL;
+ }
+ nsIComponentManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID iid;
+ if (obIID==NULL)
+ iid = NS_GET_IID(nsISupports);
+ else
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+
+ nsCOMPtr<nsISupports> pis;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->CreateInstanceByContractID(pid, NULL, iid, getter_AddRefs(pis));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ /* Return a type based on the IID (with no extra ref) */
+ return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE);
+}
+
+static PyObject *PyCreateInstance(PyObject *self, PyObject *args)
+{
+ char *notyet = NULL;
+ PyObject *obClassID = NULL, *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "O|zO", &obClassID, &notyet, &obIID))
+ return NULL;
+ if (notyet != NULL) {
+ PyErr_SetString(PyExc_ValueError, "2nd arg must be none");
+ return NULL;
+ }
+ nsIComponentManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID classID;
+ if (!Py_nsIID::IIDFromPyObject(obClassID, &classID))
+ return NULL;
+ nsIID iid;
+ if (obIID==NULL)
+ iid = NS_GET_IID(nsISupports);
+ else
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+
+ nsCOMPtr<nsISupports> pis;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->CreateInstance(classID, NULL, iid, getter_AddRefs(pis));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ /* Return a type based on the IID (with no extra ref) */
+ return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE);
+}
+
+struct PyMethodDef
+PyMethods_IComponentManager[] =
+{
+ { "createInstanceByContractID", PyCreateInstanceByContractID, 1},
+ { "createInstance", PyCreateInstance, 1},
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp b/src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp
new file mode 100644
index 00000000..7d07d421
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp
@@ -0,0 +1,203 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+
+static nsIComponentManagerObsolete *GetI(PyObject *self) {
+ static const nsIID iid = NS_GET_IID(nsIComponentManagerObsolete);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIComponentManagerObsolete *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *PyCreateInstanceByContractID(PyObject *self, PyObject *args)
+{
+ char *pid, *notyet = NULL;
+ PyObject *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "s|zO", &pid, &notyet, &obIID))
+ return NULL;
+ if (notyet != NULL) {
+ PyErr_SetString(PyExc_ValueError, "2nd arg must be none");
+ return NULL;
+ }
+ nsIComponentManagerObsolete *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID iid;
+ if (obIID==NULL)
+ iid = NS_GET_IID(nsISupports);
+ else
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+
+ nsISupports *pis;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->CreateInstanceByContractID(pid, NULL, iid, (void **)&pis);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ /* Return a type based on the IID (with no extra ref) */
+ return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE, PR_FALSE);
+}
+
+static PyObject *PyContractIDToClassID(PyObject *self, PyObject *args)
+{
+ char *pid;
+ if (!PyArg_ParseTuple(args, "s", &pid))
+ return NULL;
+ nsIComponentManagerObsolete *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID iid;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->ContractIDToClassID(pid, &iid);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ return Py_nsIID::PyObjectFromIID(iid);
+}
+
+static PyObject *PyCLSIDToContractID(PyObject *self, PyObject *args)
+{
+ PyObject *obIID;
+ if (!PyArg_ParseTuple(args, "O", &obIID))
+ return NULL;
+
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ char *ret_pid = nsnull;
+ char *ret_class = nsnull;
+ nsIComponentManagerObsolete *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->CLSIDToContractID(iid, &ret_class, &ret_pid);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+#if PY_MAJOR_VERSION <= 2
+ PyObject *ob_pid = PyString_FromString(ret_pid);
+ PyObject *ob_class = PyString_FromString(ret_class);
+#else
+ PyObject *ob_pid = PyUnicode_FromString(ret_pid);
+ PyObject *ob_class = PyUnicode_FromString(ret_class);
+#endif
+ PyObject *ret = Py_BuildValue("OO", ob_pid, ob_class);
+ nsMemory::Free(ret_pid);
+ nsMemory::Free(ret_class);
+ Py_XDECREF(ob_pid);
+ Py_XDECREF(ob_class);
+ return ret;
+}
+
+static PyObject *PyEnumerateCLSIDs(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ nsIComponentManagerObsolete *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIEnumerator *pRet;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->EnumerateCLSIDs(&pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE);
+}
+
+static PyObject *PyEnumerateContractIDs(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ nsIComponentManagerObsolete *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIEnumerator *pRet;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->EnumerateContractIDs(&pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE);
+}
+
+struct PyMethodDef
+PyMethods_IComponentManagerObsolete[] =
+{
+ { "CreateInstanceByContractID", PyCreateInstanceByContractID, 1},
+ { "createInstanceByContractID", PyCreateInstanceByContractID, 1},
+ { "EnumerateCLSIDs", PyEnumerateCLSIDs, 1},
+ { "enumerateCLSIDs", PyEnumerateCLSIDs, 1},
+ { "EnumerateContractIDs", PyEnumerateContractIDs, 1},
+ { "enumerateContractIDs", PyEnumerateContractIDs, 1},
+ { "ContractIDToClassID", PyContractIDToClassID, 1},
+ { "contractIDToClassID", PyContractIDToClassID, 1},
+ { "CLSIDToContractID", PyCLSIDToContractID, 1},
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyIEnumerator.cpp b/src/libs/xpcom18a4/python/src/PyIEnumerator.cpp
new file mode 100644
index 00000000..b196d956
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIEnumerator.cpp
@@ -0,0 +1,235 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIEnumerator.h>
+
+static nsIEnumerator *GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsIEnumerator);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIEnumerator *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *PyFirst(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":First"))
+ return NULL;
+
+ nsIEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->First();
+ Py_END_ALLOW_THREADS;
+ return PyInt_FromLong(r);
+}
+
+static PyObject *PyNext(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":Next"))
+ return NULL;
+
+ nsIEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->Next();
+ Py_END_ALLOW_THREADS;
+ return PyInt_FromLong(r);
+}
+
+static PyObject *PyCurrentItem(PyObject *self, PyObject *args)
+{
+ PyObject *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "|O:CurrentItem", &obIID))
+ return NULL;
+
+ nsIID iid(NS_GET_IID(nsISupports));
+ if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ nsIEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsISupports *pRet = nsnull;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->CurrentItem(&pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ if (obIID) {
+ nsISupports *temp;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pRet->QueryInterface(iid, (void **)&temp);
+ pRet->Release();
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) ) {
+ return PyXPCOM_BuildPyException(r);
+ }
+ pRet = temp;
+ }
+ PyObject *ret = Py_nsISupports::PyObjectFromInterface(pRet, iid);
+ NS_IF_RELEASE(pRet);
+ return ret;
+}
+
+// A method added for Python performance if you really need
+// it. Allows you to fetch a block of objects in one
+// hit, allowing the loop to remain implemented in C.
+static PyObject *PyFetchBlock(PyObject *self, PyObject *args)
+{
+ PyObject *obIID = NULL;
+ int n_wanted;
+ int n_fetched = 0;
+ if (!PyArg_ParseTuple(args, "i|O:FetchBlock", &n_wanted, &obIID))
+ return NULL;
+
+ nsIID iid(NS_GET_IID(nsISupports));
+ if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ nsIEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ // We want to fetch with the thread-lock released,
+ // but this means we can not append to the PyList
+ nsISupports **fetched = new nsISupports*[n_wanted];
+ if (fetched==nsnull) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ memset(fetched, 0, sizeof(nsISupports *) * n_wanted);
+ nsresult r = NS_OK;
+ Py_BEGIN_ALLOW_THREADS;
+ for (;n_fetched<n_wanted;) {
+ nsISupports *pNew;
+ r = pI->CurrentItem(&pNew);
+ if (NS_FAILED(r)) {
+ r = 0; // Normal enum end
+ break;
+ }
+ if (obIID) {
+ nsISupports *temp;
+ r = pNew->QueryInterface(iid, (void **)&temp);
+ pNew->Release();
+ if ( NS_FAILED(r) ) {
+ break;
+ }
+ pNew = temp;
+ }
+ fetched[n_fetched] = pNew;
+ n_fetched++; // must increment before breaking out.
+ if (NS_FAILED(pI->Next()))
+ break; // not an error condition.
+ }
+ Py_END_ALLOW_THREADS;
+ PyObject *ret;
+ if (NS_SUCCEEDED(r)) {
+ ret = PyList_New(n_fetched);
+ if (ret)
+ for (int i=0;i<n_fetched;i++) {
+ PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid);
+ NS_IF_RELEASE(fetched[i]);
+ PyList_SET_ITEM(ret, i, new_ob);
+ }
+ } else
+ ret = PyXPCOM_BuildPyException(r);
+
+ if ( ret == NULL ) {
+ // Free the objects we consumed.
+ for (int i=0;i<n_fetched;i++)
+ fetched[i]->Release();
+
+ }
+ delete [] fetched;
+ return ret;
+}
+
+static PyObject *PyIsDone(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":IsDone"))
+ return NULL;
+
+ nsIEnumerator *pI = GetI(self);
+ nsresult r;
+ if (pI==NULL)
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->IsDone();
+ Py_END_ALLOW_THREADS;
+ if (NS_FAILED(r))
+ return PyXPCOM_BuildPyException(r);
+ PyObject *ret = r==NS_OK ? Py_True : Py_False;
+ Py_INCREF(ret);
+ return ret;
+}
+
+struct PyMethodDef
+PyMethods_IEnumerator[] =
+{
+ { "First", PyFirst, 1},
+ { "first", PyFirst, 1},
+ { "Next", PyNext, 1},
+ { "next", PyNext, 1},
+ { "CurrentItem", PyCurrentItem, 1},
+ { "currentItem", PyCurrentItem, 1},
+ { "IsDone", PyIsDone, 1},
+ { "isDone", PyIsDone, 1},
+ { "FetchBlock", PyFetchBlock, 1},
+ { "fetchBlock", PyFetchBlock, 1},
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyIID.cpp b/src/libs/xpcom18a4/python/src/PyIID.cpp
new file mode 100644
index 00000000..f24ae20e
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIID.cpp
@@ -0,0 +1,410 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Py_nsIID.cpp -- IID type for Python/XPCOM
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+//
+// @doc
+
+#include "PyXPCOM_std.h"
+#include <nsIInterfaceInfoManager.h>
+
+nsIID Py_nsIID_NULL = {0,0,0,{0,0,0,0,0,0,0,0}};
+
+// @pymethod <o Py_nsIID>|xpcom|IID|Creates a new IID object
+PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args)
+{
+ PyObject *obIID;
+ PyObject *obBuf;
+ if ( PyArg_ParseTuple(args, "O", &obBuf)) {
+#if PY_MAJOR_VERSION <= 2
+ if (PyBuffer_Check(obBuf)) {
+ PyBufferProcs *pb = NULL;
+ pb = obBuf->ob_type->tp_as_buffer;
+ void *buf = NULL;
+ int size = (*pb->bf_getreadbuffer)(obBuf, 0, &buf);
+#else
+ if (PyObject_CheckBuffer(obBuf)) {
+# ifndef Py_LIMITED_API
+ Py_buffer view;
+ if (PyObject_GetBuffer(obBuf, &view, PyBUF_CONTIG_RO) != 0) {
+ PyErr_Format(PyExc_ValueError, "Could not get contiguous buffer from object");
+ return NULL;
+ }
+ Py_ssize_t size = view.len;
+ const void *buf = view.buf;
+# else /* Py_LIMITED_API - the buffer API is non-existant, from what I can tell */
+ const void *buf = NULL;
+ Py_ssize_t size = 0;
+ if (PyObject_AsReadBuffer(obBuf, &buf, &size) != 0) {
+ PyErr_Format(PyExc_ValueError, "Could not get read-only buffer from object");
+ return NULL;
+ }
+# endif /* Py_LIMITED_API */
+#endif
+ if (size != sizeof(nsIID) || buf==NULL) {
+#if PY_MAJOR_VERSION >= 3 && !defined(Py_LIMITED_API)
+ PyBuffer_Release(&view);
+#endif
+#ifdef VBOX
+ PyErr_Format(PyExc_ValueError, "A buffer object to be converted to an IID must be exactly %d bytes long", (int)sizeof(nsIID));
+#else
+ PyErr_Format(PyExc_ValueError, "A buffer object to be converted to an IID must be exactly %d bytes long", sizeof(nsIID));
+#endif
+ return NULL;
+ }
+ nsIID iid;
+ unsigned char const *ptr = (unsigned char const *)buf;
+ iid.m0 = XPT_SWAB32(*((PRUint32 *)ptr));
+ ptr = ((unsigned char const *)buf) + offsetof(nsIID, m1);
+ iid.m1 = XPT_SWAB16(*((PRUint16 *)ptr));
+ ptr = ((unsigned char const *)buf) + offsetof(nsIID, m2);
+ iid.m2 = XPT_SWAB16(*((PRUint16 *)ptr));
+ ptr = ((unsigned char const *)buf) + offsetof(nsIID, m3);
+ for (int i=0;i<8;i++) {
+ iid.m3[i] = *((PRUint8 const *)ptr);
+ ptr += sizeof(PRUint8);
+ }
+#if PY_MAJOR_VERSION >= 3 && !defined(Py_LIMITED_API)
+ PyBuffer_Release(&view);
+#endif
+ return new Py_nsIID(iid);
+ }
+ }
+ PyErr_Clear();
+ // @pyparm string/Unicode|iidString||A string representation of an IID, or a ContractID.
+ if ( !PyArg_ParseTuple(args, "O", &obIID) )
+ return NULL;
+
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ return new Py_nsIID(iid);
+}
+
+/*static*/ PRBool
+Py_nsIID::IIDFromPyObject(PyObject *ob, nsIID *pRet) {
+ PRBool ok = PR_TRUE;
+ nsIID iid;
+ if (ob==NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "The IID object is invalid!");
+ return PR_FALSE;
+ }
+#if PY_MAJOR_VERSION <= 2
+ if (PyString_Check(ob)) {
+ ok = iid.Parse(PyString_AsString(ob));
+#else
+ if (PyUnicode_Check(ob)) {
+ ok = iid.Parse(PyUnicode_AsUTF8(ob));
+#endif
+ if (!ok) {
+ PyXPCOM_BuildPyException(NS_ERROR_ILLEGAL_VALUE);
+ return PR_FALSE;
+ }
+#ifndef Py_LIMITED_API
+ } else if (ob->ob_type == &type) {
+#else
+ } else if (ob->ob_type == Py_nsIID::GetTypeObject()) {
+#endif
+ iid = ((Py_nsIID *)ob)->m_iid;
+ } else if (PyObject_HasAttrString(ob, "__class__")) {
+ // Get the _iidobj_ attribute
+ PyObject *use_ob = PyObject_GetAttrString(ob, "_iidobj_");
+ if (use_ob==NULL) {
+ PyErr_SetString(PyExc_TypeError, "Only instances with _iidobj_ attributes can be used as IID objects");
+ return PR_FALSE;
+ }
+#ifndef Py_LIMITED_API
+ if (use_ob->ob_type != &type) {
+#else
+ if (use_ob->ob_type != Py_nsIID::GetTypeObject()) {
+#endif
+ Py_DECREF(use_ob);
+ PyErr_SetString(PyExc_TypeError, "instance _iidobj_ attributes must be raw IID object");
+ return PR_FALSE;
+ }
+ iid = ((Py_nsIID *)use_ob)->m_iid;
+ Py_DECREF(use_ob);
+ } else {
+ PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an IID", PyXPCOM_ObTypeName(ob));
+ ok = PR_FALSE;
+ }
+ if (ok) *pRet = iid;
+ return ok;
+}
+
+
+// @object Py_nsIID|A Python object, representing an IID/CLSID.
+// <nl>All pythoncom functions that return a CLSID/IID will return one of these
+// objects. However, in almost all cases, functions that expect a CLSID/IID
+// as a param will accept either a string object, or a native Py_nsIID object.
+#ifndef Py_LIMITED_API
+PyTypeObject Py_nsIID::type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "IID",
+ sizeof(Py_nsIID),
+ 0,
+ PyTypeMethod_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ PyTypeMethod_getattr, /* tp_getattr */
+ 0, /* tp_setattr */
+#if PY_MAJOR_VERSION <= 2
+ PyTypeMethod_compare, /* tp_compare */
+#else
+ 0, /* reserved */
+#endif
+ PyTypeMethod_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ PyTypeMethod_hash, /* tp_hash */
+ 0, /* tp_call */
+ PyTypeMethod_str, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ 0, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ PyTypeMethod_richcompare, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+};
+#else /* Py_LIMITED_API */
+NS_EXPORT_STATIC_MEMBER_(PyTypeObject *) Py_nsIID::s_pType = NULL;
+
+PyTypeObject *Py_nsIID::GetTypeObject(void)
+{
+ PyTypeObject *pTypeObj = Py_nsIID::s_pType;
+ if (pTypeObj)
+ return pTypeObj;
+
+ PyType_Slot aTypeSlots[] = {
+ { Py_tp_base, &PyType_Type },
+ { Py_tp_dealloc, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_dealloc },
+ { Py_tp_getattr, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_getattr },
+ { Py_tp_repr, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_repr },
+ { Py_tp_hash, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_hash },
+ { Py_tp_str, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_str },
+ { Py_tp_richcompare, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_richcompare },
+ { 0, NULL } /* terminator */
+ };
+ PyType_Spec TypeSpec = {
+ /* .name: */ "IID",
+ /* .basicsize: */ sizeof(Py_nsIID),
+ /* .itemsize: */ 0,
+ /* .flags: */ 0,
+ /* .slots: */ aTypeSlots,
+ };
+
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */
+
+ pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec);
+ assert(pTypeObj);
+
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+ Py_nsIID::s_pType = pTypeObj;
+ return pTypeObj;
+}
+#endif /* Py_LIMITED_API */
+
+Py_nsIID::Py_nsIID(const nsIID &riid)
+{
+#ifndef Py_LIMITED_API
+ ob_type = &type;
+#else
+ ob_type = GetTypeObject();
+#endif
+#if 1 /* VBox: Must use for 3.9+, includes _Py_NewReferences. Works for all older versions too. @bugref{10079} */
+ PyObject_Init(this, ob_type);
+#else
+ _Py_NewReference(this);
+#endif
+
+ m_iid = riid;
+}
+
+/*static*/PyObject *
+Py_nsIID::PyTypeMethod_getattr(PyObject *self, char *name)
+{
+ Py_nsIID *me = (Py_nsIID *)self;
+ if (strcmp(name, "name")==0) {
+ char *iid_repr = nsnull;
+ nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
+ NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+ if (iim!=nsnull)
+ iim->GetNameForIID(&me->m_iid, &iid_repr);
+ if (iid_repr==nsnull)
+ iid_repr = me->m_iid.ToString();
+ PyObject *ret;
+ if (iid_repr != nsnull) {
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromString(iid_repr);
+#else
+ ret = PyUnicode_FromString(iid_repr);
+#endif
+ nsMemory::Free(iid_repr);
+ } else
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromString("<cant get IID info!>");
+#else
+ ret = PyUnicode_FromString("<cant get IID info!>");
+#endif
+ return ret;
+ }
+ return PyErr_Format(PyExc_AttributeError, "IID objects have no attribute '%s'", name);
+}
+
+#if PY_MAJOR_VERSION <= 2
+/* static */ int
+Py_nsIID::PyTypeMethod_compare(PyObject *self, PyObject *other)
+{
+ Py_nsIID *s_iid = (Py_nsIID *)self;
+ Py_nsIID *o_iid = (Py_nsIID *)other;
+ int rc = memcmp(&s_iid->m_iid, &o_iid->m_iid, sizeof(s_iid->m_iid));
+ return rc == 0 ? 0 : (rc < 0 ? -1 : 1);
+}
+#endif
+
+/* static */ PyObject *
+Py_nsIID::PyTypeMethod_richcompare(PyObject *self, PyObject *other, int op)
+{
+ PyObject *result = NULL;
+ Py_nsIID *s_iid = (Py_nsIID *)self;
+ Py_nsIID *o_iid = (Py_nsIID *)other;
+ int rc = memcmp(&s_iid->m_iid, &o_iid->m_iid, sizeof(s_iid->m_iid));
+ switch (op)
+ {
+ case Py_LT:
+ result = rc < 0 ? Py_True : Py_False;
+ break;
+ case Py_LE:
+ result = rc <= 0 ? Py_True : Py_False;
+ break;
+ case Py_EQ:
+ result = rc == 0 ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ result = rc != 0 ? Py_True : Py_False;
+ break;
+ case Py_GT:
+ result = rc > 0 ? Py_True : Py_False;
+ break;
+ case Py_GE:
+ result = rc >= 0 ? Py_True : Py_False;
+ break;
+ }
+ Py_XINCREF(result);
+ return result;
+}
+
+/* static */ PyObject *
+Py_nsIID::PyTypeMethod_repr(PyObject *self)
+{
+ Py_nsIID *s_iid = (Py_nsIID *)self;
+ char buf[256];
+ char *sziid = s_iid->m_iid.ToString();
+#ifdef VBOX
+ snprintf(buf, sizeof(buf), "_xpcom.ID('%s')", sziid);
+#else
+ sprintf(buf, "_xpcom.IID('%s')", sziid);
+#endif
+ nsMemory::Free(sziid);
+#if PY_MAJOR_VERSION <= 2
+ return PyString_FromString(buf);
+#else
+ return PyUnicode_FromString(buf);
+#endif
+}
+
+/* static */ PyObject *
+Py_nsIID::PyTypeMethod_str(PyObject *self)
+{
+ Py_nsIID *s_iid = (Py_nsIID *)self;
+ char *sziid = s_iid->m_iid.ToString();
+#if PY_MAJOR_VERSION <= 2
+ PyObject *ret = PyString_FromString(sziid);
+#else
+ PyObject *ret = PyUnicode_FromString(sziid);
+#endif
+ nsMemory::Free(sziid);
+ return ret;
+}
+
+#if PY_VERSION_HEX >= 0x03020000
+/* static */Py_hash_t
+Py_nsIID::PyTypeMethod_hash(PyObject *self)
+#else
+/* static */long
+Py_nsIID::PyTypeMethod_hash(PyObject *self)
+#endif
+{
+ const nsIID &iid = ((Py_nsIID *)self)->m_iid;
+
+#if PY_VERSION_HEX >= 0x03020000
+ Py_hash_t ret = iid.m0 + iid.m1 + iid.m2;
+#else
+ long ret = iid.m0 + iid.m1 + iid.m2;
+#endif
+ for (int i=0;i<7;i++)
+ ret += iid.m3[i];
+ if ( ret == -1 )
+ return -2;
+ return ret;
+}
+
+/*static*/ void
+Py_nsIID::PyTypeMethod_dealloc(PyObject *ob)
+{
+ delete (Py_nsIID *)ob;
+}
diff --git a/src/libs/xpcom18a4/python/src/PyIInputStream.cpp b/src/libs/xpcom18a4/python/src/PyIInputStream.cpp
new file mode 100644
index 00000000..b290a3e4
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIInputStream.cpp
@@ -0,0 +1,190 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written September 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include "nsIInputStream.h"
+
+// Prevents us needing to use an nsIScriptableInputStream
+// (and even that can't read binary data!!!)
+
+static nsIInputStream *GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsIInputStream);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIInputStream *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *DoPyRead_Buffer(nsIInputStream *pI, PyObject *obBuffer, PRUint32 n)
+{
+ PRUint32 nread;
+ void *buf;
+#ifndef VBOX /* unsafe cast on 64-bit hosts. */
+ PRUint32 buf_len;
+ if (PyObject_AsWriteBuffer(obBuffer, &buf, (Py_ssize_t *)&buf_len) != 0) {
+#else /* VBOX */
+# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
+ Py_ssize_t buf_len;
+# else
+ int buf_len;
+# endif /* VBOX */
+ if (PyObject_AsWriteBuffer(obBuffer, &buf, &buf_len) != 0) {
+#endif
+ PyErr_Clear();
+ PyErr_SetString(PyExc_TypeError, "The buffer object does not have a write buffer!");
+ return NULL;
+ }
+ if (n==(PRUint32)-1) {
+ n = buf_len;
+ } else {
+ if (n > buf_len) {
+ NS_WARNING("Warning: PyIInputStream::read() was passed an integer size greater than the size of the passed buffer! Buffer size used.\n");
+ n = buf_len;
+ }
+ }
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->Read((char *)buf, n, &nread);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyInt_FromLong(nread);
+}
+
+static PyObject *DoPyRead_Size(nsIInputStream *pI, PRUint32 n)
+{
+ if (n==(PRUint32)-1) {
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->Available(&n);
+ Py_END_ALLOW_THREADS;
+ if (NS_FAILED(r))
+ return PyXPCOM_BuildPyException(r);
+ }
+ if (n==0) { // mozilla will assert if we alloc zero bytes.
+#if PY_MAJOR_VERSION <= 2
+ return PyBuffer_New(0);
+#else
+ return PyBytes_FromString("");
+#endif
+ }
+ char *buf = (char *)nsMemory::Alloc(n);
+ if (buf==NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ nsresult r;
+ PRUint32 nread;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->Read(buf, n, &nread);
+ Py_END_ALLOW_THREADS;
+ PyObject *rc = NULL;
+ if ( NS_SUCCEEDED(r) ) {
+#if PY_MAJOR_VERSION <= 2
+ rc = PyBuffer_New(nread);
+ if (rc != NULL) {
+ void *ob_buf;
+#ifndef VBOX /* unsafe cast on 64-bit hosts. */
+ PRUint32 buf_len;
+ if (PyObject_AsWriteBuffer(rc, &ob_buf, (Py_ssize_t *)&buf_len) != 0) {
+#else /* VBOX */
+# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
+ Py_ssize_t buf_len;
+# else
+ int buf_len;
+# endif /* VBOX */
+ if (PyObject_AsWriteBuffer(rc, &ob_buf, &buf_len) != 0) {
+#endif
+ // should never fail - we just created it!
+ return NULL;
+ }
+ if (buf_len != nread) {
+ PyErr_SetString(PyExc_RuntimeError, "New buffer isnt the size we create it!");
+ return NULL;
+ }
+ memcpy(ob_buf, buf, nread);
+ }
+#else
+ rc = PyBytes_FromStringAndSize(buf, nread);
+#endif
+ } else
+ PyXPCOM_BuildPyException(r);
+ nsMemory::Free(buf);
+ return rc;
+}
+
+static PyObject *PyRead(PyObject *self, PyObject *args)
+{
+ PyObject *obBuffer = NULL;
+ PRUint32 n = (PRUint32)-1;
+
+ nsIInputStream *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+ if (PyArg_ParseTuple(args, "|i", (int *)&n))
+ // This worked - no args, or just an int.
+ return DoPyRead_Size(pI, n);
+ // try our other supported arg format.
+ PyErr_Clear();
+ if (!PyArg_ParseTuple(args, "O|i", &obBuffer, (int *)&n)) {
+ PyErr_Clear();
+ PyErr_SetString(PyExc_TypeError, "'read()' must be called as (buffer_ob, int_size=-1) or (int_size=-1)");
+ return NULL;
+ }
+ return DoPyRead_Buffer(pI, obBuffer, n);
+}
+
+
+struct PyMethodDef
+PyMethods_IInputStream[] =
+{
+ { "read", PyRead, 1},
+ // The rest are handled as normal
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp b/src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp
new file mode 100644
index 00000000..7e1a9466
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp
@@ -0,0 +1,431 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+
+
+static nsIInterfaceInfo *GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsIInterfaceInfo);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIInterfaceInfo *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *PyGetName(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":GetName"))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ char *name;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetName(&name);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+#if PY_MAJOR_VERSION <= 2
+ PyObject *ret = PyString_FromString(name);
+#else
+ PyObject *ret = PyUnicode_FromString(name);
+#endif
+ nsMemory::Free(name);
+ return ret;
+}
+
+static PyObject *PyGetIID(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":GetIID"))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID *iid_ret;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetInterfaceIID(&iid_ret);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret);
+ nsMemory::Free(iid_ret);
+ return ret;
+}
+
+static PyObject *PyIsScriptable(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":IsScriptable"))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ PRBool b_ret;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->IsScriptable(&b_ret);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyInt_FromLong(b_ret);
+}
+
+static PyObject *PyGetParent(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":GetParent"))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsCOMPtr<nsIInterfaceInfo> pRet;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetParent(getter_AddRefs(pRet));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
+}
+
+static PyObject *PyGetMethodCount(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":GetMethodCount"))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ PRUint16 ret;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetMethodCount(&ret);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyInt_FromLong(ret);
+}
+
+
+static PyObject *PyGetConstantCount(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":GetConstantCount"))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ PRUint16 ret;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetConstantCount(&ret);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyInt_FromLong(ret);
+}
+
+static PyObject *PyGetMethodInfo(PyObject *self, PyObject *args)
+{
+ PRUint16 index;
+ if (!PyArg_ParseTuple(args, "h:GetMethodInfo", &index))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ PRUint16 nmethods;
+ pI->GetMethodCount(&nmethods);
+ if (index>=nmethods) {
+ PyErr_SetString(PyExc_ValueError, "The method index is out of range");
+ return NULL;
+ }
+
+ const nsXPTMethodInfo *pRet;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetMethodInfo(index, &pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyObject_FromXPTMethodDescriptor(pRet);
+}
+
+static PyObject *PyGetMethodInfoForName(PyObject *self, PyObject *args)
+{
+ char *name;
+ if (!PyArg_ParseTuple(args, "s:GetMethodInfoForName", &name))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ const nsXPTMethodInfo *pRet;
+ PRUint16 index;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetMethodInfoForName(name, &index, &pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ PyObject *ret_i = PyObject_FromXPTMethodDescriptor(pRet);
+ if (ret_i==NULL)
+ return NULL;
+ PyObject *real_ret = Py_BuildValue("iO", (int)index, ret_i);
+ Py_DECREF(ret_i);
+ return real_ret;
+}
+
+
+static PyObject *PyGetConstant(PyObject *self, PyObject *args)
+{
+ PRUint16 index;
+ if (!PyArg_ParseTuple(args, "h:GetConstant", &index))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ const nsXPTConstant *pRet;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetConstant(index, &pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyObject_FromXPTConstant(pRet);
+}
+
+static PRBool __GetMethodInfoHelper(nsIInterfaceInfo *pii, int mi, int pi, const nsXPTMethodInfo **ppmi)
+{
+ PRUint16 nmethods=0;
+ pii->GetMethodCount(&nmethods);
+ if (mi<0 || mi>=nmethods) {
+ PyErr_SetString(PyExc_ValueError, "The method index is out of range");
+ return PR_FALSE;
+ }
+ const nsXPTMethodInfo *pmi;
+ nsresult r = pii->GetMethodInfo(mi, &pmi);
+ if ( NS_FAILED(r) ) {
+ PyXPCOM_BuildPyException(r);
+ return PR_FALSE;
+ }
+
+ int nparams=0;
+ nparams = pmi->GetParamCount();
+ if (pi<0 || pi>=nparams) {
+ PyErr_SetString(PyExc_ValueError, "The param index is out of range");
+ return PR_FALSE;
+ }
+ *ppmi = pmi;
+ return PR_TRUE;
+}
+
+static PyObject *PyGetInfoForParam(PyObject *self, PyObject *args)
+{
+ nsIInterfaceInfo *pii = GetI(self);
+ if (pii==NULL)
+ return NULL;
+ PRUint16 mi, pi;
+ if (!PyArg_ParseTuple(args, "hh:GetInfoForParam", &mi, &pi))
+ return NULL;
+ const nsXPTMethodInfo *pmi;
+ if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
+ return NULL;
+ const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
+ nsCOMPtr<nsIInterfaceInfo> pnewii;
+ nsresult n = pii->GetInfoForParam(mi, &param_info, getter_AddRefs(pnewii));
+ if (NS_FAILED(n))
+ return PyXPCOM_BuildPyException(n);
+ return Py_nsISupports::PyObjectFromInterface(pnewii, NS_GET_IID(nsIInterfaceInfo));
+}
+
+static PyObject *PyGetIIDForParam(PyObject *self, PyObject *args)
+{
+ nsIInterfaceInfo *pii = GetI(self);
+ if (pii==NULL)
+ return NULL;
+ PRUint16 mi, pi;
+ if (!PyArg_ParseTuple(args, "hh:GetIIDForParam", &mi, &pi))
+ return NULL;
+ const nsXPTMethodInfo *pmi;
+ if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
+ return NULL;
+ const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
+ nsIID *piid;
+ nsresult n = pii->GetIIDForParam(mi, &param_info, &piid);
+ if (NS_FAILED(n) || piid==nsnull)
+ return PyXPCOM_BuildPyException(n);
+ PyObject *rc = Py_nsIID::PyObjectFromIID(*piid);
+ nsMemory::Free((void*)piid);
+ return rc;
+}
+
+static PyObject *PyGetTypeForParam(PyObject *self, PyObject *args)
+{
+ nsIInterfaceInfo *pii = GetI(self);
+ if (pii==NULL)
+ return NULL;
+ PRUint16 mi, pi, dim;
+ if (!PyArg_ParseTuple(args, "hhh:GetTypeForParam", &mi, &pi, &dim))
+ return NULL;
+ const nsXPTMethodInfo *pmi;
+ if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
+ return NULL;
+ nsXPTType datumType;
+ const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
+ nsresult n = pii->GetTypeForParam(mi, &param_info, dim, &datumType);
+ if (NS_FAILED(n))
+ return PyXPCOM_BuildPyException(n);
+ return PyObject_FromXPTType(&datumType);
+}
+
+static PyObject *PyGetSizeIsArgNumberForParam(PyObject *self, PyObject *args)
+{
+ nsIInterfaceInfo *pii = GetI(self);
+ if (pii==NULL)
+ return NULL;
+ PRUint16 mi, pi, dim;
+ if (!PyArg_ParseTuple(args, "hhh:GetSizeIsArgNumberForParam", &mi, &pi, &dim))
+ return NULL;
+ const nsXPTMethodInfo *pmi;
+ if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
+ return NULL;
+ PRUint8 ret;
+ const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
+ nsresult n = pii->GetSizeIsArgNumberForParam(mi, &param_info, dim, &ret);
+ if (NS_FAILED(n))
+ return PyXPCOM_BuildPyException(n);
+ return PyInt_FromLong(ret);
+}
+
+static PyObject *PyGetLengthIsArgNumberForParam(PyObject *self, PyObject *args)
+{
+ nsIInterfaceInfo *pii = GetI(self);
+ if (pii==NULL)
+ return NULL;
+ PRUint16 mi, pi, dim;
+ if (!PyArg_ParseTuple(args, "hhh:GetLengthIsArgNumberForParam", &mi, &pi, &dim))
+ return NULL;
+ const nsXPTMethodInfo *pmi;
+ if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
+ return NULL;
+ PRUint8 ret;
+ const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
+ nsresult n = pii->GetLengthIsArgNumberForParam(mi, &param_info, dim, &ret);
+ if (NS_FAILED(n))
+ return PyXPCOM_BuildPyException(n);
+ return PyInt_FromLong(ret);
+}
+
+static PyObject *PyGetInterfaceIsArgNumberForParam(PyObject *self, PyObject *args)
+{
+ nsIInterfaceInfo *pii = GetI(self);
+ if (pii==NULL)
+ return NULL;
+ PRUint16 mi, pi;
+ if (!PyArg_ParseTuple(args, "hhh:GetInterfaceIsArgNumberForParam", &mi, &pi))
+ return NULL;
+ const nsXPTMethodInfo *pmi;
+ if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
+ return NULL;
+ PRUint8 ret;
+ const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
+ nsresult n = pii->GetInterfaceIsArgNumberForParam(mi, &param_info, &ret);
+ if (NS_FAILED(n))
+ return PyXPCOM_BuildPyException(n);
+ return PyInt_FromLong(ret);
+}
+
+struct PyMethodDef
+PyMethods_IInterfaceInfo[] =
+{
+ { "GetName", PyGetName, 1},
+ { "GetIID", PyGetIID, 1},
+ { "IsScriptable", PyIsScriptable, 1},
+ { "GetParent", PyGetParent, 1},
+ { "GetMethodCount", PyGetMethodCount, 1},
+ { "GetConstantCount", PyGetConstantCount, 1},
+ { "GetMethodInfo", PyGetMethodInfo, 1},
+ { "GetMethodInfoForName", PyGetMethodInfoForName, 1},
+ { "GetConstant", PyGetConstant, 1},
+ { "GetInfoForParam", PyGetInfoForParam, 1},
+ { "GetIIDForParam", PyGetIIDForParam, 1},
+ { "GetTypeForParam", PyGetTypeForParam, 1},
+ { "GetSizeIsArgNumberForParam", PyGetSizeIsArgNumberForParam, 1},
+ { "GetLengthIsArgNumberForParam", PyGetLengthIsArgNumberForParam, 1},
+ { "GetInterfaceIsArgNumberForParam", PyGetInterfaceIsArgNumberForParam, 1},
+ {NULL}
+};
+
+/*
+ NS_IMETHOD GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info) = 0;
+ NS_IMETHOD GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info) = 0;
+ NS_IMETHOD GetConstant(PRUint16 index, const nsXPTConstant * *constant) = 0;
+ NS_IMETHOD GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) = 0;
+ NS_IMETHOD GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) = 0;
+ NS_IMETHOD GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval) = 0;
+ NS_IMETHOD GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) = 0;
+ NS_IMETHOD GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) = 0;
+ NS_IMETHOD GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval) = 0;
+
+*/
diff --git a/src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp b/src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp
new file mode 100644
index 00000000..7c629413
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp
@@ -0,0 +1,206 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIInterfaceInfoManager.h>
+
+static nsIInterfaceInfoManager *GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsIInterfaceInfoManager);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIInterfaceInfoManager *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *PyGetInfoForIID(PyObject *self, PyObject *args)
+{
+ PyObject *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "O", &obIID))
+ return NULL;
+
+ nsIInterfaceInfoManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+
+ nsCOMPtr<nsIInterfaceInfo> pi;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetInfoForIID(&iid, getter_AddRefs(pi));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ /* Return a type based on the IID (with no extra ref) */
+ nsIID new_iid = NS_GET_IID(nsIInterfaceInfo);
+ // Can not auto-wrap the interface info manager as it is critical to
+ // building the support we need for autowrap.
+ return Py_nsISupports::PyObjectFromInterface(pi, new_iid, PR_FALSE);
+}
+
+static PyObject *PyGetInfoForName(PyObject *self, PyObject *args)
+{
+ char *name;
+ if (!PyArg_ParseTuple(args, "s", &name))
+ return NULL;
+
+ nsIInterfaceInfoManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsCOMPtr<nsIInterfaceInfo> pi;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetInfoForName(name, getter_AddRefs(pi));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ /* Return a type based on the IID (with no extra ref) */
+ // Can not auto-wrap the interface info manager as it is critical to
+ // building the support we need for autowrap.
+ return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
+}
+
+static PyObject *PyGetNameForIID(PyObject *self, PyObject *args)
+{
+ PyObject *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "O", &obIID))
+ return NULL;
+
+ nsIInterfaceInfoManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+
+ char *ret_name = NULL;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetNameForIID(&iid, &ret_name);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+#if PY_MAJOR_VERSION <= 2
+ PyObject *ret = PyString_FromString(ret_name);
+#else
+ PyObject *ret = PyUnicode_FromString(ret_name);
+#endif
+ nsMemory::Free(ret_name);
+ return ret;
+}
+
+static PyObject *PyGetIIDForName(PyObject *self, PyObject *args)
+{
+ char *name;
+ if (!PyArg_ParseTuple(args, "s", &name))
+ return NULL;
+
+ nsIInterfaceInfoManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID *iid_ret;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetIIDForName(name, &iid_ret);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret);
+ nsMemory::Free(iid_ret);
+ return ret;
+}
+
+static PyObject *PyEnumerateInterfaces(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ nsIInterfaceInfoManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsCOMPtr<nsIEnumerator> pRet;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->EnumerateInterfaces(getter_AddRefs(pRet));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator));
+}
+
+// TODO:
+// void autoRegisterInterfaces();
+
+PyMethodDef
+PyMethods_IInterfaceInfoManager[] =
+{
+ { "GetInfoForIID", PyGetInfoForIID, 1},
+ { "getInfoForIID", PyGetInfoForIID, 1},
+ { "GetInfoForName", PyGetInfoForName, 1},
+ { "getInfoForName", PyGetInfoForName, 1},
+ { "GetIIDForName", PyGetIIDForName, 1},
+ { "getIIDForName", PyGetIIDForName, 1},
+ { "GetNameForIID", PyGetNameForIID, 1},
+ { "getNameForIID", PyGetNameForIID, 1},
+ { "EnumerateInterfaces", PyEnumerateInterfaces, 1},
+ { "enumerateInterfaces", PyEnumerateInterfaces, 1},
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp b/src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp
new file mode 100644
index 00000000..b94d8eb2
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp
@@ -0,0 +1,202 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsISimpleEnumerator.h>
+
+static nsISimpleEnumerator *GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsISimpleEnumerator);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsISimpleEnumerator *)Py_nsISupports::GetI(self);
+}
+
+
+static PyObject *PyHasMoreElements(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":HasMoreElements"))
+ return NULL;
+
+ nsISimpleEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsresult r;
+ PRBool more;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->HasMoreElements(&more);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyInt_FromLong(more);
+}
+
+static PyObject *PyGetNext(PyObject *self, PyObject *args)
+{
+ PyObject *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "|O:GetNext", &obIID))
+ return NULL;
+
+ nsIID iid(NS_GET_IID(nsISupports));
+ if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ nsISimpleEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsISupports *pRet = nsnull;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetNext(&pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ if (obIID) {
+ nsISupports *temp;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pRet->QueryInterface(iid, (void **)&temp);
+ pRet->Release();
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) ) {
+ return PyXPCOM_BuildPyException(r);
+ }
+ pRet = temp;
+ }
+ PyObject *ret = Py_nsISupports::PyObjectFromInterface(pRet, iid);
+ NS_IF_RELEASE(pRet);
+ return ret;
+}
+
+// A method added for Python performance if you really need
+// it. Allows you to fetch a block of objects in one
+// hit, allowing the loop to remain implemented in C.
+static PyObject *PyFetchBlock(PyObject *self, PyObject *args)
+{
+ PyObject *obIID = NULL;
+ int n_wanted;
+ int n_fetched = 0;
+ if (!PyArg_ParseTuple(args, "i|O:FetchBlock", &n_wanted, &obIID))
+ return NULL;
+
+ nsIID iid(NS_GET_IID(nsISupports));
+ if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ nsISimpleEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ // We want to fetch with the thread-lock released,
+ // but this means we can not append to the PyList
+ nsISupports **fetched = new nsISupports*[n_wanted];
+ if (fetched==nsnull) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ memset(fetched, 0, sizeof(nsISupports *) * n_wanted);
+ nsresult r = NS_OK;
+ PRBool more;
+ Py_BEGIN_ALLOW_THREADS;
+ for (;n_fetched<n_wanted;) {
+ r = pI->HasMoreElements(&more);
+ if (NS_FAILED(r))
+ break; // this _is_ an error!
+ if (!more)
+ break; // Normal enum end.
+ nsISupports *pNew;
+ r = pI->GetNext(&pNew);
+ if (NS_FAILED(r)) // IS an error
+ break;
+ if (obIID) {
+ nsISupports *temp;
+ r = pNew->QueryInterface(iid, (void **)&temp);
+ pNew->Release();
+ if ( NS_FAILED(r) ) {
+ break;
+ }
+ pNew = temp;
+ }
+ fetched[n_fetched] = pNew;
+ n_fetched++;
+ }
+ Py_END_ALLOW_THREADS;
+ PyObject *ret;
+ if (NS_SUCCEEDED(r)) {
+ ret = PyList_New(n_fetched);
+ if (ret)
+ for (int i=0;i<n_fetched;i++) {
+ PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid);
+ NS_IF_RELEASE(fetched[i]);
+ PyList_SET_ITEM(ret, i, new_ob);
+ }
+ } else
+ ret = PyXPCOM_BuildPyException(r);
+
+ if ( ret == NULL ) {
+ // Free the objects we consumed.
+ for (int i=0;i<n_fetched;i++)
+ fetched[i]->Release();
+
+ }
+ delete [] fetched;
+ return ret;
+}
+
+
+struct PyMethodDef
+PyMethods_ISimpleEnumerator[] =
+{
+ { "HasMoreElements", PyHasMoreElements, 1},
+ { "hasMoreElements", PyHasMoreElements, 1},
+ { "GetNext", PyGetNext, 1},
+ { "getNext", PyGetNext, 1},
+ { "FetchBlock", PyFetchBlock, 1},
+ { "fetchBlock", PyFetchBlock, 1},
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyISupports.cpp b/src/libs/xpcom18a4/python/src/PyISupports.cpp
new file mode 100644
index 00000000..84504038
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyISupports.cpp
@@ -0,0 +1,621 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include "nsISupportsPrimitives.h"
+
+static PRInt32 cInterfaces=0;
+static PyObject *g_obFuncMakeInterfaceCount = NULL; // XXX - never released!!!
+
+#ifdef VBOX_DEBUG_LIFETIMES
+# include <iprt/log.h>
+# include <iprt/stream.h>
+
+/*static*/ RTLISTNODE Py_nsISupports::g_List;
+/*static*/ RTONCE Py_nsISupports::g_Once = RTONCE_INITIALIZER;
+/*static*/ RTCRITSECT Py_nsISupports::g_CritSect;
+
+/*static*/ DECLCALLBACK(int32_t)
+Py_nsISupports::initOnceCallback(void *pvUser1)
+{
+ NOREF(pvUser1);
+ RTListInit(&g_List);
+ return RTCritSectInit(&g_CritSect);
+}
+
+/*static*/ void
+Py_nsISupports::dumpList(void)
+{
+ RTOnce(&g_Once, initOnceCallback, NULL);
+ RTCritSectEnter(&g_CritSect);
+
+ uint32_t i = 0;
+ Py_nsISupports *pCur;
+ RTListForEach(&g_List, pCur, Py_nsISupports, m_ListEntry)
+ {
+ nsISupports *pISup = pCur->m_obj;
+ PyXPCOM_LogWarning("#%u: %p iid=%RTuuid obj=%p", i, pCur, &pCur->m_iid, pISup);
+ i++;
+ }
+
+ RTCritSectLeave(&g_CritSect);
+}
+
+/*static*/ void
+Py_nsISupports::dumpListToStdOut()
+{
+ RTOnce(&g_Once, initOnceCallback, NULL);
+ RTCritSectEnter(&g_CritSect);
+
+ uint32_t i = 0;
+ Py_nsISupports *pCur;
+ RTListForEach(&g_List, pCur, Py_nsISupports, m_ListEntry)
+ {
+ nsISupports *pISup = pCur->m_obj;
+ RTPrintf("#%u: %p iid=%RTuuid obj=%p\n", i, pCur, &pCur->m_iid, pISup);
+ i++;
+ }
+
+ RTCritSectLeave(&g_CritSect);
+}
+
+PRInt32
+_PyXPCOM_DumpInterfaces(void)
+{
+ Py_nsISupports::dumpListToStdOut();
+ return NS_OK;
+}
+
+#endif /* _DEBUG_LIFETIMES */
+
+
+
+PyObject *PyObject_FromNSInterface( nsISupports *aInterface,
+ const nsIID &iid,
+ PRBool bMakeNicePyObject /*= PR_TRUE */)
+{
+ return Py_nsISupports::PyObjectFromInterface(aInterface, iid,
+ bMakeNicePyObject);
+}
+
+PRInt32
+_PyXPCOM_GetInterfaceCount(void)
+{
+ return cInterfaces;
+}
+
+#ifndef Py_LIMITED_API
+Py_nsISupports::Py_nsISupports(nsISupports *punk, const nsIID &iid, PyTypeObject *this_type)
+#else
+Py_nsISupports::Py_nsISupports(nsISupports *punk, const nsIID &iid, PyXPCOM_TypeObject *this_type)
+#endif
+{
+#ifndef Py_LIMITED_API
+ ob_type = this_type;
+#else
+ ob_type = this_type->m_pTypeObj;
+ m_pMyTypeObj = this_type;
+#endif
+ m_obj = punk;
+ m_iid = iid;
+ // refcnt of object managed by caller.
+ PR_AtomicIncrement(&cInterfaces);
+ PyXPCOM_DLLAddRef();
+#if 1 /* VBox: Must use for 3.9+, includes _Py_NewReferences. Works for all older versions too. @bugref{10079} */
+ PyObject_Init(this, ob_type);
+#else
+ _Py_NewReference(this);
+#endif
+
+#ifdef VBOX_DEBUG_LIFETIMES
+ RTOnce(&g_Once, initOnceCallback, NULL);
+ RTCritSectEnter(&g_CritSect);
+ RTListAppend(&g_List, &m_ListEntry);
+ RTCritSectLeave(&g_CritSect);
+ PyXPCOM_LogWarning("Creating %p: iid=%RTuuid obj=%p", this, &m_iid, punk);
+#endif
+}
+
+Py_nsISupports::~Py_nsISupports()
+{
+#ifdef VBOX_DEBUG_LIFETIMES
+ RTCritSectEnter(&g_CritSect);
+ nsISupports *punk = m_obj;
+ RTListNodeRemove(&m_ListEntry);
+ RTCritSectLeave(&g_CritSect);
+ PyXPCOM_LogWarning("Destroying %p: iid=%RTuuid obj=%p", this, &m_iid, punk);
+#endif
+
+ SafeRelease(this);
+ PR_AtomicDecrement(&cInterfaces);
+ PyXPCOM_DLLRelease();
+}
+
+/*static*/ nsISupports *
+Py_nsISupports::GetI(PyObject *self, nsIID *ret_iid)
+{
+ if (self==NULL) {
+ PyErr_SetString(PyExc_ValueError, "The Python object is invalid");
+ return NULL;
+ }
+ Py_nsISupports *pis = (Py_nsISupports *)self;
+ if (pis->m_obj==NULL) {
+ // This should never be able to happen.
+ PyErr_SetString(PyExc_ValueError, "Internal Error - The XPCOM object has been released.");
+ return NULL;
+ }
+ if (ret_iid)
+ *ret_iid = pis->m_iid;
+ return pis->m_obj;
+}
+
+/*static*/ void
+Py_nsISupports::SafeRelease(Py_nsISupports *ob)
+{
+ if (!ob)
+ return;
+ if (ob->m_obj)
+ {
+ Py_BEGIN_ALLOW_THREADS;
+ ob->m_obj = nsnull;
+ Py_END_ALLOW_THREADS;
+ }
+}
+
+/* virtual */ PyObject *
+Py_nsISupports::getattr(const char *name)
+{
+ if (strcmp(name, "IID")==0)
+ return Py_nsIID::PyObjectFromIID( m_iid );
+
+ // Support for __unicode__ until we get a tp_unicode slot.
+ if (strcmp(name, "__unicode__")==0) {
+ nsresult rv;
+ PRUnichar *val = NULL;
+ Py_BEGIN_ALLOW_THREADS;
+ { // scope to kill pointer while thread-lock released.
+ nsCOMPtr<nsISupportsString> ss( do_QueryInterface(m_obj, &rv ));
+ if (NS_SUCCEEDED(rv))
+ rv = ss->ToString(&val);
+ } // end-scope
+ Py_END_ALLOW_THREADS;
+ PyObject *ret = NS_FAILED(rv) ?
+ PyXPCOM_BuildPyException(rv) :
+ PyObject_FromNSString(val);
+ if (val) nsMemory::Free(val);
+ return ret;
+ }
+#ifndef Py_LIMITED_API
+ PyXPCOM_TypeObject *this_type = (PyXPCOM_TypeObject *)ob_type;
+#else
+ PyXPCOM_TypeObject *this_type = m_pMyTypeObj;
+#endif
+#if PY_MAJOR_VERSION <= 2
+ return Py_FindMethodInChain(&this_type->chain, this, (char *)name);
+#else
+ PyMethodChain *chain = &this_type->chain;
+ if (name[0] == '_' && name[1] == '_') {
+# ifndef Py_LIMITED_API /** @todo ? */
+ if (!strcmp(name, "__doc__")) {
+ const char *doc = ob_type->tp_doc;
+ if (doc)
+ return PyUnicode_FromString(doc);
+ }
+# endif
+ }
+ while (chain) {
+ PyMethodDef *ml = chain->methods;
+ for (; ml->ml_name; ml++) {
+ if (!strcmp(name, ml->ml_name))
+ return PyCFunction_New(ml, this);
+ }
+ chain = chain->link;
+ }
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+#endif
+}
+
+/* virtual */ int
+Py_nsISupports::setattr(const char *name, PyObject *v)
+{
+ char buf[128];
+#ifdef VBOX
+ snprintf(buf, sizeof(buf), "%s has read-only attributes", PyXPCOM_ObTypeName(this) );
+#else
+ sprintf(buf, "%s has read-only attributes", PyXPCOM_ObTypeName(this) );
+#endif
+ PyErr_SetString(PyExc_TypeError, buf);
+ return -1;
+}
+
+/*static*/ Py_nsISupports *
+Py_nsISupports::Constructor(nsISupports *pInitObj, const nsIID &iid)
+{
+ return new Py_nsISupports(pInitObj,
+ iid,
+ type);
+}
+
+PRBool
+Py_nsISupports::InterfaceFromPyISupports(PyObject *ob,
+ const nsIID &iid,
+ nsISupports **ppv)
+{
+ nsISupports *pis;
+ PRBool rc = PR_FALSE;
+ if ( !Check(ob) )
+ {
+ PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be used as COM objects", PyXPCOM_ObTypeName(ob));
+ goto done;
+ }
+ nsIID already_iid;
+ pis = GetI(ob, &already_iid);
+ if ( !pis )
+ goto done; /* exception was set by GetI() */
+ /* note: we don't (yet) explicitly hold a reference to pis */
+ if (iid.Equals(Py_nsIID_NULL)) {
+ // a bit of a hack - we are asking for the arbitary interface
+ // wrapped by this object, not some other specific interface -
+ // so no QI, just an AddRef();
+ Py_BEGIN_ALLOW_THREADS
+ pis->AddRef();
+ Py_END_ALLOW_THREADS
+ *ppv = pis;
+ } else {
+ // specific interface requested - if it is not already the
+ // specific interface, QI for it and discard pis.
+ if (iid.Equals(already_iid)) {
+ *ppv = pis;
+ pis->AddRef();
+ } else {
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS
+ r = pis->QueryInterface(iid, (void **)ppv);
+ Py_END_ALLOW_THREADS
+ if ( NS_FAILED(r) )
+ {
+ PyXPCOM_BuildPyException(r);
+ goto done;
+ }
+ /* note: the QI added a ref for the return value */
+ }
+ }
+ rc = PR_TRUE;
+done:
+ return rc;
+}
+
+PRBool
+Py_nsISupports::InterfaceFromPyObject(PyObject *ob,
+ const nsIID &iid,
+ nsISupports **ppv,
+ PRBool bNoneOK,
+ PRBool bTryAutoWrap /* = PR_TRUE */)
+{
+ if ( ob == NULL )
+ {
+ // don't overwrite an error message
+ if ( !PyErr_Occurred() )
+ PyErr_SetString(PyExc_TypeError, "The Python object is invalid");
+ return PR_FALSE;
+ }
+ if ( ob == Py_None )
+ {
+ if ( bNoneOK )
+ {
+ *ppv = NULL;
+ return PR_TRUE;
+ }
+ else
+ {
+ PyErr_SetString(PyExc_TypeError, "None is not a invalid interface object in this context");
+ return PR_FALSE;
+ }
+ }
+
+ // support nsIVariant
+ if (iid.Equals(NS_GET_IID(nsIVariant)) || iid.Equals(NS_GET_IID(nsIWritableVariant))) {
+ // Check it is not already nsIVariant
+ if (PyObject_HasAttrString(ob, "__class__")) {
+ PyObject *sub_ob = PyObject_GetAttrString(ob, "_comobj_");
+ if (sub_ob==NULL) {
+ PyErr_Clear();
+ } else {
+ if (InterfaceFromPyISupports(sub_ob, iid, ppv)) {
+ Py_DECREF(sub_ob);
+ return PR_TRUE;
+ }
+ PyErr_Clear();
+ Py_DECREF(sub_ob);
+ }
+ }
+ nsresult nr = PyObject_AsVariant(ob, (nsIVariant **)ppv);
+ if (NS_FAILED(nr)) {
+ PyXPCOM_BuildPyException(nr);
+ return PR_FALSE;
+ }
+ NS_ASSERTION(ppv != nsnull, "PyObject_AsVariant worked but gave null!");
+ return PR_TRUE;
+ }
+ // end of variant support.
+
+ if (PyObject_HasAttrString(ob, "__class__")) {
+ // Get the _comobj_ attribute
+ PyObject *use_ob = PyObject_GetAttrString(ob, "_comobj_");
+ if (use_ob==NULL) {
+ PyErr_Clear();
+ if (bTryAutoWrap)
+ // Try and auto-wrap it - errors will leave Py exception set,
+ return PyXPCOM_XPTStub::AutoWrapPythonInstance(ob, iid, ppv);
+ PyErr_SetString(PyExc_TypeError, "The Python instance can not be converted to an XPCOM object");
+ return PR_FALSE;
+ } else
+ ob = use_ob;
+
+ } else {
+ Py_INCREF(ob);
+ }
+ PRBool rc = InterfaceFromPyISupports(ob, iid, ppv);
+ Py_DECREF(ob);
+ return rc;
+}
+
+
+// Interface conversions
+/*static*/void
+#ifndef Py_LIMITED_API
+Py_nsISupports::RegisterInterface( const nsIID &iid, PyTypeObject *t)
+#else
+Py_nsISupports::RegisterInterface( const nsIID &iid, PyXPCOM_TypeObject *t)
+#endif
+{
+ if (mapIIDToType==NULL)
+ mapIIDToType = PyDict_New();
+
+ if (mapIIDToType) {
+ PyObject *key = Py_nsIID::PyObjectFromIID(iid);
+ if (key)
+ PyDict_SetItem(mapIIDToType, key, (PyObject *)t);
+ Py_XDECREF(key);
+ }
+}
+
+/*static */PyObject *
+Py_nsISupports::PyObjectFromInterface(nsISupports *pis,
+ const nsIID &riid,
+ PRBool bMakeNicePyObject, /* = PR_TRUE */
+ PRBool bIsInternalCall /* = PR_FALSE */)
+{
+ // Quick exit.
+ if (pis==NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ if (!bIsInternalCall) {
+#ifdef NS_DEBUG
+ nsISupports *queryResult = nsnull;
+ Py_BEGIN_ALLOW_THREADS;
+ pis->QueryInterface(riid, (void **)&queryResult);
+ Py_END_ALLOW_THREADS;
+ NS_ASSERTION(queryResult == pis, "QueryInterface needed");
+ NS_IF_RELEASE(queryResult);
+#endif
+ }
+
+#ifndef Py_LIMITED_API
+ PyTypeObject *createType = NULL;
+#else
+ PyXPCOM_TypeObject *createType = NULL;
+#endif
+ // If the IID is for nsISupports, dont bother with
+ // a map lookup as we know the type!
+ if (!riid.Equals(NS_GET_IID(nsISupports))) {
+ // Look up the map
+ PyObject *obiid = Py_nsIID::PyObjectFromIID(riid);
+ if (!obiid) return NULL;
+
+ if (mapIIDToType != NULL)
+#ifndef Py_LIMITED_API
+ createType = (PyTypeObject *)PyDict_GetItem(mapIIDToType, obiid);
+#else
+ createType = (PyXPCOM_TypeObject *)PyDict_GetItem(mapIIDToType, obiid);
+#endif
+ Py_DECREF(obiid);
+ }
+ if (createType==NULL)
+ createType = Py_nsISupports::type;
+#ifndef Py_LIMITED_API
+ // Check it is indeed one of our types.
+ if (!PyXPCOM_TypeObject::IsType(createType)) {
+ PyErr_SetString(PyExc_RuntimeError, "The type map is invalid");
+ return NULL;
+ }
+ // we can now safely cast the thing to a PyComTypeObject and use it
+ PyXPCOM_TypeObject *myCreateType = (PyXPCOM_TypeObject *)createType;
+#else /* Since the mapIIDToType is only updated by us, there should be no need for the above. */
+ PyXPCOM_TypeObject * const myCreateType = createType;
+#endif
+ if (myCreateType->ctor==NULL) {
+ PyErr_SetString(PyExc_TypeError, "The type does not declare a PyCom constructor");
+ return NULL;
+ }
+
+ Py_nsISupports *ret = (*myCreateType->ctor)(pis, riid);
+#ifdef _DEBUG_LIFETIMES
+ PyXPCOM_LogF("XPCOM Object created at 0x%0xld, nsISupports at 0x%0xld",
+ ret, ret->m_obj);
+#endif
+ if (ret && bMakeNicePyObject)
+ return MakeDefaultWrapper(ret, riid);
+ return ret;
+}
+
+// Call back into Python, passing a raw nsIInterface object, getting back
+// the object to actually pass to Python.
+PyObject *
+Py_nsISupports::MakeDefaultWrapper(PyObject *pyis,
+ const nsIID &iid)
+{
+ NS_PRECONDITION(pyis, "NULL pyobject!");
+ PyObject *obIID = NULL;
+ PyObject *args = NULL;
+ PyObject *mod = NULL;
+ PyObject *ret = NULL;
+
+ obIID = Py_nsIID::PyObjectFromIID(iid);
+ if (obIID==NULL)
+ goto done;
+
+ if (g_obFuncMakeInterfaceCount==NULL) {
+ PyObject *mod = PyImport_ImportModule("xpcom.client");
+ if (mod)
+ g_obFuncMakeInterfaceCount = PyObject_GetAttrString(mod, "MakeInterfaceResult");
+ Py_XDECREF(mod);
+ }
+ if (g_obFuncMakeInterfaceCount==NULL) goto done;
+
+ args = Py_BuildValue("OO", pyis, obIID);
+ if (args==NULL) goto done;
+ ret = PyEval_CallObject(g_obFuncMakeInterfaceCount, args);
+done:
+ if (PyErr_Occurred()) {
+ NS_ABORT_IF_FALSE(ret==NULL, "Have an error, but also a return val!");
+ PyXPCOM_LogError("Creating an interface object to be used as a result failed\n");
+ PyErr_Clear();
+ }
+ Py_XDECREF(mod);
+ Py_XDECREF(args);
+ Py_XDECREF(obIID);
+ if (ret==NULL) // eek - error - return the original with no refcount mod.
+ ret = pyis;
+ else
+ // no error - decref the old object
+ Py_DECREF(pyis);
+ // return our obISupports. If NULL, we are really hosed and nothing we can do.
+ return ret;
+}
+
+// @pymethod <o Py_nsISupports>|Py_nsISupports|QueryInterface|Queries an object for a specific interface.
+PyObject *
+Py_nsISupports::QueryInterface(PyObject *self, PyObject *args)
+{
+ PyObject *obiid;
+ int bWrap = 1;
+ // @pyparm IID|iid||The IID requested.
+ // @rdesc The result is always a <o Py_nsISupports> object.
+ // Any error (including E_NOINTERFACE) will generate a <o com_error> exception.
+ if (!PyArg_ParseTuple(args, "O|i:QueryInterface", &obiid, &bWrap))
+ return NULL;
+
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obiid, &iid))
+ return NULL;
+
+ nsISupports *pMyIS = GetI(self);
+ if (pMyIS==NULL) return NULL;
+
+ // Optimization, If we already wrap the IID, just return
+ // ourself.
+ if (!bWrap && iid.Equals(((Py_nsISupports *)self)->m_iid)) {
+ Py_INCREF(self);
+ return self;
+ }
+
+ nsCOMPtr<nsISupports> pis;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pMyIS->QueryInterface(iid, getter_AddRefs(pis));
+ Py_END_ALLOW_THREADS;
+
+ /* Note that this failure may include E_NOINTERFACE */
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ /* Return a type based on the IID (with no extra ref) */
+ return ((Py_nsISupports *)self)->MakeInterfaceResult(pis, iid, (PRBool)bWrap);
+}
+
+
+#ifdef VBOX
+static PyObject *
+QueryErrorObject(PyObject *self, PyObject *args)
+{
+ nsresult rc = 0;
+
+ if (!PyArg_ParseTuple(args, "i", &rc))
+ return NULL;
+
+ return PyXPCOM_BuildErrorMessage(rc);
+}
+#endif
+
+// @object Py_nsISupports|The base object for all PythonCOM objects. Wraps a COM nsISupports interface.
+/*static*/ struct PyMethodDef
+Py_nsISupports::methods[] =
+{
+ { "queryInterface", Py_nsISupports::QueryInterface, 1, "Queries the object for an interface."},
+ { "QueryInterface", Py_nsISupports::QueryInterface, 1, "An alias for queryInterface."},
+#ifdef VBOX
+ { "QueryErrorObject", QueryErrorObject, 1, "Query an error object for given status code."},
+#endif
+ {NULL}
+};
+
+/*static*/void Py_nsISupports::InitType(void)
+{
+ type = new PyXPCOM_TypeObject(
+ "nsISupports",
+ NULL,
+ sizeof(Py_nsISupports),
+ methods,
+ Constructor);
+}
+
+PyXPCOM_TypeObject *Py_nsISupports::type = NULL;
+PyObject *Py_nsISupports::mapIIDToType = NULL;
diff --git a/src/libs/xpcom18a4/python/src/PyIVariant.cpp b/src/libs/xpcom18a4/python/src/PyIVariant.cpp
new file mode 100644
index 00000000..cd9f79c4
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIVariant.cpp
@@ -0,0 +1,231 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * Mark Hammond.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This code is part of the XPCOM extensions for Python.
+//
+// Written April 2002
+
+#include "PyXPCOM_std.h"
+#include "nsIVariant.h"
+
+// Prevents us needing to use an nsIScriptableInputStream
+// (and even that can't read binary data!!!)
+
+static nsIVariant *GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsIVariant);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIVariant *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *MyBool( PRBool v) {
+ PyObject *ret = v ? Py_True : Py_False;
+ Py_INCREF(ret);
+ return ret;
+}
+static PyObject *MyChar( char c) {
+#if PY_MAJOR_VERSION <= 2
+ return PyString_FromStringAndSize(&c, 1);
+#else
+ return PyUnicode_FromStringAndSize(&c, 1);
+#endif
+}
+static PyObject *MyUChar( PRUnichar c) {
+ return PyObject_FromNSString( &c, 1);
+}
+static PyObject *MyUnicode( PRUnichar *p) {
+ return PyObject_FromNSString(p);
+}
+
+#define GET_SIMPLE(Type, FuncGet, FuncConvert) \
+static PyObject *FuncGet(PyObject *self, PyObject *args) { \
+ nsIVariant *pI = GetI(self); \
+ if (pI==NULL) return NULL; \
+ if (!PyArg_ParseTuple(args, ":" #FuncGet)) return NULL; \
+ Type t; \
+ nsresult nr = pI->FuncGet(&t); \
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr); \
+ return FuncConvert(t); \
+}
+
+#define GET_ALLOCATED(Type, FuncGet, FuncConvert, FuncFree) \
+static PyObject *FuncGet(PyObject *self, PyObject *args) { \
+ nsIVariant *pI = GetI(self); \
+ if (pI==NULL) return NULL; \
+ if (!PyArg_ParseTuple(args, ":" #FuncGet)) return NULL; \
+ Type t; \
+ nsresult nr = pI->FuncGet(&t); \
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr); \
+ PyObject *ret = FuncConvert(t); \
+ FuncFree(t); \
+ return ret; \
+}
+
+#define GET_ALLOCATED_SIZE(Type, FuncGet, FuncConvert, FuncFree) \
+static PyObject *FuncGet(PyObject *self, PyObject *args) { \
+ nsIVariant *pI = GetI(self); \
+ if (pI==NULL) return NULL; \
+ if (!PyArg_ParseTuple(args, ":" #FuncGet)) return NULL; \
+ Type t; PRUint32 size; \
+ nsresult nr = pI->FuncGet(&size, &t); \
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr); \
+ PyObject *ret = FuncConvert(t, size); \
+ FuncFree(t); \
+ return ret; \
+}
+
+GET_SIMPLE(PRUint8, GetAsInt8, PyInt_FromLong)
+GET_SIMPLE(PRUint8, GetAsUint8, PyInt_FromLong)
+GET_SIMPLE(PRInt16, GetAsInt16, PyInt_FromLong)
+GET_SIMPLE(PRUint16, GetAsUint16, PyInt_FromLong)
+GET_SIMPLE(PRInt32, GetAsInt32, PyInt_FromLong)
+GET_SIMPLE(PRUint32, GetAsUint32, PyInt_FromLong)
+GET_SIMPLE(PRInt64, GetAsInt64, PyLong_FromLongLong)
+GET_SIMPLE(PRUint64, GetAsUint64, PyLong_FromUnsignedLongLong)
+GET_SIMPLE(float, GetAsFloat, PyFloat_FromDouble)
+GET_SIMPLE(double, GetAsDouble, PyFloat_FromDouble)
+GET_SIMPLE(PRBool, GetAsBool, MyBool)
+GET_SIMPLE(char, GetAsChar, MyChar)
+GET_SIMPLE(PRUnichar, GetAsWChar, MyUChar)
+GET_SIMPLE(nsIID, GetAsID, Py_nsIID::PyObjectFromIID)
+
+#if PY_MAJOR_VERSION <= 2
+GET_ALLOCATED(char *, GetAsString, PyString_FromString, nsMemory::Free)
+#else
+GET_ALLOCATED(char *, GetAsString, PyUnicode_FromString, nsMemory::Free)
+#endif
+GET_ALLOCATED(PRUnichar *, GetAsWString, MyUnicode, nsMemory::Free)
+#if PY_MAJOR_VERSION <= 2
+GET_ALLOCATED_SIZE(char *, GetAsStringWithSize, PyString_FromStringAndSize, nsMemory::Free)
+#else
+GET_ALLOCATED_SIZE(char *, GetAsStringWithSize, PyUnicode_FromStringAndSize, nsMemory::Free)
+#endif
+GET_ALLOCATED_SIZE(PRUnichar *, GetAsWStringWithSize, PyObject_FromNSString, nsMemory::Free)
+
+static PyObject *GetAsInterface(PyObject *self, PyObject *args) {
+ nsIVariant *pI = GetI(self);
+ if (pI==NULL) return NULL;
+ if (!PyArg_ParseTuple(args, ":GetAsInterface")) return NULL;
+ nsCOMPtr<nsISupports> p;
+ nsIID *iid;
+ nsresult nr = pI->GetAsInterface(&iid, getter_AddRefs(p));
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
+ return Py_nsISupports::PyObjectFromInterface(p, *iid);
+}
+
+static PyObject *GetAsISupports(PyObject *self, PyObject *args) {
+ nsIVariant *pI = GetI(self);
+ if (pI==NULL) return NULL;
+ if (!PyArg_ParseTuple(args, ":GetAsInterface")) return NULL;
+ nsCOMPtr<nsISupports> p;
+ nsIID *iid;
+ nsresult nr = pI->GetAsInterface(&iid, getter_AddRefs(p));
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
+ return Py_nsISupports::PyObjectFromInterface(p, *iid);
+}
+
+extern PyObject *PyObject_FromVariantArray( Py_nsISupports*, nsIVariant *v);
+
+static PyObject *GetAsArray(PyObject *self, PyObject *args) {
+ nsIVariant *pI = GetI(self);
+ if (pI==NULL) return NULL;
+ if (!PyArg_ParseTuple(args, ":GetAsArray")) return NULL;
+ return PyObject_FromVariantArray((Py_nsISupports *)self, pI);
+}
+
+static PyObject *Get(PyObject *self, PyObject *args) {
+ nsIVariant *pI = GetI(self);
+ if (pI==NULL) return NULL;
+ if (!PyArg_ParseTuple(args, ":Get")) return NULL;
+ return PyObject_FromVariant((Py_nsISupports *)self, pI);
+}
+
+struct PyMethodDef
+PyMethods_IVariant[] =
+{
+ { "getAsInt8", GetAsInt8, 1},
+ { "getAsUint8", GetAsUint8, 1},
+ { "getAsInt16", GetAsInt16, 1},
+ { "getAsUint16", GetAsUint16, 1},
+ { "getAsInt32", GetAsInt32, 1},
+ { "getAsUint32", GetAsUint32, 1},
+ { "getAsInt64", GetAsInt64, 1},
+ { "getAsUint64", GetAsUint64, 1},
+ { "getAsFloat", GetAsFloat, 1},
+ { "getAsDouble", GetAsDouble, 1},
+ { "getAsBool", GetAsBool, 1},
+ { "getAsChar", GetAsChar, 1},
+ { "getAsWChar", GetAsWChar, 1},
+ { "getAsString", GetAsString, 1},
+ { "getAsWString", GetAsWString, 1},
+ { "getAsStringWithSize", GetAsStringWithSize, 1},
+ { "getAsWStringWithSize", GetAsWStringWithSize, 1},
+ { "getAsISupports", GetAsISupports, 1},
+ { "getAsInterface", GetAsInterface, 1},
+ { "getAsArray", GetAsArray, 1},
+ { "getAsID", GetAsID, 1},
+ { "get", Get, 1},
+ {NULL}
+};
+
+PyObject *
+Py_nsIVariant::getattr(const char *name)
+{
+
+ PyObject *ret = NULL;
+ if (strcmp(name, "dataType")==0) {
+ nsIVariant *pI = ::GetI(this);
+ if (pI) {
+ PRUint16 dt;
+ nsresult nr = pI->GetDataType(&dt);
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
+ ret = PyInt_FromLong(dt);
+ }
+ } else {
+ ret = Py_nsISupports::getattr(name);
+ }
+ return ret;
+}
+
+int
+Py_nsIVariant::setattr(const char *name, PyObject *v)
+{
+ return Py_nsISupports::setattr(name, v);
+}
diff --git a/src/libs/xpcom18a4/python/src/PyXPCOM.h b/src/libs/xpcom18a4/python/src/PyXPCOM.h
new file mode 100644
index 00000000..91bc8d12
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyXPCOM.h
@@ -0,0 +1,1036 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// PyXPCOM.h - the main header file for the Python XPCOM support.
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#ifndef __PYXPCOM_H__
+#define __PYXPCOM_H__
+
+#include "nsIAllocator.h"
+#include "nsIWeakReference.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsIClassInfo.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentManagerObsolete.h"
+#include "nsIServiceManager.h"
+#include "nsIInputStream.h"
+#include "nsIVariant.h"
+#include "nsIModule.h"
+
+#include "nsXPIDLString.h"
+#include "nsCRT.h"
+#include "xptcall.h"
+#include "xpt_xdr.h"
+
+#ifdef VBOX_DEBUG_LIFETIMES
+# include <iprt/critsect.h>
+# include <iprt/list.h>
+# include <iprt/once.h>
+#endif
+
+#ifdef HAVE_LONG_LONG
+ // Mozilla also defines this - we undefine it to
+ // prevent a compiler warning.
+# undef HAVE_LONG_LONG
+#endif // HAVE_LONG_LONG
+
+#ifdef _POSIX_C_SOURCE // Ditto here
+# undef _POSIX_C_SOURCE
+#endif // _POSIX_C_SOURCE
+
+#ifdef VBOX_PYXPCOM
+// unfortunatelly, if SOLARIS is defined Python porting layer
+// defines gethostname() in invalid fashion what kills compilation
+# ifdef SOLARIS
+# undef SOLARIS
+# define SOLARIS_WAS_DEFINED
+# endif
+
+// Python.h/pyconfig.h redefines _XOPEN_SOURCE on some hosts
+# ifdef _XOPEN_SOURCE
+# define VBOX_XOPEN_SOURCE_DEFINED _XOPEN_SOURCE
+# undef _XOPEN_SOURCE
+# endif
+
+#endif /* VBOX_PYXPCOM */
+
+#include <Python.h>
+
+#ifdef VBOX_PYXPCOM
+
+# ifdef SOLARIS_WAS_DEFINED
+# define SOLARIS
+# undef SOLARIS_WAS_DEFINED
+# endif
+
+// restore the old value of _XOPEN_SOURCE if not defined by Python.h/pyconfig.h
+# if !defined(_XOPEN_SOURCE) && defined(VBOX_XOPEN_SOURCE_DEFINED)
+# define _XOPEN_SOURCE VBOX_XOPEN_SOURCE_DEFINED
+# endif
+# undef VBOX_XOPEN_SOURCE_DEFINED
+
+# if (PY_VERSION_HEX <= 0x02040000)
+// although in more recent versions of Python this type is ssize_t, earlier
+// it was used as int
+typedef int Py_ssize_t;
+# endif
+
+# if (PY_VERSION_HEX <= 0x02030000)
+// this one not defined before
+inline PyObject *PyBool_FromLong(long ok)
+{
+ PyObject *result;
+ if (ok)
+ result = Py_True;
+ else
+ result = Py_False;
+ Py_INCREF(result);
+ return result;
+}
+# endif
+
+# if PY_MAJOR_VERSION >= 3
+# define PyInt_FromLong(l) PyLong_FromLong(l)
+# define PyInt_Check(o) PyLong_Check(o)
+# define PyInt_AsLong(o) PyLong_AsLong(o)
+# define PyNumber_Int(o) PyNumber_Long(o)
+# if !defined(Py_LIMITED_API) && PY_VERSION_HEX <= 0x03030000 /* 3.3 added PyUnicode_AsUTF8AndSize */
+# ifndef PyUnicode_AsUTF8
+# define PyUnicode_AsUTF8(o) _PyUnicode_AsString(o)
+# endif
+# ifndef PyUnicode_AsUTF8AndSize
+# define PyUnicode_AsUTF8AndSize(o,s) _PyUnicode_AsStringAndSize(o,s)
+# endif
+# endif
+typedef struct PyMethodChain
+{
+ PyMethodDef *methods;
+ struct PyMethodChain *link;
+} PyMethodChain;
+# endif
+
+#endif /* VBOX_PYXPCOM */
+
+#ifdef BUILD_PYXPCOM
+ /* We are building the main dll */
+# define PYXPCOM_EXPORT NS_EXPORT
+#else
+ /* This module uses the dll */
+# define PYXPCOM_EXPORT NS_IMPORT
+#endif // BUILD_PYXPCOM
+
+// An IID we treat as NULL when passing as a reference.
+extern PYXPCOM_EXPORT nsIID Py_nsIID_NULL;
+
+class Py_nsISupports;
+
+
+/** @name VBox limited API hacks:
+ * @{ */
+#ifndef Py_LIMITED_API
+
+# define PyXPCOM_ObTypeName(obj) (Py_TYPE(obj)->tp_name)
+
+#else /* Py_LIMITED_API */
+
+# if PY_VERSION_HEX <= 0x03030000
+# error "Py_LIMITED_API mode only works for Python 3.3 and higher."
+# endif
+
+const char *PyXPCOMGetObTypeName(PyTypeObject *pTypeObj);
+# define PyXPCOM_ObTypeName(obj) PyXPCOMGetObTypeName(Py_TYPE(obj))
+
+# if Py_LIMITED_API < 0x030A0000
+/* Note! While we should not technically be using PyUnicode_AsUTF8AndSize, it was
+ made part of the limited API in 3.10 (see https://bugs.python.org/issue41784 and
+ https://github.com/python/cpython/commit/a05195ac61f1908ac5990cccb5aa82442bdaf15d). */
+extern "C" PyAPI_FUNC(const char *) PyUnicode_AsUTF8AndSize(PyObject *, Py_ssize_t *);
+# endif
+
+/* PyUnicode_AsUTF8 is just PyUnicode_AsUTF8AndSize without returning a size. */
+# define PyUnicode_AsUTF8(o) PyUnicode_AsUTF8AndSize(o, NULL)
+
+DECLINLINE(int) PyRun_SimpleString(const char *pszCode)
+{
+ /* Get the main mode dictionary: */
+ PyObject *pMainMod = PyImport_AddModule("__main__");
+ if (pMainMod) {
+ PyObject *pMainModDict = PyModule_GetDict(pMainMod);
+
+ /* Compile and run the code. */
+ PyObject *pCodeObject = Py_CompileString(pszCode, "PyXPCOM", Py_file_input);
+ if (pCodeObject) {
+ PyObject *pResult = PyEval_EvalCode(pCodeObject, pMainModDict, pMainModDict);
+ Py_DECREF(pCodeObject);
+ if (pResult) {
+ Py_DECREF(pResult);
+ return 0;
+ }
+ PyErr_Print();
+ }
+ }
+ return -1;
+}
+
+DECLINLINE(PyObject *) PyTuple_GET_ITEM(PyObject *pTuple, Py_ssize_t idx)
+{
+ return PyTuple_GetItem(pTuple, idx);
+}
+
+DECLINLINE(int) PyTuple_SET_ITEM(PyObject *pTuple, Py_ssize_t idx, PyObject *pItem)
+{
+ int rc = PyTuple_SetItem(pTuple, idx, pItem); /* Steals pItem ref, just like PyTuple_SET_ITEM. */
+ Assert(rc == 0);
+ return rc;
+}
+
+DECLINLINE(int) PyList_SET_ITEM(PyObject *pList, Py_ssize_t idx, PyObject *pItem)
+{
+ int rc = PyList_SetItem(pList, idx, pItem); /* Steals pItem ref, just like PyList_SET_ITEM. */
+ Assert(rc == 0);
+ return rc;
+}
+
+DECLINLINE(Py_ssize_t) PyBytes_GET_SIZE(PyObject *pBytes)
+{
+ return PyBytes_Size(pBytes);
+}
+
+DECLINLINE(const char *) PyBytes_AS_STRING(PyObject *pBytes)
+{
+ return PyBytes_AsString(pBytes);
+}
+
+DECLINLINE(Py_ssize_t) PyUnicode_GET_SIZE(PyObject *pUnicode)
+{
+ /* Note! Currently only used for testing for zero or 1 codepoints, so we don't
+ really need to deal with the different way these two treats surrogate pairs. */
+# if Py_LIMITED_API >= 0x03030000
+ return PyUnicode_GetLength(pUnicode);
+# else
+ return PyUnicode_GetSize(pUnicode);
+# endif
+}
+
+# define PyObject_CheckBuffer(pAllegedBuffer) PyObject_CheckReadBuffer(pAllegedBuffer)
+
+# include <iprt/asm.h>
+DECLINLINE(Py_hash_t) _Py_HashPointer(void *p)
+{
+ Py_hash_t uHash = (Py_hash_t)RT_CONCAT(ASMRotateRightU,ARCH_BITS)((uintptr_t)p, 4);
+ return uHash != -1 ? uHash : -2;
+}
+
+#endif /* Py_LIMITED_API */
+/** @} */
+
+
+/*************************************************************************
+**************************************************************************
+
+ Error and exception related function.
+
+**************************************************************************
+*************************************************************************/
+
+#define NS_PYXPCOM_NO_SUCH_METHOD \
+ NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_PYXPCOM, 0)
+
+// The exception object (loaded from the xpcom .py code)
+extern PYXPCOM_EXPORT PyObject *PyXPCOM_Error;
+
+// Client related functions - generally called by interfaces before
+// they return NULL back to Python to indicate the error.
+// All these functions return NULL so interfaces can generally
+// just "return PyXPCOM_BuildPyException(hr, punk, IID_IWhatever)"
+PYXPCOM_EXPORT PyObject *PyXPCOM_BuildPyException(nsresult res);
+
+#ifdef VBOX
+// Build human readable error message out of XPCOM error
+PYXPCOM_EXPORT PyObject *PyXPCOM_BuildErrorMessage(nsresult r);
+#endif
+
+// Used in gateways to handle the current Python exception
+// NOTE: this function assumes it is operating within the Python context
+PYXPCOM_EXPORT nsresult PyXPCOM_SetCOMErrorFromPyException();
+
+// Write current exception and traceback to a string.
+PYXPCOM_EXPORT PRBool PyXPCOM_FormatCurrentException(nsCString &streamout);
+// Write specified exception and traceback to a string.
+PYXPCOM_EXPORT PRBool PyXPCOM_FormatGivenException(nsCString &streamout,
+ PyObject *exc_typ, PyObject *exc_val,
+ PyObject *exc_tb);
+
+// A couple of logging/error functions. These probably end up
+// being written to the console service.
+
+// Log a warning for the user - something at runtime
+// they may care about, but nothing that prevents us actually
+// working.
+// As it's designed for user error/warning, it exists in non-debug builds.
+PYXPCOM_EXPORT void PyXPCOM_LogWarning(const char *fmt, ...);
+
+// Log an error for the user - something that _has_ prevented
+// us working. This is probably accompanied by a traceback.
+// As it's designed for user error/warning, it exists in non-debug builds.
+PYXPCOM_EXPORT void PyXPCOM_LogError(const char *fmt, ...);
+
+// The raw one
+PYXPCOM_EXPORT void PyXPCOM_Log(const char *level, const nsCString &msg);
+
+#ifdef DEBUG
+// Mainly designed for developers of the XPCOM package.
+// Only enabled in debug builds.
+PYXPCOM_EXPORT void PyXPCOM_LogDebug(const char *fmt, ...);
+#define PYXPCOM_LOG_DEBUG PyXPCOM_LogDebug
+#else
+#define PYXPCOM_LOG_DEBUG()
+#endif // DEBUG
+
+// Some utility converters
+// moz strings to PyObject.
+PYXPCOM_EXPORT PyObject *PyObject_FromNSString( const nsACString &s,
+ PRBool bAssumeUTF8 = PR_FALSE );
+PYXPCOM_EXPORT PyObject *PyObject_FromNSString( const nsAString &s );
+PYXPCOM_EXPORT PyObject *PyObject_FromNSString( const PRUnichar *s,
+ PRUint32 len = (PRUint32)-1);
+
+// PyObjects to moz strings. As per the moz string guide, we pass a reference
+// to an abstract string
+PYXPCOM_EXPORT PRBool PyObject_AsNSString( PyObject *ob, nsAString &aStr);
+
+// Variants.
+PYXPCOM_EXPORT nsresult PyObject_AsVariant( PyObject *ob, nsIVariant **aRet);
+PYXPCOM_EXPORT PyObject *PyObject_FromVariant( Py_nsISupports *parent,
+ nsIVariant *v);
+
+// Interfaces - these are the "official" functions
+PYXPCOM_EXPORT PyObject *PyObject_FromNSInterface( nsISupports *aInterface,
+ const nsIID &iid,
+ PRBool bMakeNicePyObject = PR_TRUE);
+
+/*************************************************************************
+**************************************************************************
+
+ Support for CALLING (ie, using) interfaces.
+
+**************************************************************************
+*************************************************************************/
+
+typedef Py_nsISupports* (* PyXPCOM_I_CTOR)(nsISupports *, const nsIID &);
+
+//////////////////////////////////////////////////////////////////////////
+// class PyXPCOM_TypeObject
+// Base class for (most of) the type objects.
+
+#ifndef Py_LIMITED_API
+class PYXPCOM_EXPORT PyXPCOM_TypeObject : public PyTypeObject {
+#else
+class PYXPCOM_EXPORT PyXPCOM_TypeObject : public PyObject {
+#endif
+public:
+ PyXPCOM_TypeObject(
+ const char *name,
+ PyXPCOM_TypeObject *pBaseType,
+ int typeSize,
+ struct PyMethodDef* methodList,
+ PyXPCOM_I_CTOR ctor);
+ ~PyXPCOM_TypeObject();
+
+ PyMethodChain chain;
+ PyXPCOM_TypeObject *baseType;
+ PyXPCOM_I_CTOR ctor;
+
+ static PRBool IsType(PyTypeObject *t);
+ // Static methods for the Python type.
+ static void Py_dealloc(PyObject *ob);
+ static PyObject *Py_repr(PyObject *ob);
+ static PyObject *Py_str(PyObject *ob);
+ static PyObject *Py_getattr(PyObject *self, char *name);
+ static int Py_setattr(PyObject *op, char *name, PyObject *v);
+ static int Py_cmp(PyObject *ob1, PyObject *ob2);
+ static PyObject *Py_richcmp(PyObject *ob1, PyObject *ob2, int op);
+#if PY_VERSION_HEX >= 0x03020000
+ static Py_hash_t Py_hash(PyObject *self);
+#else
+ static long Py_hash(PyObject *self);
+#endif
+#ifdef Py_LIMITED_API
+ PyTypeObject *m_pTypeObj; /**< The python type object we wrap. */
+#endif
+};
+
+//////////////////////////////////////////////////////////////////////////
+// class Py_nsISupports
+// This class serves 2 purposes:
+// * It is a base class for other interfaces we support "natively"
+// * It is instantiated for _all_ other interfaces.
+//
+// This is different than win32com, where a PyIUnknown only
+// ever holds an IUnknown - but here, we could be holding
+// _any_ interface.
+class PYXPCOM_EXPORT Py_nsISupports : public PyObject
+{
+public:
+ // Check if a Python object can safely be cast to an Py_nsISupports,
+ // and optionally check that the object is wrapping the specified
+ // interface.
+ static PRBool Check( PyObject *ob, const nsIID &checkIID = Py_nsIID_NULL) {
+ Py_nsISupports *self = static_cast<Py_nsISupports *>(ob);
+ if (ob==NULL || !PyXPCOM_TypeObject::IsType(ob->ob_type ))
+ return PR_FALSE;
+ if (!checkIID.Equals(Py_nsIID_NULL))
+ return self->m_iid.Equals(checkIID) != 0;
+ return PR_TRUE;
+ }
+ // Get the nsISupports interface from the PyObject WITH NO REF COUNT ADDED
+ static nsISupports *GetI(PyObject *self, nsIID *ret_iid = NULL);
+ nsCOMPtr<nsISupports> m_obj;
+ nsIID m_iid;
+#ifdef Py_LIMITED_API
+ /** Because PyXPCOM_TypeObject cannot inherit from PyTypeObject in
+ * Py_LIMITED_API mode, we cannot use ob_type to get to the method list.
+ * Instead of we store it here. */
+ PyXPCOM_TypeObject *m_pMyTypeObj;
+#endif
+
+ // Given an nsISupports and an Interface ID, create and return an object
+ // Does not QI the object - the caller must ensure the nsISupports object
+ // is really a pointer to an object identified by the IID (although
+ // debug builds should check this)
+ // PRBool bMakeNicePyObject indicates if we should call back into
+ // Python to wrap the object. This allows Python code to
+ // see the correct xpcom.client.Interface object even when calling
+ // xpcom functions directly from C++.
+ // NOTE: There used to be a bAddRef param to this as an internal
+ // optimization, but since removed. This function *always* takes a
+ // reference to the nsISupports.
+ static PyObject *PyObjectFromInterface(nsISupports *ps,
+ const nsIID &iid,
+ PRBool bMakeNicePyObject = PR_TRUE,
+ PRBool bIsInternalCall = PR_FALSE);
+
+ // Given a Python object that is a registered COM type, return a given
+ // interface pointer on its underlying object, with a NEW REFERENCE ADDED.
+ // bTryAutoWrap indicates if a Python instance object should attempt to
+ // be automatically wrapped in an XPCOM object. This is really only
+ // provided to stop accidental recursion should the object returned by
+ // the wrap process itself be in instance (where it should already be
+ // a COM object.
+ // If |iid|==nsIVariant, then arbitary Python objects will be wrapped
+ // in an nsIVariant.
+ static PRBool InterfaceFromPyObject(
+ PyObject *ob,
+ const nsIID &iid,
+ nsISupports **ppret,
+ PRBool bNoneOK,
+ PRBool bTryAutoWrap = PR_TRUE);
+
+ // Given a Py_nsISupports, return an interface.
+ // Object *must* be Py_nsISupports - there is no
+ // "autowrap", no "None" support, etc
+ static PRBool InterfaceFromPyISupports(PyObject *ob,
+ const nsIID &iid,
+ nsISupports **ppv);
+
+ static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid);
+ // The Python methods
+ static PyObject *QueryInterface(PyObject *self, PyObject *args);
+
+ // Internal (sort-of) objects.
+ static NS_EXPORT_STATIC_MEMBER_(PyXPCOM_TypeObject) *type;
+ static NS_EXPORT_STATIC_MEMBER_(PyMethodDef) methods[];
+ static PyObject *mapIIDToType;
+ static void SafeRelease(Py_nsISupports *ob);
+#ifndef Py_LIMITED_API
+ static void RegisterInterface( const nsIID &iid, PyTypeObject *t);
+#else
+ static void RegisterInterface( const nsIID &iid, PyXPCOM_TypeObject *t);
+#endif
+ static void InitType();
+#ifdef VBOX_DEBUG_LIFETIMES
+ static void dumpList(void);
+ static void dumpListToStdOut(void);
+#endif
+
+ virtual ~Py_nsISupports();
+ virtual PyObject *getattr(const char *name);
+ virtual int setattr(const char *name, PyObject *val);
+ // A virtual function to sub-classes can customize the way
+ // nsISupports objects are returned from their methods.
+ // ps is a new object just obtained from some operation performed on us
+ virtual PyObject *MakeInterfaceResult(nsISupports *ps, const nsIID &iid,
+ PRBool bMakeNicePyObject = PR_TRUE) {
+ return PyObjectFromInterface(ps, iid, bMakeNicePyObject);
+ }
+
+protected:
+ // ctor is protected - must create objects via
+ // PyObjectFromInterface()
+ Py_nsISupports(nsISupports *p,
+ const nsIID &iid,
+#ifndef Py_LIMITED_API
+ PyTypeObject *type);
+#else
+ PyXPCOM_TypeObject *type);
+#endif
+
+ // Make a default wrapper for an ISupports (which is an
+ // xpcom.client.Component instance)
+ static PyObject *MakeDefaultWrapper(PyObject *pyis, const nsIID &iid);
+
+#ifdef VBOX_DEBUG_LIFETIMES
+ static DECLCALLBACK(int32_t) initOnceCallback(void *pvUser1);
+
+ RTLISTNODE m_ListEntry; /**< List entry. */
+
+ static RTONCE g_Once; /**< Init list and critsect once. */
+ static RTCRITSECT g_CritSect; /**< Critsect protecting the list. */
+ static RTLISTANCHOR g_List; /**< List of live interfaces.*/
+#endif
+};
+
+// Python/XPCOM IID support
+class PYXPCOM_EXPORT Py_nsIID : public PyObject
+{
+public:
+ Py_nsIID(const nsIID &riid);
+ nsIID m_iid;
+
+ PRBool
+ IsEqual(const nsIID &riid) {
+ return m_iid.Equals(riid);
+ }
+
+ PRBool
+ IsEqual(PyObject *ob) {
+ return ob &&
+#ifndef Py_LIMITED_API
+ ob->ob_type== &type &&
+#else
+ ob->ob_type == s_pType &&
+#endif
+ m_iid.Equals(((Py_nsIID *)ob)->m_iid);
+ }
+
+ PRBool
+ IsEqual(Py_nsIID &iid) {
+ return m_iid.Equals(iid.m_iid);
+ }
+
+ static PyObject *
+ PyObjectFromIID(const nsIID &iid) {
+ return new Py_nsIID(iid);
+ }
+
+ static PRBool IIDFromPyObject(PyObject *ob, nsIID *pRet);
+ /* Python support */
+ static PyObject *PyTypeMethod_getattr(PyObject *self, char *name);
+#if PY_MAJOR_VERSION <= 2
+ static int PyTypeMethod_compare(PyObject *self, PyObject *ob);
+#endif
+ static PyObject *PyTypeMethod_richcompare(PyObject *self, PyObject *ob, int op);
+ static PyObject *PyTypeMethod_repr(PyObject *self);
+#if PY_VERSION_HEX >= 0x03020000
+ static Py_hash_t PyTypeMethod_hash(PyObject *self);
+#else
+ static long PyTypeMethod_hash(PyObject *self);
+#endif
+ static PyObject *PyTypeMethod_str(PyObject *self);
+ static void PyTypeMethod_dealloc(PyObject *self);
+#ifndef Py_LIMITED_API
+ static NS_EXPORT_STATIC_MEMBER_(PyTypeObject) type;
+#else
+ static NS_EXPORT_STATIC_MEMBER_(PyTypeObject *) s_pType;
+ static PyTypeObject *GetTypeObject(void);
+#endif
+ static NS_EXPORT_STATIC_MEMBER_(PyMethodDef) methods[];
+};
+
+///////////////////////////////////////////////////////
+//
+// Helper classes for managing arrays of variants.
+class PythonTypeDescriptor; // Forward declare.
+
+class PYXPCOM_EXPORT PyXPCOM_InterfaceVariantHelper {
+public:
+ PyXPCOM_InterfaceVariantHelper(Py_nsISupports *parent, int methodindex);
+ ~PyXPCOM_InterfaceVariantHelper();
+ PRBool Init(PyObject *obParams);
+ PRBool FillArray();
+
+ PyObject *MakePythonResult();
+
+ nsXPTCVariant *m_var_array;
+ int m_num_array;
+ int m_methodindex;
+protected:
+ PyObject *MakeSinglePythonResult(int index);
+ PRBool FillInVariant(const PythonTypeDescriptor &, int, int);
+ PRBool PrepareOutVariant(const PythonTypeDescriptor &td, int value_index);
+ PRBool SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size);
+ PRUint32 GetSizeIs( int var_index, PRBool is_arg1);
+
+ PyObject *m_pyparams; // sequence of actual params passed (ie, not including hidden)
+ PyObject *m_typedescs; // desc of _all_ params, including hidden.
+ PythonTypeDescriptor *m_python_type_desc_array;
+ void **m_buffer_array;
+ Py_nsISupports *m_parent;
+
+};
+
+/*************************************************************************
+**************************************************************************
+
+ Support for IMPLEMENTING interfaces.
+
+**************************************************************************
+*************************************************************************/
+#define NS_IINTERNALPYTHON_IID_STR "AC7459FC-E8AB-4f2e-9C4F-ADDC53393A20"
+#define NS_IINTERNALPYTHON_IID \
+ { 0xac7459fc, 0xe8ab, 0x4f2e, { 0x9c, 0x4f, 0xad, 0xdc, 0x53, 0x39, 0x3a, 0x20 } }
+
+class PyXPCOM_GatewayWeakReference;
+
+// This interface is needed primarily to give us a known vtable base.
+// If we QI a Python object for this interface, we can safely cast the result
+// to a PyG_Base. Any other interface, we do now know which vtable we will get.
+// We also allow the underlying PyObject to be extracted
+class nsIInternalPython : public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IINTERNALPYTHON_IID)
+ // Get the underlying Python object with new reference added
+ virtual PyObject *UnwrapPythonObject(void) = 0;
+};
+
+// This is roughly equivalent to PyGatewayBase in win32com
+//
+class PYXPCOM_EXPORT PyG_Base : public nsIInternalPython, public nsISupportsWeakReference
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSWEAKREFERENCE
+ PyObject *UnwrapPythonObject(void);
+
+ // A static "constructor" - the real ctor is protected.
+ static nsresult CreateNew(PyObject *pPyInstance,
+ const nsIID &iid,
+ void **ppResult);
+
+ // A utility to auto-wrap an arbitary Python instance
+ // in a COM gateway.
+ static PRBool AutoWrapPythonInstance(PyObject *ob,
+ const nsIID &iid,
+ nsISupports **ppret);
+
+
+ // A helper that creates objects to be passed for nsISupports
+ // objects. See extensive comments in PyG_Base.cpp.
+ PyObject *MakeInterfaceParam(nsISupports *pis,
+ const nsIID *piid,
+ int methodIndex = -1,
+ const XPTParamDescriptor *d = NULL,
+ int paramIndex = -1);
+
+ // A helper that ensures all casting and vtable offsetting etc
+ // done against this object happens in the one spot!
+ virtual void *ThisAsIID( const nsIID &iid ) = 0;
+
+ // Helpers for "native" interfaces.
+ // Not used by the generic stub interface.
+ nsresult HandleNativeGatewayError(const char *szMethodName);
+
+ // These data members used by the converter helper functions - hence public
+ nsIID m_iid;
+ PyObject * m_pPyObject;
+ // We keep a reference count on this object, and the object
+ // itself uses normal refcount rules - thus, it will only
+ // die when we die, and all external references are removed.
+ // This means that once we have created it (and while we
+ // are alive) it will never die.
+ nsCOMPtr<nsIWeakReference> m_pWeakRef;
+#ifdef NS_BUILD_REFCNT_LOGGING
+ char refcntLogRepr[64]; // sigh - I wish I knew how to use the Moz string classes :( OK for debug only tho.
+#endif
+protected:
+ PyG_Base(PyObject *instance, const nsIID &iid);
+ virtual ~PyG_Base();
+ PyG_Base *m_pBaseObject; // A chain to implement identity rules.
+ nsresult InvokeNativeViaPolicy( const char *szMethodName,
+ PyObject **ppResult = NULL,
+ const char *szFormat = NULL,
+ ...
+ );
+ nsresult InvokeNativeViaPolicyInternal( const char *szMethodName,
+ PyObject **ppResult,
+ const char *szFormat,
+ va_list va);
+ nsresult InvokeNativeGetViaPolicy(const char *szPropertyName,
+ PyObject **ppResult = NULL
+ );
+ nsresult InvokeNativeSetViaPolicy(const char *szPropertyName,
+ ...);
+};
+
+class PYXPCOM_EXPORT PyXPCOM_XPTStub : public PyG_Base, public nsXPTCStubBase
+{
+friend class PyG_Base;
+public:
+ NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) \
+ {return PyG_Base::QueryInterface(aIID, aInstancePtr);} \
+ NS_IMETHOD_(nsrefcnt) AddRef(void) {return PyG_Base::AddRef();} \
+ NS_IMETHOD_(nsrefcnt) Release(void) {return PyG_Base::Release();} \
+
+ NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info);
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant* params);
+
+ virtual void *ThisAsIID(const nsIID &iid);
+protected:
+ PyXPCOM_XPTStub(PyObject *instance, const nsIID &iid) : PyG_Base(instance, iid) {;}
+private:
+};
+
+// For the Gateways we manually implement.
+#define PYGATEWAY_BASE_SUPPORT(INTERFACE, GATEWAY_BASE) \
+ NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) \
+ {return PyG_Base::QueryInterface(aIID, aInstancePtr);} \
+ NS_IMETHOD_(nsrefcnt) AddRef(void) {return PyG_Base::AddRef();} \
+ NS_IMETHOD_(nsrefcnt) Release(void) {return PyG_Base::Release();} \
+ virtual void *ThisAsIID(const nsIID &iid) { \
+ if (iid.Equals(NS_GET_IID(INTERFACE))) return (INTERFACE *)this; \
+ return GATEWAY_BASE::ThisAsIID(iid); \
+ } \
+
+extern PYXPCOM_EXPORT void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
+
+extern PYXPCOM_EXPORT PRInt32 _PyXPCOM_GetGatewayCount(void);
+extern PYXPCOM_EXPORT PRInt32 _PyXPCOM_GetInterfaceCount(void);
+#ifdef VBOX_DEBUG_LIFETIMES
+extern PYXPCOM_EXPORT PRInt32 _PyXPCOM_DumpInterfaces(void);
+#endif
+
+
+// Weak Reference class. This is a true COM object, representing
+// a weak reference to a Python object. For each Python XPCOM object,
+// there is exactly zero or one corresponding weak reference instance.
+// When both are alive, each holds a pointer to the other. When the main
+// object dies due to XPCOM reference counting, it zaps the pointer
+// in its corresponding weak reference object. Thus, the weak-reference
+// can live beyond the object (possibly with a NULL pointer back to the
+// "real" object, but as implemented, the weak reference will never be
+// destroyed before the object
+class PYXPCOM_EXPORT PyXPCOM_GatewayWeakReference : public nsIWeakReference {
+public:
+ PyXPCOM_GatewayWeakReference(PyG_Base *base);
+ virtual ~PyXPCOM_GatewayWeakReference();
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIWEAKREFERENCE
+ PyG_Base *m_pBase; // NO REF COUNT!!!
+#ifdef NS_BUILD_REFCNT_LOGGING
+ char refcntLogRepr[41];
+#endif
+};
+
+
+// Helpers classes for our gateways.
+class PYXPCOM_EXPORT PyXPCOM_GatewayVariantHelper
+{
+public:
+ PyXPCOM_GatewayVariantHelper( PyG_Base *gateway,
+ int methodIndex,
+ const nsXPTMethodInfo *info,
+ nsXPTCMiniVariant* params );
+ ~PyXPCOM_GatewayVariantHelper();
+ PyObject *MakePyArgs();
+ nsresult ProcessPythonResult(PyObject *ob);
+ PyG_Base *m_gateway;
+private:
+ nsresult BackFillVariant( PyObject *ob, int index);
+ PyObject *MakeSingleParam(int index, PythonTypeDescriptor &td);
+ PRBool GetIIDForINTERFACE_ID(int index, const nsIID **ppret);
+ nsresult GetArrayType(PRUint8 index, PRUint8 *ret, nsIID **ppiid);
+ PRUint32 GetSizeIs( int var_index, PRBool is_arg1);
+ PRBool SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size);
+ PRBool CanSetSizeIs( int var_index, PRBool is_arg1 );
+ nsIInterfaceInfo *GetInterfaceInfo(); // NOTE: no ref count on result.
+
+
+ nsXPTCMiniVariant* m_params;
+ const nsXPTMethodInfo *m_info;
+ int m_method_index;
+ PythonTypeDescriptor *m_python_type_desc_array;
+ int m_num_type_descs;
+ nsCOMPtr<nsIInterfaceInfo> m_interface_info;
+};
+
+// Misc converters.
+PyObject *PyObject_FromXPTType( const nsXPTType *d);
+// XPTTypeDescriptor derived from XPTType - latter is automatically processed via PyObject_FromXPTTypeDescriptor XPTTypeDescriptor
+PyObject *PyObject_FromXPTTypeDescriptor( const XPTTypeDescriptor *d);
+
+PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d);
+PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d);
+PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *d);
+
+// DLL reference counting functions.
+// Although we maintain the count, we never actually
+// finalize Python when it hits zero!
+void PyXPCOM_DLLAddRef();
+void PyXPCOM_DLLRelease();
+
+/*************************************************************************
+**************************************************************************
+
+ LOCKING AND THREADING
+
+**************************************************************************
+*************************************************************************/
+
+//
+// We have 2 discrete locks in use (when no free-threaded is used, anyway).
+// The first type of lock is the global Python lock. This is the standard lock
+// in use by Python, and must be used as documented by Python. Specifically, no
+// 2 threads may _ever_ call _any_ Python code (including INCREF/DECREF) without
+// first having this thread lock.
+//
+// The second type of lock is a "global framework lock", and used whenever 2 threads
+// of C code need access to global data. This is different than the Python
+// lock - this lock is used when no Python code can ever be called by the
+// threads, but the C code still needs thread-safety.
+
+// We also supply helper classes which make the usage of these locks a one-liner.
+
+// The "framework" lock, implemented as a PRLock
+PYXPCOM_EXPORT void PyXPCOM_AcquireGlobalLock(void);
+PYXPCOM_EXPORT void PyXPCOM_ReleaseGlobalLock(void);
+
+// Helper class for the DLL global lock.
+//
+// This class magically waits for PyXPCOM framework global lock, and releases it
+// when finished.
+// NEVER new one of these objects - only use on the stack!
+class CEnterLeaveXPCOMFramework {
+public:
+ CEnterLeaveXPCOMFramework() {PyXPCOM_AcquireGlobalLock();}
+ ~CEnterLeaveXPCOMFramework() {PyXPCOM_ReleaseGlobalLock();}
+};
+
+// Python thread-lock stuff. Free-threading patches use different semantics, but
+// these are abstracted away here...
+//#include <threadstate.h>
+
+// Helper class for Enter/Leave Python
+//
+// This class magically waits for the Python global lock, and releases it
+// when finished.
+
+// Nested invocations will deadlock, so be careful.
+
+// NEVER new one of these objects - only use on the stack!
+
+PYXPCOM_EXPORT void PyXPCOM_MakePendingCalls();
+PYXPCOM_EXPORT PRBool PyXPCOM_Globals_Ensure();
+
+// For 2.3, use the PyGILState_ calls
+#if (PY_VERSION_HEX >= 0x02030000)
+#define PYXPCOM_USE_PYGILSTATE
+#endif
+
+#ifdef PYXPCOM_USE_PYGILSTATE
+class CEnterLeavePython {
+public:
+ CEnterLeavePython() {
+ state = PyGILState_Ensure();
+ // See "pending calls" comment below. We reach into the Python
+ // implementation to see if we are the first call on the stack.
+# ifndef Py_LIMITED_API
+ if (PyThreadState_Get()->gilstate_counter==1) {
+# else
+ if (state == PyGILState_UNLOCKED) {
+# endif
+ PyXPCOM_MakePendingCalls();
+ }
+ }
+ ~CEnterLeavePython() {
+ PyGILState_Release(state);
+ }
+ PyGILState_STATE state;
+};
+#else
+
+extern PYXPCOM_EXPORT PyInterpreterState *PyXPCOM_InterpreterState;
+PYXPCOM_EXPORT PRBool PyXPCOM_ThreadState_Ensure();
+PYXPCOM_EXPORT void PyXPCOM_ThreadState_Free();
+PYXPCOM_EXPORT void PyXPCOM_ThreadState_Clear();
+PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Acquire();
+PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Release();
+
+// Pre 2.3 thread-state dances.
+class CEnterLeavePython {
+public:
+ CEnterLeavePython() {
+ created = PyXPCOM_ThreadState_Ensure();
+ PyXPCOM_InterpreterLock_Acquire();
+ if (created) {
+ // If pending python calls are waiting as we enter Python,
+ // it will generally mean an asynch signal handler, etc.
+ // We can either call it here, or wait for Python to call it
+ // as part of its "even 'n' opcodes" check. If we wait for
+ // Python to check it and the pending call raises an exception,
+ // then it is _our_ code that will fail - this is unfair,
+ // as the signal was raised before we were entered - indeed,
+ // we may be directly responding to the signal!
+ // Thus, we flush all the pending calls here, and report any
+ // exceptions via our normal exception reporting mechanism.
+ // We can then execute our code in the knowledge that only
+ // signals raised _while_ we are executing will cause exceptions.
+ PyXPCOM_MakePendingCalls();
+ }
+ }
+ ~CEnterLeavePython() {
+ // The interpreter state must be cleared
+ // _before_ we release the lock, as some of
+ // the sys. attributes cleared (eg, the current exception)
+ // may need the lock to invoke their destructors -
+ // specifically, when exc_value is a class instance, and
+ // the exception holds the last reference!
+ if ( created )
+ PyXPCOM_ThreadState_Clear();
+ PyXPCOM_InterpreterLock_Release();
+ if ( created )
+ PyXPCOM_ThreadState_Free();
+ }
+private:
+ PRBool created;
+};
+#endif // PYXPCOM_USE_PYGILSTATE
+
+// Our classes.
+// Hrm - So we can't have templates, eh??
+// preprocessor to the rescue, I guess.
+#define PyXPCOM_INTERFACE_DECLARE(ClassName, InterfaceName, Methods ) \
+ \
+extern struct PyMethodDef Methods[]; \
+ \
+class ClassName : public Py_nsISupports \
+{ \
+public: \
+ static PYXPCOM_EXPORT PyXPCOM_TypeObject *type; \
+ static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid) { \
+ return new ClassName(pInitObj, iid); \
+ } \
+ static void InitType() { \
+ type = new PyXPCOM_TypeObject( \
+ #InterfaceName, \
+ Py_nsISupports::type, \
+ sizeof(ClassName), \
+ Methods, \
+ Constructor); \
+ const nsIID &iid = NS_GET_IID(InterfaceName); \
+ RegisterInterface(iid, type); \
+ } \
+protected: \
+ ClassName(nsISupports *p, const nsIID &iid) : \
+ Py_nsISupports(p, iid, type) { \
+ /* The IID _must_ be the IID of the interface we are wrapping! */ \
+ NS_ABORT_IF_FALSE(iid.Equals(NS_GET_IID(InterfaceName)), "Bad IID"); \
+ } \
+}; \
+ \
+// End of PyXPCOM_INTERFACE_DECLARE macro
+
+#define PyXPCOM_ATTR_INTERFACE_DECLARE(ClassName, InterfaceName, Methods )\
+ \
+extern struct PyMethodDef Methods[]; \
+ \
+class ClassName : public Py_nsISupports \
+{ \
+public: \
+ static PyXPCOM_TypeObject *type; \
+ static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid) { \
+ return new ClassName(pInitObj, iid); \
+ } \
+ static void InitType() { \
+ type = new PyXPCOM_TypeObject( \
+ #InterfaceName, \
+ Py_nsISupports::type, \
+ sizeof(ClassName), \
+ Methods, \
+ Constructor); \
+ const nsIID &iid = NS_GET_IID(InterfaceName); \
+ RegisterInterface(iid, type); \
+} \
+ virtual PyObject *getattr(const char *name); \
+ virtual int setattr(const char *name, PyObject *val); \
+protected: \
+ ClassName(nsISupports *p, const nsIID &iid) : \
+ Py_nsISupports(p, iid, type) { \
+ /* The IID _must_ be the IID of the interface we are wrapping! */ \
+ NS_ABORT_IF_FALSE(iid.Equals(NS_GET_IID(InterfaceName)), "Bad IID"); \
+ } \
+}; \
+ \
+// End of PyXPCOM_ATTR_INTERFACE_DECLARE macro
+
+#define PyXPCOM_INTERFACE_DEFINE(ClassName, InterfaceName, Methods ) \
+PyXPCOM_TypeObject *ClassName::type = NULL;
+
+
+// And the classes
+PyXPCOM_INTERFACE_DECLARE(Py_nsIComponentManager, nsIComponentManager, PyMethods_IComponentManager)
+PyXPCOM_INTERFACE_DECLARE(Py_nsIInterfaceInfoManager, nsIInterfaceInfoManager, PyMethods_IInterfaceInfoManager)
+PyXPCOM_INTERFACE_DECLARE(Py_nsIEnumerator, nsIEnumerator, PyMethods_IEnumerator)
+PyXPCOM_INTERFACE_DECLARE(Py_nsISimpleEnumerator, nsISimpleEnumerator, PyMethods_ISimpleEnumerator)
+PyXPCOM_INTERFACE_DECLARE(Py_nsIInterfaceInfo, nsIInterfaceInfo, PyMethods_IInterfaceInfo)
+PyXPCOM_INTERFACE_DECLARE(Py_nsIInputStream, nsIInputStream, PyMethods_IInputStream)
+PyXPCOM_ATTR_INTERFACE_DECLARE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassInfo)
+PyXPCOM_ATTR_INTERFACE_DECLARE(Py_nsIVariant, nsIVariant, PyMethods_IVariant)
+// deprecated, but retained for backward compatibility:
+PyXPCOM_INTERFACE_DECLARE(Py_nsIComponentManagerObsolete, nsIComponentManagerObsolete, PyMethods_IComponentManagerObsolete)
+#endif // __PYXPCOM_H__
diff --git a/src/libs/xpcom18a4/python/src/PyXPCOM_std.h b/src/libs/xpcom18a4/python/src/PyXPCOM_std.h
new file mode 100644
index 00000000..b7b7ff8c
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyXPCOM_std.h
@@ -0,0 +1,56 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// standard include - sets up all the defines used by
+// the mozilla make process - too lazy to work out how to integrate
+// with their make, so this will do!
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+// This header is considered internal - hence
+// we can use it to trigger "exports"
+#define BUILD_PYXPCOM
+
+#include "PyXPCOM.h"
diff --git a/src/libs/xpcom18a4/python/src/Pyxpt_info.cpp b/src/libs/xpcom18a4/python/src/Pyxpt_info.cpp
new file mode 100644
index 00000000..d1df54fe
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/Pyxpt_info.cpp
@@ -0,0 +1,197 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Pyxpt_info.cpp - wrappers for the xpt_info objects.
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+#include "PyXPCOM_std.h"
+
+PyObject *PyObject_FromXPTType( const nsXPTType *d)
+{
+ if (d==nsnull) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ // build an object using the same format as a TypeDescriptor.
+ return Py_BuildValue("bzzz",
+ d->flags,
+ NULL, NULL, NULL);
+}
+
+PyObject *PyObject_FromXPTTypeDescriptor( const XPTTypeDescriptor *d)
+{
+ if (d==nsnull) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return Py_BuildValue("bbbh",
+ d->prefix.flags,
+ d->argnum,
+ d->argnum2,
+ d->type.iface // this is actually a union!
+ );
+}
+
+PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d)
+{
+ if (d==nsnull) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ PyObject *ob = PyObject_FromXPTTypeDescriptor(&d->type);
+ PyObject *ret = Py_BuildValue("bO", d->flags, ob);
+ Py_DECREF(ob);
+ return ret;
+}
+
+PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d)
+{
+ if (d==nsnull) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ PyObject *ob_params = PyTuple_New(d->num_args);
+ if (ob_params==NULL)
+ return NULL;
+ for (int i=0;i<d->num_args;i++)
+ PyTuple_SET_ITEM(ob_params, i, PyObject_FromXPTParamDescriptor(d->params+i));
+ PyObject *ob_ret = PyObject_FromXPTParamDescriptor(d->result);
+ PyObject *ret = Py_BuildValue("bsOO", d->flags, d->name, ob_params, ob_ret);
+ Py_XDECREF(ob_ret);
+ Py_XDECREF(ob_params);
+ return ret;
+}
+
+PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *c)
+{
+ if (c==nsnull) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ PyObject *ob_type = PyObject_FromXPTTypeDescriptor(&c->type);
+ if (ob_type==NULL)
+ return NULL;
+ PyObject *v = NULL;
+ switch (c->type.prefix.flags) {
+ case TD_INT8:
+ v = PyInt_FromLong( c->value.i8 );
+ break;
+ case TD_INT16:
+ v = PyInt_FromLong( c->value.i16 );
+ break;
+ case TD_INT32:
+ v = PyInt_FromLong( c->value.i32 );
+ break;
+ case TD_INT64:
+ v = PyLong_FromLongLong(c->value.i64);
+ break;
+ case TD_UINT8:
+ v = PyInt_FromLong( c->value.ui8 );
+ break;
+ case TD_UINT16:
+ v = PyInt_FromLong( c->value.ui16 );
+ break;
+ case TD_UINT32:
+ v = PyInt_FromLong( c->value.ui32 );
+ break;
+ case TD_UINT64:
+ v = PyLong_FromUnsignedLongLong(c->value.ui64);
+ break;
+ case TD_FLOAT:
+ v = PyFloat_FromDouble(c->value.flt);
+ break;
+ case TD_DOUBLE:
+ v = PyFloat_FromDouble(c->value.dbl);
+ break;
+ case TD_BOOL:
+ v = c->value.bul ? Py_True : Py_False;
+ Py_INCREF(v);
+ break;
+ case TD_CHAR:
+#if PY_MAJOR_VERSION <= 2
+ v = PyString_FromStringAndSize(&c->value.ch, 1);
+#else
+ v = PyUnicode_FromStringAndSize(&c->value.ch, 1);
+#endif
+ break;
+ case TD_WCHAR:
+ v = PyObject_FromNSString((PRUnichar *)&c->value.wch, 1);
+ break;
+ // TD_VOID = 13,
+ case TD_PNSIID:
+ v = Py_nsIID::PyObjectFromIID(*c->value.iid);
+ break;
+ // TD_DOMSTRING = 15,
+ case TD_PSTRING:
+#if PY_MAJOR_VERSION <= 2
+ v = PyString_FromString(c->value.str);
+#else
+ v = PyUnicode_FromString(c->value.str);
+#endif
+ break;
+ case TD_PWSTRING:
+ v = PyObject_FromNSString((PRUnichar *)c->value.wstr, nsCRT::strlen((PRUnichar *)c->value.wstr));
+ break;
+ // TD_INTERFACE_TYPE = 18,
+ // TD_INTERFACE_IS_TYPE = 19,
+ // TD_ARRAY = 20,
+ // TD_PSTRING_SIZE_IS = 21,
+ // TD_PWSTRING_SIZE_IS = 22
+ // TD_UTF8STRING = 23,
+ // TD_CSTRING = 24,
+ // TD_ASTRING = 25
+ default:
+#if PY_MAJOR_VERSION <= 2
+ v = PyString_FromString("Unknown type code!!");
+#else
+ v = PyUnicode_FromString("Unknown type code!!");
+#endif
+ break;
+
+ }
+ PyObject *ret = Py_BuildValue("sbO", c->name, ob_type, v);
+ Py_DECREF(ob_type);
+ Py_DECREF(v);
+ return ret;
+}
diff --git a/src/libs/xpcom18a4/python/src/TypeObject.cpp b/src/libs/xpcom18a4/python/src/TypeObject.cpp
new file mode 100644
index 00000000..37cc13d7
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/TypeObject.cpp
@@ -0,0 +1,457 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIInterfaceInfoManager.h>
+#include <nsXPCOM.h>
+#include <nsISupportsPrimitives.h>
+
+#if defined(Py_LIMITED_API) && defined(RT_OS_LINUX)
+# include <features.h>
+# ifdef __GLIBC_PREREQ
+# if __GLIBC_PREREQ(2,9)
+# define PYXPCOM_HAVE_PIPE2
+# include <fcntl.h>
+# endif
+# endif
+#endif
+
+
+#ifndef Py_LIMITED_API
+static PyTypeObject PyInterfaceType_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "interface-type", /* Name of this type */
+ sizeof(PyTypeObject), /* Basic object size */
+ 0, /* Item size for varobject */
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ PyType_Type.tp_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ PyType_Type.tp_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /* tp_getattro */
+ 0, /*tp_setattro */
+ 0, /* tp_as_buffer */
+ 0, /* tp_flags */
+ "Define the behavior of a PythonCOM Interface type.",
+};
+
+#else /* Py_LIMITED_API */
+
+/** The offset of PyTypeObject::ob_name. */
+static size_t g_offObTypeNameMember = sizeof(PyVarObject);
+
+/**
+ * Base type object for XPCOM interfaces. Created dynamicially.
+ */
+static PyTypeObject *g_pPyInterfaceTypeObj = NULL;
+
+/**
+ * Gets the base XPCOM interface type object, creating it if needed.
+ */
+static PyTypeObject *PyXPCOM_CreateInterfaceType(void)
+{
+ static char g_szTypeDoc[] = "Define the behavior of a PythonCOM Interface type."; /* need non-const */
+ PyType_Slot aTypeSlots[] = {
+ { Py_tp_doc, g_szTypeDoc },
+ { 0, NULL } /* terminator */
+ };
+ static const char g_szClassNm[] = "interface-type";
+ PyType_Spec TypeSpec = {
+ /* .name: */ g_szClassNm,
+ /* .basicsize: */ 0,
+ /* .itemsize: */ 0,
+ /* .flags: */ Py_TPFLAGS_BASETYPE,
+ /* .slots: */ aTypeSlots,
+ };
+
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */
+
+ PyTypeObject *pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec);
+ assert(pTypeObj);
+
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+ g_pPyInterfaceTypeObj = pTypeObj;
+
+ /*
+ * Verify/correct g_offObTypeNameMember.
+ *
+ * Using pipe+write to probe the memory content, banking on the kernel
+ * to return EFAULT when we pass it an invalid address.
+ */
+ for (size_t off = sizeof(PyVarObject); off < sizeof(PyVarObject) + 64; off += sizeof(char *)) {
+ const char * const pszProbe = *(const char **)((uintptr_t)(pTypeObj) + off);
+ if (RT_VALID_PTR(pszProbe)) {
+ int fds[2] = { -1, -1 };
+# ifdef PYXPCOM_HAVE_PIPE2
+ int rc = pipe2(fds, O_CLOEXEC);
+# else
+ int rc = pipe(fds);
+# endif
+ if (rc)
+ break;
+
+ ssize_t cbWritten = write(fds[1], pszProbe, sizeof(g_szClassNm));
+ if (cbWritten == (ssize_t)sizeof(g_szClassNm)) {
+ char szReadBack[sizeof(g_szClassNm)];
+ ssize_t offRead = 0;
+ while (offRead < cbWritten) {
+ ssize_t cbRead = read(fds[0], &szReadBack[offRead], cbWritten - offRead);
+ if (cbRead >= 0) {
+ offRead += cbRead;
+ } else if (errno != EINTR)
+ break;
+ }
+ if ( cbWritten == offRead
+ && memcmp(szReadBack, g_szClassNm, sizeof(szReadBack)) == 0) {
+ g_offObTypeNameMember = off;
+ close(fds[0]);
+ close(fds[1]);
+ return pTypeObj;
+ }
+ }
+ close(fds[0]);
+ close(fds[1]);
+ }
+ }
+ assert(0);
+
+ return pTypeObj;
+}
+
+/**
+ * Gets the base XPCOM interface type object, creating it if needed.
+ */
+static PyTypeObject *PyXPCOM_GetInterfaceType(void)
+{
+ PyTypeObject *pTypeObj = g_pPyInterfaceTypeObj;
+ if (pTypeObj)
+ return pTypeObj;
+ return PyXPCOM_CreateInterfaceType();
+}
+
+/**
+ * Get the PyTypeObject::ob_name value.
+ *
+ * @todo This is _horrible_, but there appears to be no simple tp_name getter
+ * till https://bugs.python.org/issue31497 (2017 / 3.7.0). But even then
+ * it is not part of the limited API.
+ */
+const char *PyXPCOMGetObTypeName(PyTypeObject *pTypeObj)
+{
+ return *(const char **)((uintptr_t)(pTypeObj) + g_offObTypeNameMember);
+}
+
+#endif /* Py_LIMITED_API */
+
+/*static*/ PRBool
+PyXPCOM_TypeObject::IsType(PyTypeObject *t)
+{
+#if PY_MAJOR_VERSION <= 2
+ return t->ob_type == &PyInterfaceType_Type;
+#elif !defined(Py_LIMITED_API)
+ return Py_TYPE(t) == &PyInterfaceType_Type;
+#else
+ return Py_TYPE(t) == g_pPyInterfaceTypeObj /* Typically not the case as t->ob_type is &PyType_Type */
+ || PyType_IsSubtype(t, g_pPyInterfaceTypeObj); /* rather than g_pPyInterfaceTypeObj because of PyType_FromSpec(). */
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//
+// The type methods
+//
+/*static*/PyObject *
+PyXPCOM_TypeObject::Py_getattr(PyObject *self, char *name)
+{
+ return ((Py_nsISupports *)self)->getattr(name);
+}
+
+/*static*/int
+PyXPCOM_TypeObject::Py_setattr(PyObject *op, char *name, PyObject *v)
+{
+ return ((Py_nsISupports *)op)->setattr(name, v);
+}
+
+// @pymethod int|Py_nsISupports|__cmp__|Implements XPCOM rules for object identity.
+/*static*/int
+PyXPCOM_TypeObject::Py_cmp(PyObject *self, PyObject *other)
+{
+ // @comm NOTE: Copied from COM - have not confirmed these rules are true for XPCOM
+ // @comm As per the XPCOM rules for object identity, both objects are queried for nsISupports, and these values compared.
+ // The only meaningful test is for equality - the result of other comparisons is undefined
+ // (ie, determined by the object's relative addresses in memory.
+ nsISupports *pUnkOther;
+ nsISupports *pUnkThis;
+ if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE))
+ return -1;
+ if (!Py_nsISupports::InterfaceFromPyObject(other, NS_GET_IID(nsISupports), &pUnkOther, PR_FALSE)) {
+ pUnkThis->Release();
+ return -1;
+ }
+ int rc = pUnkThis==pUnkOther ? 0 :
+ (pUnkThis < pUnkOther ? -1 : 1);
+ pUnkThis->Release();
+ pUnkOther->Release();
+ return rc;
+}
+
+/*static*/PyObject *
+PyXPCOM_TypeObject::Py_richcmp(PyObject *self, PyObject *other, int op)
+{
+ PyObject *result = NULL;
+ int rc = Py_cmp(self, other);
+ switch (op)
+ {
+ case Py_LT:
+ result = rc < 0 ? Py_True : Py_False;
+ break;
+ case Py_LE:
+ result = rc <= 0 ? Py_True : Py_False;
+ break;
+ case Py_EQ:
+ result = rc == 0 ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ result = rc != 0 ? Py_True : Py_False;
+ break;
+ case Py_GT:
+ result = rc > 0 ? Py_True : Py_False;
+ break;
+ case Py_GE:
+ result = rc >= 0 ? Py_True : Py_False;
+ break;
+ }
+ Py_XINCREF(result);
+ return result;
+}
+
+// @pymethod int|Py_nsISupports|__hash__|Implement a hash-code for the XPCOM object using XPCOM identity rules.
+#if PY_VERSION_HEX >= 0x03020000
+/*static*/Py_hash_t PyXPCOM_TypeObject::Py_hash(PyObject *self)
+#else
+/*static*/long PyXPCOM_TypeObject::Py_hash(PyObject *self)
+#endif
+{
+ // We always return the value of the nsISupports *.
+ nsISupports *pUnkThis;
+ if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE))
+ return -1;
+#if PY_VERSION_HEX >= 0x03020000
+ Py_hash_t ret = _Py_HashPointer(pUnkThis);
+#else
+ long ret = _Py_HashPointer(pUnkThis);
+#endif
+ pUnkThis->Release();
+ return ret;
+}
+
+// @method string|Py_nsISupports|__repr__|Called to create a representation of a Py_nsISupports object
+/*static */PyObject *
+PyXPCOM_TypeObject::Py_repr(PyObject *self)
+{
+ // @comm The repr of this object displays both the object's address, and its attached nsISupports's address
+ Py_nsISupports *pis = (Py_nsISupports *)self;
+ // Try and get the IID name.
+ char *iid_repr = nsnull;
+ nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
+ NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+ if (iim!=nsnull)
+ iim->GetNameForIID(&pis->m_iid, &iid_repr);
+ if (iid_repr==nsnull)
+ // no IIM available, or it doesnt know the name.
+ iid_repr = pis->m_iid.ToString();
+ // XXX - need some sort of buffer overflow.
+ char buf[512];
+#ifdef VBOX
+ snprintf(buf, sizeof(buf), "<XPCOM object (%s) at %p/%p>",
+ iid_repr, (void *)self, (void *)pis->m_obj.get());
+#else
+ sprintf(buf, "<XPCOM object (%s) at 0x%p/0x%p>",
+ iid_repr, (void *)self, (void *)pis->m_obj.get());
+#endif
+ nsMemory::Free(iid_repr);
+#if PY_MAJOR_VERSION <= 2
+ return PyString_FromString(buf);
+#else
+ return PyUnicode_FromString(buf);
+#endif
+}
+
+/*static */PyObject *
+PyXPCOM_TypeObject::Py_str(PyObject *self)
+{
+ Py_nsISupports *pis = (Py_nsISupports *)self;
+ nsresult rv;
+ char *val = NULL;
+ Py_BEGIN_ALLOW_THREADS;
+ { // scope to kill pointer while thread-lock released.
+ nsCOMPtr<nsISupportsCString> ss( do_QueryInterface(pis->m_obj, &rv ));
+ if (NS_SUCCEEDED(rv))
+ rv = ss->ToString(&val);
+ } // end-scope
+ Py_END_ALLOW_THREADS;
+ PyObject *ret;
+ if (NS_FAILED(rv))
+ ret = Py_repr(self);
+ else
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromString(val);
+#else
+ ret = PyUnicode_FromString(val);
+#endif
+ if (val) nsMemory::Free(val);
+ return ret;
+}
+
+/* static */void
+PyXPCOM_TypeObject::Py_dealloc(PyObject *self)
+{
+ delete (Py_nsISupports *)self;
+}
+
+PyXPCOM_TypeObject::PyXPCOM_TypeObject( const char *name, PyXPCOM_TypeObject *pBase, int typeSize, struct PyMethodDef* methodList, PyXPCOM_I_CTOR thector)
+{
+#ifndef Py_LIMITED_API
+ static const PyTypeObject type_template = {
+ PyVarObject_HEAD_INIT(&PyInterfaceType_Type, 0)
+ "XPCOMTypeTemplate", /*tp_name*/
+ sizeof(Py_nsISupports), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ Py_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ Py_getattr, /* tp_getattr */
+ Py_setattr, /* tp_setattr */
+#if PY_MAJOR_VERSION <= 2
+ Py_cmp, /* tp_compare */
+#else
+ 0, /* reserved */
+#endif
+ Py_repr, /* tp_repr */
+ 0, /* tp_as_number*/
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ Py_hash, /* tp_hash */
+ 0, /* tp_call */
+ Py_str, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ 0, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ Py_richcmp, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ };
+
+ *((PyTypeObject *)this) = type_template;
+#else /* Py_LIMITED_API */
+ /* Create the type specs: */
+ PyType_Slot aTypeSlots[] = {
+ { Py_tp_base, PyXPCOM_GetInterfaceType() },
+ { Py_tp_dealloc, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_dealloc },
+ { Py_tp_getattr, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_getattr },
+ { Py_tp_setattr, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_setattr },
+ { Py_tp_repr, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_repr },
+ { Py_tp_hash, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_hash },
+ { Py_tp_str, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_str },
+ { Py_tp_richcompare, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_richcmp },
+ { 0, NULL } /* terminator */
+ };
+ PyType_Spec TypeSpec = {
+ /* .name: */ name,
+ /* .basicsize: */ typeSize,
+ /* .itemsize: */ 0,
+ /* .flags: */ Py_TPFLAGS_BASETYPE /*?*/,
+ /* .slots: */ aTypeSlots,
+ };
+
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */
+
+ m_pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec);
+ assert(m_pTypeObj);
+
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+
+ /* Initialize the PyObject part - needed so we can keep instance in a PyDict: */
+ ob_type = PyXPCOM_GetInterfaceType();
+ PyObject_Init(this, ob_type); /* VBox: Needed for 3.9 and up (also works on Python 2.7), includes _Py_NewReferences. @bugref{10079} */
+
+#endif /* Py_LIMITED_API */
+
+ chain.methods = methodList;
+ chain.link = pBase ? &pBase->chain : NULL;
+
+ baseType = pBase;
+ ctor = thector;
+
+#ifndef Py_LIMITED_API
+ // cast away const, as Python doesnt use it.
+ tp_name = (char *)name;
+ tp_basicsize = typeSize;
+#endif
+}
+
+PyXPCOM_TypeObject::~PyXPCOM_TypeObject()
+{
+}
+
diff --git a/src/libs/xpcom18a4/python/src/VariantUtils.cpp b/src/libs/xpcom18a4/python/src/VariantUtils.cpp
new file mode 100644
index 00000000..ac14a2cf
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/VariantUtils.cpp
@@ -0,0 +1,3112 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Unicode corrections by Shane Hathaway (http://hathawaymix.org),
+ * inspired by Mikhail Sobolev
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIInterfaceInfoManager.h>
+#include <nsAString.h>
+#include <nsString.h>
+#include <nsReadableUtils.h>
+
+// ------------------------------------------------------------------------
+// nsString utilities
+// ------------------------------------------------------------------------
+// one day we may know what they look like.
+inline
+PRBool
+IsNullDOMString( const nsAString& aString )
+{
+ return PR_FALSE;
+}
+
+inline
+PRBool
+IsNullDOMString( const nsACString& aString )
+{
+ return PR_FALSE;
+}
+
+#define PyUnicode_FromPRUnichar(src, size) \
+ PyUnicode_DecodeUTF16((char*)(src),sizeof(PRUnichar)*(size),NULL,NULL)
+
+// Create a zero-terminated PRUnichar buffer from a Python unicode.
+// On success, returns 0. On failure, returns -1 and sets an exception.
+// dest_out must not be null. size_out may be null.
+static int
+PyUnicode_AsPRUnichar(PyObject *obj, PRUnichar **dest_out, PRUint32 *size_out)
+{
+ PRUint32 size;
+ PyObject *s;
+ const void *src;
+ PRUnichar *dest;
+
+ s = PyUnicode_AsUTF16String(obj);
+ if (!s)
+ return -1;
+ // Drop the UTF-16 byte order mark at the beginning of
+ // the string. (See the docs on PyUnicode_AsUTF16String.)
+ // Some Mozilla libraries don't like the mark.
+#if PY_MAJOR_VERSION <= 2
+ size = (PyString_GET_SIZE(s) - 2) / sizeof(PRUnichar);
+ src = PyString_AS_STRING(s) + 2;
+#else
+ if (!PyBytes_Check(s)) {
+ PyErr_SetString(PyExc_TypeError, "internal error in PyXPCOM, parameter must be a bytes object");
+ return -1;
+ }
+ size = (PyBytes_GET_SIZE(s) - 2) / sizeof(PRUnichar);
+ src = PyBytes_AS_STRING(s) + 2;
+#endif
+ dest = (PRUnichar *)nsMemory::Alloc(sizeof(PRUnichar) * (size + 1));
+ if (!dest) {
+ PyErr_NoMemory();
+ Py_DECREF(s);
+ return -1;
+ }
+ memcpy(dest, src, sizeof(PRUnichar) * size);
+ Py_DECREF(s);
+ dest[size] = 0;
+ *dest_out = dest;
+ if (size_out)
+ *size_out = size;
+ return 0;
+}
+
+PyObject *PyObject_FromNSString( const nsACString &s, PRBool bAssumeUTF8 /*= PR_FALSE */)
+{
+ PyObject *ret;
+ if (IsNullDOMString(s)) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ if (bAssumeUTF8) {
+ const nsPromiseFlatCString& temp = PromiseFlatCString(s);
+ ret = PyUnicode_DecodeUTF8(temp.get(), temp.Length(), NULL);
+ } else {
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromStringAndSize(NULL, s.Length());
+#else
+ ret = PyUnicode_FromStringAndSize(NULL, s.Length());
+#endif
+ if (!ret)
+ return NULL;
+ // Need "CopyAsciiTo"!?
+ nsACString::const_iterator fromBegin, fromEnd;
+#if PY_MAJOR_VERSION <= 2
+ char* dest = (char *)PyString_AS_STRING(ret);
+#else
+ char* dest = (char *)PyUnicode_AsUTF8(ret);
+#endif
+ copy_string(s.BeginReading(fromBegin), s.EndReading(fromEnd), dest);
+ }
+ }
+ return ret;
+}
+
+PyObject *PyObject_FromNSString( const nsAString &s )
+{
+ PyObject *ret;
+ if (IsNullDOMString(s)) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ const nsPromiseFlatString& temp = PromiseFlatString(s);
+ ret = PyUnicode_FromPRUnichar(temp.get(), temp.Length());
+ }
+ return ret;
+}
+
+PyObject *PyObject_FromNSString( const PRUnichar *s,
+ PRUint32 len /* = (PRUint32)-1*/)
+{
+ return PyUnicode_FromPRUnichar(s,
+ len==((PRUint32)-1)? nsCRT::strlen(s) : len);
+}
+
+PRBool PyObject_AsNSString( PyObject *val, nsAString &aStr)
+{
+ if (val == Py_None) {
+ aStr.Truncate();
+ return NS_OK;
+ }
+ PyObject *val_use = NULL;
+ PRBool ok = PR_TRUE;
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ ok = PR_FALSE;
+ }
+ if (ok && (val_use = PyUnicode_FromObject(val))==NULL)
+ ok = PR_FALSE;
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ ok = PR_FALSE;
+ }
+ val_use = val;
+ Py_INCREF(val_use);
+#endif
+ if (ok) {
+ if (PyUnicode_GET_SIZE(val_use) == 0) {
+ aStr.Truncate();
+ }
+ else {
+ PRUint32 nch;
+ PRUnichar *tempo;
+ // can we do this without the copy?
+ if (PyUnicode_AsPRUnichar(val_use, &tempo, &nch) < 0)
+ return PR_FALSE;
+ aStr.Assign(tempo, nch);
+ nsMemory::Free(tempo);
+ }
+ }
+ Py_XDECREF(val_use);
+ return ok;
+}
+
+// Array utilities
+static PRUint32 GetArrayElementSize( PRUint8 t)
+{
+ PRUint32 ret;
+ switch (t & XPT_TDP_TAGMASK) {
+ case nsXPTType::T_U8:
+ case nsXPTType::T_I8:
+ ret = sizeof(PRInt8);
+ break;
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U16:
+ ret = sizeof(PRInt16);
+ break;
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U32:
+ ret = sizeof(PRInt32);
+ break;
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U64:
+ ret = sizeof(PRInt64);
+ break;
+ case nsXPTType::T_FLOAT:
+ ret = sizeof(float);
+ break;
+ case nsXPTType::T_DOUBLE:
+ ret = sizeof(double);
+ break;
+ case nsXPTType::T_BOOL:
+ ret = sizeof(PRBool);
+ break;
+ case nsXPTType::T_CHAR:
+ ret = sizeof(char);
+ break;
+ case nsXPTType::T_WCHAR:
+ ret = sizeof(PRUnichar);
+ break;
+ case nsXPTType::T_IID:
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_INTERFACE_IS:
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_CSTRING:
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_UTF8STRING:
+
+ ret = sizeof( void * );
+ break;
+ default:
+ NS_ABORT_IF_FALSE(0, "Unknown array type code!");
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static nsresult
+GetArrayElementIID(Py_nsISupports* self,
+ nsXPTCVariant* dispatchParams,
+ PRUint16 methodIndex,
+ PRUint8 paramIndex,
+ nsIID *result)
+{
+ nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
+ nsCOMPtr<nsIInterfaceInfo> ii;
+ nsresult rc;
+
+ rc = iim->GetInfoForIID(&self->m_iid, getter_AddRefs(ii));
+ if (NS_FAILED(rc))
+ return rc;
+
+
+ const nsXPTMethodInfo *mi;
+ rc = ii->GetMethodInfo(methodIndex, &mi);
+ if (NS_FAILED(rc))
+ return rc;
+
+ const nsXPTParamInfo& paramInfo = mi->GetParam(paramIndex);
+
+ if (!paramInfo.GetType().IsArray()) {
+ PyXPCOM_LogWarning("Passing non-array to GetArrayElementIID\n");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ nsXPTType elemType;
+ rc = ii->GetTypeForParam(methodIndex, &paramInfo, 1, &elemType);
+ if (NS_FAILED(rc))
+ return rc;
+
+ PRUint8 tag = elemType.TagPart();
+ if (tag == nsXPTType::T_INTERFACE)
+ {
+ rc = ii->GetIIDForParamNoAlloc(methodIndex, &paramInfo, result);
+ }
+ else if (tag == nsXPTType::T_INTERFACE_IS)
+ {
+ PyXPCOM_LogWarning("Unable to handle T_INTERFACE_IS yet\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+ else
+ {
+ // this may be valid case, for arrays of other types
+ // we don't need IID for
+ rc = NS_ERROR_INVALID_ARG;
+ }
+
+ return rc;
+}
+
+
+void FreeSingleArray(void *array_ptr, PRUint32 sequence_size, PRUint8 array_type)
+{
+ // Free each array element - NOT the array itself
+ // Thus, we only need to free arrays or pointers.
+ void **p = (void **)array_ptr;
+ PRUint32 i;
+ switch(array_type & XPT_TDP_TAGMASK) {
+ case nsXPTType::T_IID:
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ for (i=0; i<sequence_size; i++)
+ if (p[i]) nsMemory::Free(p[i]);
+ break;
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ for (i=0; i<sequence_size; i++)
+ if (p[i]) {
+ Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
+ ((nsISupports *)p[i])->Release();
+ Py_END_ALLOW_THREADS;
+ }
+ break;
+
+ // Ones we know need no deallocation
+ case nsXPTType::T_U8:
+ case nsXPTType::T_I8:
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U16:
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U32:
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U64:
+ case nsXPTType::T_FLOAT:
+ case nsXPTType::T_DOUBLE:
+ case nsXPTType::T_BOOL:
+ case nsXPTType::T_CHAR:
+ case nsXPTType::T_WCHAR:
+ break;
+
+ // And a warning should new type codes appear, as they may need deallocation.
+ default:
+ PyXPCOM_LogWarning("Deallocating unknown type %d (0x%x) - possible memory leak\n");
+ break;
+ }
+}
+
+#define FILL_SIMPLE_POINTER( type, val ) *((type *)pthis) = (type)(val)
+#define BREAK_FALSE {rc=PR_FALSE;break;}
+
+
+PRBool FillSingleArray(void *array_ptr, PyObject *sequence_ob, PRUint32 sequence_size,
+ PRUint32 array_element_size, PRUint8 array_type, nsIID *pIID)
+{
+ PRUint8 *pthis = (PRUint8 *)array_ptr;
+ NS_ABORT_IF_FALSE(pthis, "Don't have a valid array to fill!");
+ PRBool rc = PR_TRUE;
+ // We handle T_U8 specially as a string/Unicode.
+ // If it is NOT a string, we just fall through and allow the standard
+ // sequence unpack code process it (just slower!)
+#if PY_MAJOR_VERSION <= 2
+ if ( array_type == nsXPTType::T_U8 &&
+ (PyString_Check(sequence_ob) || PyUnicode_Check(sequence_ob))) {
+#else
+ if ( array_type == nsXPTType::T_U8 && PyUnicode_Check(sequence_ob)) {
+#endif
+
+ PRBool release_seq;
+ if (PyUnicode_Check(sequence_ob)) {
+ release_seq = PR_TRUE;
+#if PY_MAJOR_VERSION <= 2
+ sequence_ob = PyObject_Str(sequence_ob);
+#else
+ sequence_ob = PyUnicode_AsUTF8String(sequence_ob);
+#endif
+ } else
+ release_seq = PR_FALSE;
+ if (!sequence_ob) // presumably a memory error, or Unicode encoding error.
+ return PR_FALSE;
+#if PY_MAJOR_VERSION <= 2
+ memcpy(pthis, PyString_AS_STRING(sequence_ob), sequence_size);
+#else
+ memcpy(pthis, PyUnicode_AsUTF8(sequence_ob), sequence_size);
+#endif
+ if (release_seq)
+ {
+ Py_DECREF(sequence_ob);
+ }
+ return PR_TRUE;
+ }
+
+ for (PRUint32 i=0; rc && i<sequence_size; i++,pthis += array_element_size) {
+ PyObject *val = PySequence_GetItem(sequence_ob, i);
+ PyObject *val_use = NULL;
+ if (val==NULL)
+ return PR_FALSE;
+ switch(array_type) {
+ case nsXPTType::T_I8:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt8, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_I16:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt16, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_I32:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt32, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_I64:
+ if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt64, PyLong_AsLongLong(val_use) );
+ break;
+ case nsXPTType::T_U8:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint8, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_U16:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint16, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_U32:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint32, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_U64:
+ if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint64, PyLong_AsUnsignedLongLong(val_use) );
+ break;
+ case nsXPTType::T_FLOAT:
+ if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
+ FILL_SIMPLE_POINTER( float, PyFloat_AsDouble(val_use) );
+ break;
+ case nsXPTType::T_DOUBLE:
+ if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
+ FILL_SIMPLE_POINTER( double, PyFloat_AsDouble(val_use) );
+ break;
+ case nsXPTType::T_BOOL:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ FILL_SIMPLE_POINTER( PRBool, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_CHAR:
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+ FILL_SIMPLE_POINTER( char, *PyString_AS_STRING(val_use) );
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ FILL_SIMPLE_POINTER( char, *PyUnicode_AsUTF8(val) );
+#endif
+ break;
+
+ case nsXPTType::T_WCHAR:
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+#endif
+ if ((val_use = PyUnicode_FromObject(val)) == NULL)
+ BREAK_FALSE;
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+ // Lossy!
+#ifndef Py_LIMITED_API
+ FILL_SIMPLE_POINTER( PRUnichar, *PyUnicode_AS_UNICODE(val_use) );
+#else
+ FILL_SIMPLE_POINTER( PRUnichar, PyUnicode_ReadChar(val_use, 0) );
+#endif
+ break;
+
+ case nsXPTType::T_IID: {
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(val, &iid))
+ BREAK_FALSE;
+ nsIID **pp = (nsIID **)pthis;
+ // If there is an existing IID, free it.
+ if (*pp)
+ nsMemory::Free(*pp);
+ *pp = (nsIID *)nsMemory::Alloc(sizeof(nsIID));
+ if (*pp==NULL) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ memcpy(*pp, &iid, sizeof(iid));
+ break;
+ }
+
+ // case nsXPTType::T_BSTR:
+
+ case nsXPTType::T_CHAR_STR: {
+ // If it is an existing string, free it.
+ char **pp = (char **)pthis;
+ if (*pp)
+ nsMemory::Free(*pp);
+ *pp = nsnull;
+
+ if (val == Py_None)
+ break; // Remains NULL.
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+
+ const char *sz = PyString_AS_STRING(val_use);
+ int nch = PyString_GET_SIZE(val_use);
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_AsUTF8String(val))==NULL)
+ BREAK_FALSE;
+
+ const char *sz = PyBytes_AS_STRING(val_use);
+ int nch = PyBytes_GET_SIZE(val_use);
+#endif
+
+ *pp = (char *)nsMemory::Alloc(nch+1);
+ if (*pp==NULL) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ strncpy(*pp, sz, nch+1);
+ break;
+ }
+ case nsXPTType::T_WCHAR_STR: {
+ // If it is an existing string, free it.
+ PRUnichar **pp = (PRUnichar **)pthis;
+ if (*pp)
+ nsMemory::Free(*pp);
+ *pp = nsnull;
+ if (val == Py_None)
+ break; // Remains NULL.
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_FromObject(val))==NULL)
+ BREAK_FALSE;
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ val_use = val;
+ Py_INCREF(val_use);
+#endif
+ if (PyUnicode_AsPRUnichar(val_use, pp, NULL) < 0)
+ BREAK_FALSE;
+ break;
+ }
+ case nsXPTType::T_INTERFACE_IS: // hmm - ignoring the IID can't be good :(
+ case nsXPTType::T_INTERFACE: {
+ // We do allow NULL here, even tho doing so will no-doubt crash some objects.
+ // (but there will certainly be objects out there that will allow NULL :-(
+ nsISupports *pnew;
+ if (!Py_nsISupports::InterfaceFromPyObject(val, NS_GET_IID(nsISupports), &pnew, PR_TRUE))
+ BREAK_FALSE;
+ nsISupports **pp = (nsISupports **)pthis;
+ if (*pp) {
+ Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
+ (*pp)->Release();
+ Py_END_ALLOW_THREADS;
+ }
+ *pp = pnew; // ref-count added by InterfaceFromPyObject
+ break;
+ }
+ default:
+ // try and limp along in this case.
+ // leave rc TRUE
+ PyXPCOM_LogWarning("Converting Python object for an array element - The object type (0x%x) is unknown - leaving param alone!\n", array_type);
+ break;
+ }
+ Py_XDECREF(val_use);
+ Py_DECREF(val);
+ }
+ return rc;
+}
+
+static PyObject *UnpackSingleArray(Py_nsISupports *parent, void *array_ptr,
+ PRUint32 sequence_size, PRUint8 array_type, nsIID *iid)
+{
+ if (array_ptr==NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ if (array_type == nsXPTType::T_U8)
+#if PY_MAJOR_VERSION <= 2
+ return PyString_FromStringAndSize( (char *)array_ptr, sequence_size );
+#else
+ return PyBytes_FromStringAndSize( (char *)array_ptr, sequence_size );
+#endif
+
+ PRUint32 array_element_size = GetArrayElementSize(array_type);
+ PyObject *list_ret = PyList_New(sequence_size);
+ PRUint8 *pthis = (PRUint8 *)array_ptr;
+ for (PRUint32 i=0; i<sequence_size; i++,pthis += array_element_size) {
+ PyObject *val = NULL;
+ switch(array_type) {
+ case nsXPTType::T_I8:
+ val = PyInt_FromLong( *((PRInt8 *)pthis) );
+ break;
+ case nsXPTType::T_I16:
+ val = PyInt_FromLong( *((PRInt16 *)pthis) );
+ break;
+ case nsXPTType::T_I32:
+ val = PyInt_FromLong( *((PRInt32 *)pthis) );
+ break;
+ case nsXPTType::T_I64:
+ val = PyLong_FromLongLong( *((PRInt64 *)pthis) );
+ break;
+ // case nsXPTType::T_U8 - handled above!
+ case nsXPTType::T_U16:
+ val = PyInt_FromLong( *((PRUint16 *)pthis) );
+ break;
+ case nsXPTType::T_U32:
+ val = PyInt_FromLong( *((PRUint32 *)pthis) );
+ break;
+ case nsXPTType::T_U64:
+ val = PyLong_FromUnsignedLongLong( *((PRUint64 *)pthis) );
+ break;
+ case nsXPTType::T_FLOAT:
+ val = PyFloat_FromDouble( *((float*)pthis) );
+ break;
+ case nsXPTType::T_DOUBLE:
+ val = PyFloat_FromDouble( *((double*)pthis) );
+ break;
+ case nsXPTType::T_BOOL:
+ val = (*((PRBool *)pthis)) ? Py_True : Py_False;
+ Py_INCREF(val);
+ break;
+ case nsXPTType::T_IID:
+ val = Py_nsIID::PyObjectFromIID( **((nsIID **)pthis) );
+ break;
+
+ case nsXPTType::T_CHAR_STR: {
+ char **pp = (char **)pthis;
+ if (*pp==NULL) {
+ Py_INCREF(Py_None);
+ val = Py_None;
+ } else
+#if PY_MAJOR_VERSION <= 2
+ val = PyString_FromString(*pp);
+#else
+ val = PyUnicode_FromString(*pp);
+#endif
+ break;
+ }
+ case nsXPTType::T_WCHAR_STR: {
+ PRUnichar **pp = (PRUnichar **)pthis;
+ if (*pp==NULL) {
+ Py_INCREF(Py_None);
+ val = Py_None;
+ } else {
+ val = PyUnicode_FromPRUnichar( *pp, nsCRT::strlen(*pp) );
+ }
+ break;
+ }
+ case nsXPTType::T_INTERFACE_IS:
+ case nsXPTType::T_INTERFACE: {
+ nsISupports **pp = (nsISupports **)pthis;
+ // If we have an owning parent, let it create
+ // the object for us.
+ if (iid && iid->Equals(NS_GET_IID(nsIVariant)))
+ val = PyObject_FromVariant(parent, (nsIVariant *)*pp);
+ else if (parent)
+ val = parent->MakeInterfaceResult(*pp, iid ? *iid : NS_GET_IID(nsISupports));
+ else
+ val = Py_nsISupports::PyObjectFromInterface(
+ *pp,
+ iid ? *iid : NS_GET_IID(nsISupports),
+ PR_TRUE);
+ break;
+ }
+ default: {
+ char buf[128];
+ sprintf(buf, "Unknown XPCOM array type flags (0x%x)", array_type);
+ PyXPCOM_LogWarning("%s - returning a string object with this message!\n", buf);
+#if PY_MAJOR_VERSION <= 2
+ val = PyString_FromString(buf);
+#else
+ val = PyUnicode_FromString(buf);
+#endif
+ break;
+ }
+ }
+ if (val==NULL) {
+ NS_ABORT_IF_FALSE(PyErr_Occurred(), "NULL result in array conversion, but no error set!");
+ return NULL;
+ }
+ PyList_SET_ITEM(list_ret, i, val); // ref-count consumed.
+ }
+ return list_ret;
+}
+
+
+// ------------------------------------------------------------------------
+// nsIVariant utilities
+// ------------------------------------------------------------------------
+struct BVFTResult {
+ BVFTResult() {pis = NULL;iid=Py_nsIID_NULL;}
+ nsISupports *pis;
+ nsIID iid;
+};
+
+static PRUint16 BestVariantTypeForPyObject( PyObject *ob, BVFTResult *pdata = NULL)
+{
+ nsISupports *ps = NULL;
+ nsIID iid;
+ // start with some fast concrete checks.
+ if (ob==Py_None)
+ return nsIDataType::VTYPE_EMPTY;
+ if (ob==Py_True || ob == Py_False)
+ return nsIDataType::VTYPE_BOOL;
+ if (PyInt_Check(ob))
+ return nsIDataType::VTYPE_INT32;
+ if (PyLong_Check(ob))
+ return nsIDataType::VTYPE_INT64;
+ if (PyFloat_Check(ob))
+ return nsIDataType::VTYPE_DOUBLE;
+#if PY_MAJOR_VERSION <= 2
+ if (PyString_Check(ob))
+ return nsIDataType::VTYPE_STRING_SIZE_IS;
+#endif
+ if (PyUnicode_Check(ob))
+ return nsIDataType::VTYPE_WSTRING_SIZE_IS;
+ if (PyTuple_Check(ob) || PyList_Check(ob)) {
+ if (PySequence_Length(ob))
+ return nsIDataType::VTYPE_ARRAY;
+ return nsIDataType::VTYPE_EMPTY_ARRAY;
+ }
+ // Now do expensive or abstract checks.
+ if (Py_nsISupports::InterfaceFromPyObject(ob, NS_GET_IID(nsISupports), &ps, PR_TRUE)) {
+ if (pdata) {
+ pdata->pis = ps;
+ pdata->iid = NS_GET_IID(nsISupports);
+ } else
+ ps->Release();
+ return nsIDataType::VTYPE_INTERFACE_IS;
+ } else
+ PyErr_Clear();
+ if (Py_nsIID::IIDFromPyObject(ob, &iid)) {
+ if (pdata)
+ pdata->iid = iid;
+ return nsIDataType::VTYPE_ID;
+ } else
+ PyErr_Clear();
+ if (PySequence_Check(ob)) {
+ if (PySequence_Length(ob))
+ return nsIDataType::VTYPE_ARRAY;
+ return nsIDataType::VTYPE_EMPTY_ARRAY;
+ }
+ return (PRUint16)-1;
+}
+
+nsresult PyObject_AsVariant( PyObject *ob, nsIVariant **aRet)
+{
+ nsresult nr = NS_OK;
+ nsCOMPtr<nsIWritableVariant> v = do_CreateInstance("@mozilla.org/variant;1", &nr);
+ NS_ENSURE_SUCCESS(nr, nr);
+ // *sigh* - I tried the abstract API (PyNumber_Check, etc)
+ // but our COM instances too often qualify.
+ BVFTResult cvt_result;
+ PRUint16 dt = BestVariantTypeForPyObject(ob, &cvt_result);
+ switch (dt) {
+ case nsIDataType::VTYPE_BOOL:
+ nr = v->SetAsBool(ob==Py_True);
+ break;
+ case nsIDataType::VTYPE_INT32:
+ nr = v->SetAsInt32(PyInt_AsLong(ob));
+ break;
+ case nsIDataType::VTYPE_INT64:
+ nr = v->SetAsInt64(PyLong_AsLongLong(ob));
+ break;
+ case nsIDataType::VTYPE_DOUBLE:
+ nr = v->SetAsDouble(PyFloat_AsDouble(ob));
+ break;
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ {
+#if PY_MAJOR_VERSION <= 2
+ nr = v->SetAsStringWithSize(PyString_Size(ob), PyString_AsString(ob));
+#else
+ Py_ssize_t cb = 0;
+ const char *psz = PyUnicode_AsUTF8AndSize(ob, &cb);
+ nr = v->SetAsStringWithSize(cb, psz);
+#endif
+ break;
+ }
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+#if PY_VERSION_HEX >= 0x03030000
+ if (PyUnicode_GetLength(ob) == 0) {
+#else
+ if (PyUnicode_GetSize(ob) == 0) {
+#endif
+ nr = v->SetAsWStringWithSize(0, (PRUnichar*)NULL);
+ }
+ else {
+ PRUint32 nch;
+ PRUnichar *p;
+ if (PyUnicode_AsPRUnichar(ob, &p, &nch) < 0) {
+ PyXPCOM_LogWarning("Failed to convert object to unicode", PyXPCOM_ObTypeName(ob));
+ nr = NS_ERROR_UNEXPECTED;
+ break;
+ }
+ nr = v->SetAsWStringWithSize(nch, p);
+ nsMemory::Free(p);
+ }
+ break;
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ {
+ nsISupports *ps = cvt_result.pis;
+ nr = v->SetAsInterface(cvt_result.iid, ps);
+ if (ps) {
+ Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
+ ps->Release();
+ Py_END_ALLOW_THREADS;
+ }
+ break;
+ }
+ case nsIDataType::VTYPE_ID:
+ nr = v->SetAsID(cvt_result.iid);
+ break;
+ case nsIDataType::VTYPE_ARRAY:
+ {
+ int seq_length = PySequence_Length(ob);
+ NS_ABORT_IF_FALSE(seq_length!=0, "VTYPE_ARRAY assumes at least one element!");
+ PyObject *first = PySequence_GetItem(ob, 0);
+ if (!first) break;
+ int array_type = BestVariantTypeForPyObject(first);
+ Py_DECREF(first);
+ // Arrays can't handle all types. This means we lost embedded NULLs.
+ // This should really be fixed in XPCOM.
+ if (array_type == nsIDataType::VTYPE_STRING_SIZE_IS) array_type = nsIDataType::VTYPE_CHAR_STR;
+ if (array_type == nsIDataType::VTYPE_WSTRING_SIZE_IS) array_type = nsIDataType::VTYPE_WCHAR_STR;
+ PRUint32 element_size = GetArrayElementSize(array_type);
+ int cb_buffer_pointer = seq_length * element_size;
+ void *buffer_pointer;
+ if ((buffer_pointer = (void *)nsMemory::Alloc(cb_buffer_pointer)) == nsnull) {
+ nr = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ memset(buffer_pointer, 0, cb_buffer_pointer);
+ if (FillSingleArray(buffer_pointer, ob, seq_length, element_size, array_type, nsnull)) {
+ nr = v->SetAsArray(array_type, &NS_GET_IID(nsISupports), seq_length, buffer_pointer);
+ FreeSingleArray(buffer_pointer, seq_length, array_type);
+ } else
+ nr = NS_ERROR_UNEXPECTED;
+ nsMemory::Free(buffer_pointer);
+ break;
+ }
+ case nsIDataType::VTYPE_EMPTY:
+ nr = v->SetAsEmpty();
+ break;
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ nr = v->SetAsEmptyArray();
+ break;
+ case (PRUint16)-1:
+ PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", PyXPCOM_ObTypeName(ob));
+ nr = NS_ERROR_UNEXPECTED;
+ default:
+ NS_ABORT_IF_FALSE(0, "BestVariantTypeForPyObject() returned a variant type not handled here!");
+ PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", PyXPCOM_ObTypeName(ob));
+ nr = NS_ERROR_UNEXPECTED;
+ }
+ if (NS_FAILED(nr))
+ return nr;
+ return v->QueryInterface(NS_GET_IID(nsIVariant), (void **)aRet);
+}
+
+static PyObject *MyBool_FromBool(PRBool v)
+{
+ PyObject *ret = v ? Py_True : Py_False;
+ Py_INCREF(ret);
+ return ret;
+}
+
+#define GET_FROM_V(Type, FuncGet, FuncConvert) { \
+ Type t; \
+ if (NS_FAILED(nr = FuncGet( &t ))) goto done;\
+ ret = FuncConvert(t);\
+ break; \
+}
+
+PyObject *PyObject_FromVariantArray( Py_nsISupports *parent, nsIVariant *v)
+{
+ nsresult nr;
+ NS_PRECONDITION(v, "NULL variant!");
+ if (!v)
+ return PyXPCOM_BuildPyException(NS_ERROR_INVALID_POINTER);
+#ifdef NS_DEBUG
+ PRUint16 dt;
+ nr = v->GetDataType(&dt);
+ NS_ABORT_IF_FALSE(dt == nsIDataType::VTYPE_ARRAY, "expected an array variant");
+#endif
+ nsIID iid;
+ void *p;
+ PRUint16 type;
+ PRUint32 count;
+ nr = v->GetAsArray(&type, &iid, &count, &p);
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
+ PyObject *ret = UnpackSingleArray(parent, p, count, (PRUint8)type, &iid);
+ FreeSingleArray(p, count, (PRUint8)type);
+ nsMemory::Free(p);
+ return ret;
+}
+
+PyObject *PyObject_FromVariant( Py_nsISupports *parent, nsIVariant *v)
+{
+ if (!v) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ PRUint16 dt;
+ nsresult nr;
+ PyObject *ret = NULL;
+ nr = v->GetDataType(&dt);
+ if (NS_FAILED(nr)) goto done;
+ switch (dt) {
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_EMPTY:
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ break;
+ case nsIDataType::VTYPE_ARRAY:
+ ret = PyObject_FromVariantArray(parent, v);
+ break;
+ case nsIDataType::VTYPE_INT8:
+ case nsIDataType::VTYPE_INT16:
+ case nsIDataType::VTYPE_INT32:
+ GET_FROM_V(PRInt32, v->GetAsInt32, PyInt_FromLong);
+ case nsIDataType::VTYPE_UINT8:
+ case nsIDataType::VTYPE_UINT16:
+ case nsIDataType::VTYPE_UINT32:
+ GET_FROM_V(PRUint32, v->GetAsUint32, PyLong_FromUnsignedLong);
+ case nsIDataType::VTYPE_INT64:
+ GET_FROM_V(PRInt64, v->GetAsInt64, PyLong_FromLongLong);
+ case nsIDataType::VTYPE_UINT64:
+ GET_FROM_V(PRUint64, v->GetAsUint64, PyLong_FromUnsignedLongLong);
+ case nsIDataType::VTYPE_FLOAT:
+ case nsIDataType::VTYPE_DOUBLE:
+ GET_FROM_V(double, v->GetAsDouble, PyFloat_FromDouble);
+ case nsIDataType::VTYPE_BOOL:
+ GET_FROM_V(PRBool, v->GetAsBool, MyBool_FromBool);
+ default:
+ PyXPCOM_LogWarning("Converting variant to Python object - variant type '%d' unknown - using string.\n", dt);
+ // Fall through to the string case
+ case nsIDataType::VTYPE_CHAR:
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_CSTRING: {
+ nsCAutoString s;
+ if (NS_FAILED(nr=v->GetAsACString(s))) goto done;
+ ret = PyObject_FromNSString(s);
+ break;
+ }
+ case nsIDataType::VTYPE_WCHAR:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ case nsIDataType::VTYPE_ASTRING: {
+ nsAutoString s;
+ if (NS_FAILED(nr=v->GetAsAString(s))) goto done;
+ ret = PyObject_FromNSString(s);
+ break;
+ }
+ case nsIDataType::VTYPE_ID:
+ GET_FROM_V(nsIID, v->GetAsID, Py_nsIID::PyObjectFromIID);
+ case nsIDataType::VTYPE_INTERFACE: {
+ nsCOMPtr<nsISupports> p;
+ if (NS_FAILED(nr=v->GetAsISupports(getter_AddRefs(p)))) goto done;
+ if (parent)
+ ret = parent->MakeInterfaceResult(p, NS_GET_IID(nsISupports));
+ else
+ ret = Py_nsISupports::PyObjectFromInterface(
+ p, NS_GET_IID(nsISupports), PR_TRUE);
+ break;
+ }
+ case nsIDataType::VTYPE_INTERFACE_IS: {
+ nsCOMPtr<nsISupports> p;
+ nsIID *iid;
+ if (NS_FAILED(nr=v->GetAsInterface(&iid, getter_AddRefs(p)))) goto done;
+ // If the variant itself holds a variant, we should
+ // probably unpack that too?
+ ret = parent->MakeInterfaceResult(p, *iid);
+ break;
+ // case nsIDataType::VTYPE_WCHAR_STR
+ // case nsIDataType::VTYPE_UTF8STRING
+ }
+ }
+done:
+ if (NS_FAILED(nr)) {
+ NS_ABORT_IF_FALSE(ret==NULL, "Have an error, but also a return val!");
+ PyXPCOM_BuildPyException(nr);
+ }
+ return ret;
+}
+
+// ------------------------------------------------------------------------
+// TypeDescriptor helper class
+// ------------------------------------------------------------------------
+class PythonTypeDescriptor {
+public:
+ PythonTypeDescriptor() {
+ param_flags = type_flags = argnum = argnum2 = 0;
+ extra = NULL;
+ is_auto_out = PR_FALSE;
+ is_auto_in = PR_FALSE;
+ have_set_auto = PR_FALSE;
+ }
+ ~PythonTypeDescriptor() {
+ Py_XDECREF(extra);
+ }
+ PRUint8 param_flags;
+ PRUint8 type_flags;
+ PRUint8 argnum; /* used for iid_is and size_is */
+ PRUint8 argnum2; /* used for length_is */
+ PyObject *extra; // The IID object, or the type of the array.
+ // Extra items to help our processing.
+ // Is this auto-filled by some other "in" param?
+ PRBool is_auto_in;
+ // Is this auto-filled by some other "out" param?
+ PRBool is_auto_out;
+ // If is_auto_out, have I already filled it? Used when multiple
+ // params share a size_is fields - first time sets it, subsequent
+ // time check it.
+ PRBool have_set_auto;
+};
+
+static int ProcessPythonTypeDescriptors(PythonTypeDescriptor *pdescs, int num)
+{
+ // Loop over the array, checking all the params marked as having an arg.
+ // If these args nominate another arg as the size_is param, then
+ // we reset the size_is param to _not_ requiring an arg.
+ int i;
+ for (i=0;i<num;i++) {
+ PythonTypeDescriptor &ptd = pdescs[i];
+ // Can't use XPT_TDP_TAG() - it uses a ".flags" reference in the macro.
+ switch (ptd.type_flags & XPT_TDP_TAGMASK) {
+ case nsXPTType::T_ARRAY:
+ NS_ABORT_IF_FALSE(ptd.argnum < num, "Bad dependent index");
+ if (ptd.argnum2 < num) {
+ if (XPT_PD_IS_IN(ptd.param_flags))
+ pdescs[ptd.argnum2].is_auto_in = PR_TRUE;
+ if (XPT_PD_IS_OUT(ptd.param_flags))
+ pdescs[ptd.argnum2].is_auto_out = PR_TRUE;
+ }
+ break;
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ NS_ABORT_IF_FALSE(ptd.argnum < num, "Bad dependent index");
+ if (ptd.argnum < num) {
+ if (XPT_PD_IS_IN(ptd.param_flags))
+ pdescs[ptd.argnum].is_auto_in = PR_TRUE;
+ if (XPT_PD_IS_OUT(ptd.param_flags))
+ pdescs[ptd.argnum].is_auto_out = PR_TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ int total_params_needed = 0;
+ for (i=0;i<num;i++)
+ if (XPT_PD_IS_IN(pdescs[i].param_flags) && !pdescs[i].is_auto_in && !XPT_PD_IS_DIPPER(pdescs[i].param_flags))
+ total_params_needed++;
+
+ return total_params_needed;
+}
+
+/*************************************************************************
+**************************************************************************
+
+Helpers when CALLING interfaces.
+
+**************************************************************************
+*************************************************************************/
+
+PyXPCOM_InterfaceVariantHelper::PyXPCOM_InterfaceVariantHelper(Py_nsISupports *parent, int methodindex)
+{
+ m_var_array=nsnull;
+ m_buffer_array=nsnull;
+ m_pyparams=nsnull;
+ m_typedescs = nsnull;
+ m_python_type_desc_array = nsnull;
+ m_num_array = 0;
+ m_methodindex = methodindex;
+ // Parent should never die before we do, but let's not take the chance.
+ m_parent = parent;
+ Py_INCREF(parent);
+}
+
+PyXPCOM_InterfaceVariantHelper::~PyXPCOM_InterfaceVariantHelper()
+{
+ Py_DECREF(m_parent);
+ Py_XDECREF(m_pyparams);
+ for (int i=0;i<m_num_array;i++) {
+ if (m_var_array) {
+ nsXPTCVariant &ns_v = m_var_array[i];
+ if (ns_v.IsValInterface()) {
+ if (ns_v.val.p) {
+ Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
+ ((nsISupports *)ns_v.val.p)->Release();
+ Py_END_ALLOW_THREADS;
+ }
+ }
+ if (ns_v.IsValDOMString() && ns_v.val.p) {
+ delete (const nsAString *)ns_v.val.p;
+ }
+ if (ns_v.IsValCString() && ns_v.val.p) {
+ delete (const nsACString *)ns_v.val.p;
+ }
+ if (ns_v.IsValUTF8String() && ns_v.val.p) {
+ delete (const nsACString *)ns_v.val.p;
+ }
+ if (ns_v.IsValArray()) {
+ nsXPTCVariant &ns_v = m_var_array[i];
+ if (ns_v.val.p) {
+ PRUint8 array_type = (PRUint8)PyInt_AsLong(m_python_type_desc_array[i].extra);
+ PRUint32 seq_size = GetSizeIs(i, PR_FALSE);
+ FreeSingleArray(ns_v.val.p, seq_size, array_type);
+ }
+ }
+ // IsOwned must be the last check of the loop, as
+ // this frees the underlying data used above (eg, by the array free process)
+ if (ns_v.IsValAllocated() && !ns_v.IsValInterface() && !ns_v.IsValDOMString()) {
+ NS_ABORT_IF_FALSE(ns_v.IsPtrData(), "expecting a pointer to free");
+ nsMemory::Free(ns_v.val.p);
+ }
+ }
+ if (m_buffer_array && m_buffer_array[i])
+ nsMemory::Free(m_buffer_array[i]);
+ }
+ delete [] m_python_type_desc_array;
+ delete [] m_buffer_array;
+ delete [] m_var_array;
+}
+
+PRBool PyXPCOM_InterfaceVariantHelper::Init(PyObject *obParams)
+{
+ PRBool ok = PR_FALSE;
+ int i;
+ int total_params_needed = 0;
+ if (!PySequence_Check(obParams) || PySequence_Length(obParams)!=2) {
+ PyErr_Format(PyExc_TypeError, "Param descriptors must be a sequence of exactly length 2");
+ return PR_FALSE;
+ }
+ PyObject *typedescs = PySequence_GetItem(obParams, 0);
+ if (typedescs==NULL)
+ return PR_FALSE;
+ // NOTE: The length of the typedescs may be different than the
+ // args actually passed. The typedescs always include all
+ // hidden params (such as "size_is"), while the actual
+ // args never include this.
+ m_num_array = PySequence_Length(typedescs);
+ if (PyErr_Occurred()) goto done;
+
+ m_pyparams = PySequence_GetItem(obParams, 1);
+ if (m_pyparams==NULL) goto done;
+
+ m_python_type_desc_array = new PythonTypeDescriptor[m_num_array];
+ if (!m_python_type_desc_array) goto done;
+
+ // Pull apart the type descs and stash them.
+ for (i=0;i<m_num_array;i++) {
+ PyObject *desc_object = PySequence_GetItem(typedescs, i);
+ if (desc_object==NULL)
+ goto done;
+
+ // Pull apart the typedesc tuple back into a structure we can work with.
+ PythonTypeDescriptor &ptd = m_python_type_desc_array[i];
+ PRBool this_ok = PyArg_ParseTuple(desc_object, "bbbbO:type_desc",
+ &ptd.param_flags, &ptd.type_flags, &ptd.argnum, &ptd.argnum2, &ptd.extra);
+ Py_DECREF(desc_object);
+ if (!this_ok) goto done;
+ Py_INCREF(ptd.extra);
+
+ }
+ total_params_needed = ProcessPythonTypeDescriptors(m_python_type_desc_array, m_num_array);
+ // OK - check we got the number of args we expected.
+ // If not, its really an internal error rather than the user.
+ if (PySequence_Length(m_pyparams) != total_params_needed) {
+#ifdef VBOX
+ PyErr_Format(PyExc_ValueError, "The type descriptions indicate %d args are needed, but %ld were provided",
+ total_params_needed, (long)PySequence_Length(m_pyparams));
+#else
+ PyErr_Format(PyExc_ValueError, "The type descriptions indicate %d args are needed, but %d were provided",
+ total_params_needed, PySequence_Length(m_pyparams));
+#endif
+ goto done;
+ }
+
+ // Init the other arrays.
+ m_var_array = new nsXPTCVariant[m_num_array];
+ if (!m_var_array) goto done;
+ /*memset(m_var_array, 0, m_num_array * sizeof(m_var_array[0])); - VBox not needed */
+
+ m_buffer_array = new void *[m_num_array];
+ if (!m_buffer_array) goto done;
+ memset(m_buffer_array, 0, m_num_array * sizeof(m_buffer_array[0]));
+
+ ok = PR_TRUE;
+done:
+ if (!ok && !PyErr_Occurred())
+ PyErr_NoMemory();
+
+ Py_XDECREF(typedescs);
+ return ok;
+}
+
+
+PRBool PyXPCOM_InterfaceVariantHelper::FillArray()
+{
+ int param_index = 0;
+ int i;
+ for (i=0;i<m_num_array;i++) {
+ PythonTypeDescriptor &ptd = m_python_type_desc_array[i];
+ // stash the type_flags into the variant, and remember how many extra bits of info we have.
+ m_var_array[i].type = ptd.type_flags;
+ if (XPT_PD_IS_IN(ptd.param_flags) && !ptd.is_auto_in && !XPT_PD_IS_DIPPER(ptd.param_flags)) {
+ if (!FillInVariant(ptd, i, param_index))
+ return PR_FALSE;
+ param_index++;
+ }
+ if ((XPT_PD_IS_OUT(ptd.param_flags) && !ptd.is_auto_out) || XPT_PD_IS_DIPPER(ptd.param_flags)) {
+ if (!PrepareOutVariant(ptd, i))
+ return PR_FALSE;
+ }
+ }
+ // There may be out "size_is" params we havent touched yet
+ // (ie, as the param itself is marked "out", we never got to
+ // touch the associated "size_is".
+ // Final loop to handle this.
+ for (i=0;i<m_num_array;i++) {
+ PythonTypeDescriptor &ptd = m_python_type_desc_array[i];
+ if (ptd.is_auto_out && !ptd.have_set_auto) {
+ // Call PrepareOutVariant to ensure buffers etc setup.
+ if (!PrepareOutVariant(ptd, i))
+ return PR_FALSE;
+ }
+ }
+ return PR_TRUE;
+}
+
+
+PRBool PyXPCOM_InterfaceVariantHelper::SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size)
+{
+ NS_ABORT_IF_FALSE(var_index < m_num_array, "var_index param is invalid");
+ PRUint8 argnum = is_arg1 ?
+ m_python_type_desc_array[var_index].argnum :
+ m_python_type_desc_array[var_index].argnum2;
+ NS_ABORT_IF_FALSE(argnum < m_num_array, "size_is param is invalid");
+ PythonTypeDescriptor &td_size = m_python_type_desc_array[argnum];
+ NS_ABORT_IF_FALSE(td_size.is_auto_in || td_size.is_auto_out, "Setting size_is, but param is not marked as auto!");
+ NS_ABORT_IF_FALSE( (td_size.type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_U32, "size param must be Uint32");
+ nsXPTCVariant &ns_v = m_var_array[argnum];
+
+ if (!td_size.have_set_auto) {
+ ns_v.type = td_size.type_flags;
+ ns_v.val.u32 = new_size;
+ // In case it is "out", setup the necessary pointers.
+ PrepareOutVariant(td_size, argnum);
+ td_size.have_set_auto = PR_TRUE;
+ } else {
+ if (ns_v.val.u32 != new_size) {
+ PyErr_Format(PyExc_ValueError, "Array lengths inconsistent; array size previously set to %d, but second array is of size %d", ns_v.val.u32, new_size);
+ return PR_FALSE;
+ }
+ }
+ return PR_TRUE;
+}
+
+PRUint32 PyXPCOM_InterfaceVariantHelper::GetSizeIs( int var_index, PRBool is_arg1)
+{
+ NS_ABORT_IF_FALSE(var_index < m_num_array, "var_index param is invalid");
+ PRUint8 argnum = is_arg1 ?
+ m_python_type_desc_array[var_index].argnum :
+ m_python_type_desc_array[var_index].argnum2;
+ NS_ABORT_IF_FALSE(argnum < m_num_array, "size_is param is invalid");
+ NS_ABORT_IF_FALSE( (m_python_type_desc_array[argnum].type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_U32, "size param must be Uint32");
+ PRBool is_out = XPT_PD_IS_OUT(m_python_type_desc_array[argnum].param_flags);
+ nsXPTCVariant &ns_v = m_var_array[argnum];
+ return is_out ? *((PRUint32 *)ns_v.ptr) : ns_v.val.u32;
+}
+
+#define MAKE_VALUE_BUFFER(size) \
+ if ((this_buffer_pointer = (void *)nsMemory::Alloc((size))) == nsnull) { \
+ PyErr_NoMemory(); \
+ BREAK_FALSE; \
+ }
+
+PRBool PyXPCOM_InterfaceVariantHelper::FillInVariant(const PythonTypeDescriptor &td, int value_index, int param_index)
+{
+ PRBool rc = PR_TRUE;
+ // Get a reference to the variant we are filling for convenience.
+ nsXPTCVariant &ns_v = m_var_array[value_index];
+ NS_ABORT_IF_FALSE(ns_v.type == td.type_flags, "Expecting variant all setup for us");
+
+ // We used to avoid passing internal buffers to PyString etc objects
+ // for 2 reasons: paranoia (so incorrect external components couldn't break
+ // Python) and simplicity (in vs in-out issues, etc)
+ // However, at least one C++ implemented component (nsITimelineService)
+ // uses a "char *", and keys on the address (assuming that the same
+ // *pointer* is passed rather than value. Therefore, we have a special case
+ // - T_CHAR_STR that is "in" gets the Python string pointer passed.
+ void *&this_buffer_pointer = m_buffer_array[value_index]; // Freed at object destruction with PyMem_Free()
+ NS_ABORT_IF_FALSE(this_buffer_pointer==nsnull, "We appear to already have a buffer");
+ int cb_this_buffer_pointer = 0;
+ if (XPT_PD_IS_IN(td.param_flags)) {
+ NS_ABORT_IF_FALSE(!td.is_auto_in, "Param is 'auto-in', but we are filling it normally!");
+ PyObject *val_use = NULL; // a temp object converters can use, and will be DECREF'd
+ PyObject *val = PySequence_GetItem(m_pyparams, param_index);
+ NS_WARN_IF_FALSE(val, "Have an 'in' param, but no Python value!");
+ if (val==NULL) {
+ PyErr_Format(PyExc_ValueError, "Param %d is marked as 'in', but no value was given", value_index);
+ return PR_FALSE;
+ }
+ switch (XPT_TDP_TAG(ns_v.type)) {
+ case nsXPTType::T_I8:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.i8 = (PRInt8)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_I16:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.i16 = (PRInt16)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_I32:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.i32 = (PRInt32)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_I64:
+ if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE
+ ns_v.val.i64 = (PRInt64)PyLong_AsLongLong(val_use);
+ break;
+ case nsXPTType::T_U8:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.u8 = (PRUint8)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_U16:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.u16 = (PRUint16)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_U32:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.u32 = (PRUint32)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_U64:
+ if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE
+ ns_v.val.u64 = (PRUint64)PyLong_AsUnsignedLongLong(val_use);
+ break;
+ case nsXPTType::T_FLOAT:
+ if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
+ ns_v.val.f = (float)PyFloat_AsDouble(val_use);
+ break;
+ case nsXPTType::T_DOUBLE:
+ if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
+ ns_v.val.d = PyFloat_AsDouble(val_use);
+ break;
+ case nsXPTType::T_BOOL:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.b = (PRBool)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_CHAR:{
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+ if (PyString_GET_SIZE(val_use) != 1) {
+ PyErr_SetString(PyExc_ValueError, "Must specify a one character string for a character");
+ BREAK_FALSE;
+ }
+
+ ns_v.val.c = *PyString_AS_STRING(val_use);
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ if (PyUnicode_GET_SIZE(val) != 1) {
+ PyErr_SetString(PyExc_ValueError, "Must specify a one character string for a character");
+ BREAK_FALSE;
+ }
+
+# ifndef Py_LIMITED_API
+ ns_v.val.c = *PyUnicode_AS_UNICODE(val_use);
+# else
+ ns_v.val.c = PyUnicode_ReadChar(val_use, 0);
+# endif
+#endif
+ break;
+ }
+
+ case nsXPTType::T_WCHAR: {
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+#endif
+ if ((val_use = PyUnicode_FromObject(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyUnicode_FromObject() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a unicode object!");
+ if (PyUnicode_GET_SIZE(val_use) != 1) {
+ PyErr_SetString(PyExc_ValueError, "Must specify a one character string for a character");
+ BREAK_FALSE;
+ }
+ // Lossy!
+#ifndef Py_LIMITED_API
+ ns_v.val.wc = *PyUnicode_AS_UNICODE(val_use);
+#else
+ ns_v.val.wc = PyUnicode_ReadChar(val_use, 0);
+#endif
+ break;
+ }
+ // case nsXPTType::T_VOID: /* fall through */
+ case nsXPTType::T_IID:
+ nsIID iid;
+ MAKE_VALUE_BUFFER(sizeof(nsIID));
+ if (!Py_nsIID::IIDFromPyObject(val, &iid))
+ BREAK_FALSE;
+ memcpy(this_buffer_pointer, &iid, sizeof(iid));
+ ns_v.val.p = this_buffer_pointer;
+ break;
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING: {
+ nsString *s = new nsString();
+ if (!s) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ ns_v.val.p = s;
+ // We created it - flag as such for cleanup.
+ ns_v.flags |= nsXPTCVariant::VAL_IS_DOMSTR;
+
+ if (!PyObject_AsNSString(val, *s))
+ BREAK_FALSE;
+ break;
+ }
+ case nsXPTType::T_CSTRING:
+ case nsXPTType::T_UTF8STRING: {
+ PRBool bIsUTF8 = XPT_TDP_TAG(ns_v.type) == nsXPTType::T_UTF8STRING;
+ if (val==Py_None) {
+ ns_v.val.p = new nsCString();
+ } else {
+#if PY_MAJOR_VERSION <= 2
+ if (PyString_Check(val)) {
+ // strings are assumed to already be UTF8 encoded.
+ val_use = val;
+ Py_INCREF(val);
+ }
+ else
+#endif
+ if (PyUnicode_Check(val)) {
+ // Unicode objects are encoded by us.
+ if (bIsUTF8)
+ val_use = PyUnicode_AsUTF8String(val);
+ else
+#if PY_MAJOR_VERSION <= 2
+ val_use = PyObject_Str(val);
+#else
+ val_use = PyUnicode_AsUTF8String(val);
+#endif
+ } else {
+#if PY_MAJOR_VERSION <= 2
+ PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be string or Unicode objects");
+#else
+ PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be unicode objects");
+#endif
+ BREAK_FALSE;
+ }
+ if (!val_use)
+ BREAK_FALSE;
+#if PY_MAJOR_VERSION <= 2
+ ns_v.val.p = new nsCString(PyString_AS_STRING(val_use),
+ PyString_GET_SIZE(val_use));
+#else
+ ns_v.val.p = new nsCString(PyBytes_AS_STRING(val_use),
+ PyBytes_GET_SIZE(val_use));
+#endif
+ }
+
+ if (!ns_v.val.p) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ // We created it - flag as such for cleanup.
+ ns_v.flags |= bIsUTF8 ? nsXPTCVariant::VAL_IS_UTF8STR : nsXPTCVariant::VAL_IS_CSTR;
+ break;
+ }
+ case nsXPTType::T_CHAR_STR: {
+ if (val==Py_None) {
+ ns_v.val.p = nsnull;
+ break;
+ }
+#if PY_MAJOR_VERSION <= 2
+ // If an "in" char *, and we have a PyString, then pass the
+ // pointer (hoping everyone else plays by the rules too.
+ if (!XPT_PD_IS_OUT(td.param_flags) && PyString_Check(val)) {
+ ns_v.val.p = (void *)PyString_AS_STRING(val);
+ break;
+ }
+
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+
+ cb_this_buffer_pointer = PyString_GET_SIZE(val_use)+1;
+ MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
+ memcpy(this_buffer_pointer, PyString_AS_STRING(val_use), cb_this_buffer_pointer);
+#else
+
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_AsUTF8String(val))==NULL)
+ BREAK_FALSE;
+
+ cb_this_buffer_pointer = PyBytes_GET_SIZE(val_use)+1;
+ MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
+ memcpy(this_buffer_pointer, PyBytes_AS_STRING(val_use), cb_this_buffer_pointer);
+#endif
+ ns_v.val.p = this_buffer_pointer;
+ break;
+ }
+
+ case nsXPTType::T_WCHAR_STR: {
+ if (val==Py_None) {
+ ns_v.val.p = nsnull;
+ break;
+ }
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_FromObject(val))==NULL)
+ BREAK_FALSE;
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ val_use = val;
+ Py_INCREF(val_use);
+#endif
+ PRUnichar *sv;
+ PRUint32 nch;
+ if (PyUnicode_AsPRUnichar(val_use, &sv, &nch) < 0)
+ BREAK_FALSE;
+ cb_this_buffer_pointer = (nch + 1) * sizeof(PRUnichar);
+ this_buffer_pointer = sv;
+ ns_v.val.p = this_buffer_pointer;
+ break;
+ }
+ case nsXPTType::T_INTERFACE: {
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(td.extra, &iid))
+ BREAK_FALSE;
+ if (!Py_nsISupports::InterfaceFromPyObject(
+ val,
+ iid,
+ (nsISupports **)&ns_v.val.p,
+ PR_TRUE))
+ BREAK_FALSE;
+ // We have added a reference - flag as such for cleanup.
+ ns_v.flags |= nsXPTCVariant::VAL_IS_IFACE;
+ break;
+ }
+ case nsXPTType::T_INTERFACE_IS: {
+ nsIID iid;
+ nsXPTCVariant &ns_viid = m_var_array[td.argnum];
+ NS_WARN_IF_FALSE(XPT_TDP_TAG(ns_viid.type)==nsXPTType::T_IID, "The INTERFACE_IS iid describer isnt an IID!");
+ // This is a pretty serious problem, but not Python's fault!
+ // Just return an nsISupports and hope the caller does whatever
+ // QI they need before using it.
+ if (XPT_TDP_TAG(ns_viid.type)==nsXPTType::T_IID &&
+ XPT_PD_IS_IN(ns_viid.type)) {
+ nsIID *piid = (nsIID *)ns_viid.val.p;
+ if (piid==NULL)
+ // Also serious, but like below, not our fault!
+ iid = NS_GET_IID(nsISupports);
+ else
+ iid = *piid;
+ } else
+ // Use NULL IID to avoid a QI in this case.
+ iid = Py_nsIID_NULL;
+ if (!Py_nsISupports::InterfaceFromPyObject(
+ val,
+ iid,
+ (nsISupports **)&ns_v.val.p,
+ PR_TRUE))
+ BREAK_FALSE;
+ // We have added a reference - flag as such for cleanup.
+ ns_v.flags |= nsXPTCVariant::VAL_IS_IFACE;
+ break;
+ }
+ case nsXPTType::T_PSTRING_SIZE_IS: {
+ if (val==Py_None) {
+ ns_v.val.p = nsnull;
+ break;
+ }
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+
+ cb_this_buffer_pointer = PyString_GET_SIZE(val_use);
+ MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
+ memcpy(this_buffer_pointer, PyString_AS_STRING(val_use), cb_this_buffer_pointer);
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_AsUTF8String(val))==NULL)
+ BREAK_FALSE;
+
+ cb_this_buffer_pointer = PyBytes_GET_SIZE(val_use);
+ MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
+ memcpy(this_buffer_pointer, PyBytes_AS_STRING(val_use), cb_this_buffer_pointer);
+#endif
+ ns_v.val.p = this_buffer_pointer;
+ rc = SetSizeIs(value_index, PR_TRUE, cb_this_buffer_pointer);
+ break;
+ }
+
+ case nsXPTType::T_PWSTRING_SIZE_IS: {
+ if (val==Py_None) {
+ ns_v.val.p = nsnull;
+ break;
+ }
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_FromObject(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyObject_Unicode didnt return a unicode object!");
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ val_use = val;
+ Py_INCREF(val_use);
+#endif
+ PRUnichar *sv;
+ PRUint32 nch;
+ if (PyUnicode_AsPRUnichar(val_use, &sv, &nch) < 0)
+ BREAK_FALSE;
+ cb_this_buffer_pointer = (nch + 1) * sizeof(PRUnichar);
+ this_buffer_pointer = sv;
+ ns_v.val.p = this_buffer_pointer;
+ rc = SetSizeIs(value_index, PR_TRUE, nch);
+ break;
+ }
+ case nsXPTType::T_ARRAY: {
+ if (val==Py_None) {
+ ns_v.val.p = nsnull;
+ break;
+ }
+ if (!PyInt_Check(td.extra)) {
+ PyErr_SetString(PyExc_TypeError, "The array info is not valid");
+ BREAK_FALSE;
+ }
+ if (!PySequence_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a sequence");
+ BREAK_FALSE;
+ }
+ int array_type = PyInt_AsLong(td.extra);
+ PRUint32 element_size = GetArrayElementSize(array_type);
+ int seq_length = PySequence_Length(val);
+ cb_this_buffer_pointer = seq_length * element_size;
+ if (cb_this_buffer_pointer==0)
+ // prevent assertions allocing zero bytes. Can't use NULL.
+ cb_this_buffer_pointer = 1;
+ MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
+ memset(this_buffer_pointer, 0, cb_this_buffer_pointer);
+ rc = FillSingleArray(this_buffer_pointer, val, seq_length, element_size, array_type&XPT_TDP_TAGMASK, nsnull);
+ if (!rc) break;
+ rc = SetSizeIs(value_index, PR_FALSE, seq_length);
+ if (!rc) break;
+ ns_v.flags |= nsXPTCVariant::VAL_IS_ARRAY;
+ ns_v.val.p = this_buffer_pointer;
+ break;
+ }
+ default:
+ PyErr_Format(PyExc_TypeError, "The object type (0x%x) is unknown", XPT_TDP_TAG(ns_v.type));
+ rc = PR_FALSE;
+ break;
+ }
+ Py_DECREF(val); // Cant be NULL!
+ Py_XDECREF(val_use);
+ }
+ return rc && !PyErr_Occurred();
+}
+
+PRBool PyXPCOM_InterfaceVariantHelper::PrepareOutVariant(const PythonTypeDescriptor &td, int value_index)
+{
+ PRBool rc = PR_TRUE;
+ nsXPTCVariant &ns_v = m_var_array[value_index];
+ void *&this_buffer_pointer = m_buffer_array[value_index]; // Freed at object destruction with PyMem_Free()
+ // Do the out param thang...
+ if (XPT_PD_IS_OUT(td.param_flags) || XPT_PD_IS_DIPPER(td.param_flags)) {
+ NS_ABORT_IF_FALSE(ns_v.ptr == NULL, "already have a pointer!");
+ ns_v.ptr = &ns_v;
+ ns_v.flags |= nsXPTCVariant::PTR_IS_DATA;
+
+ // Special flags based on the data type
+ switch (XPT_TDP_TAG(ns_v.type)) {
+ case nsXPTType::T_I8:
+ case nsXPTType::T_I16:
+ case nsXPTType::T_I32:
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U8:
+ case nsXPTType::T_U16:
+ case nsXPTType::T_U32:
+ case nsXPTType::T_U64:
+ case nsXPTType::T_FLOAT:
+ case nsXPTType::T_DOUBLE:
+ case nsXPTType::T_BOOL:
+ case nsXPTType::T_CHAR:
+ case nsXPTType::T_WCHAR:
+ case nsXPTType::T_VOID:
+ break;
+
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ NS_ABORT_IF_FALSE(this_buffer_pointer==NULL, "Can't have an interface and a buffer pointer!");
+ ns_v.flags |= nsXPTCVariant::VAL_IS_IFACE;
+ ns_v.flags |= nsXPTCVariant::VAL_IS_ALLOCD;
+ break;
+ case nsXPTType::T_ARRAY:
+ ns_v.flags |= nsXPTCVariant::VAL_IS_ARRAY;
+ ns_v.flags |= nsXPTCVariant::VAL_IS_ALLOCD;
+ // Even if ns_val.p already setup as part of "in" processing,
+ // we need to ensure setup for out.
+ NS_ABORT_IF_FALSE(ns_v.val.p==nsnull || ns_v.val.p==this_buffer_pointer, "Garbage in our pointer?");
+ ns_v.val.p = this_buffer_pointer;
+ this_buffer_pointer = nsnull;
+ break;
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_WCHAR_STR:
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_IID:
+ // If we stashed a value in the this_buffer_pointer, and
+ // we are passing it as an OUT param, we do _not_ want to
+ // treat it as a temporary buffer.
+ // For example, if we pass an IID or string as an IN param,
+ // we allocate a buffer for the value, but this is NOT cleaned up
+ // via normal VARIANT cleanup rules - hence we clean it up ourselves.
+ // If the param is IN/OUT, then the buffer falls under the normal variant
+ // rules (ie, is flagged as VAL_IS_ALLOCD), so we dont clean it as a temporary.
+ // (it may have been changed under us - we free the _new_ value.
+ // Even if ns_val.p already setup as part of "in" processing,
+ // we need to ensure setup for out.
+ NS_ABORT_IF_FALSE(ns_v.val.p==nsnull || ns_v.val.p==this_buffer_pointer, "Garbage in our pointer?");
+ ns_v.val.p = this_buffer_pointer;
+ ns_v.flags |= nsXPTCVariant::VAL_IS_ALLOCD;
+ this_buffer_pointer = nsnull;
+ break;
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_ASTRING: {
+ NS_ABORT_IF_FALSE(ns_v.val.p==nsnull, "T_DOMTSTRINGS cant be out and have a value (ie, no in/outs are allowed!");
+ NS_ABORT_IF_FALSE(XPT_PD_IS_DIPPER(td.param_flags) && XPT_PD_IS_IN(td.param_flags), "out DOMStrings must really be in dippers!");
+ ns_v.flags |= nsXPTCVariant::VAL_IS_DOMSTR;
+ // Dippers are really treated like "in" params.
+ ns_v.ptr = new nsString();
+ ns_v.val.p = ns_v.ptr; // VAL_IS_* says the .p is what gets freed
+ if (!ns_v.ptr) {
+ PyErr_NoMemory();
+ rc = PR_FALSE;
+ }
+ break;
+ }
+ case nsXPTType::T_CSTRING:
+ case nsXPTType::T_UTF8STRING: {
+ NS_ABORT_IF_FALSE(ns_v.val.p==nsnull, "T_DOMTSTRINGS cant be out and have a value (ie, no in/outs are allowed!");
+ NS_ABORT_IF_FALSE(XPT_PD_IS_DIPPER(td.param_flags) && XPT_PD_IS_IN(td.param_flags), "out DOMStrings must really be in dippers!");
+ ns_v.flags |= ( XPT_TDP_TAG(ns_v.type)==nsXPTType::T_CSTRING ? nsXPTCVariant::VAL_IS_CSTR : nsXPTCVariant::VAL_IS_UTF8STR);
+ ns_v.ptr = new nsCString();
+ ns_v.val.p = ns_v.ptr; // VAL_IS_* says the .p is what gets freed
+ if (!ns_v.ptr) {
+ PyErr_NoMemory();
+ rc = PR_FALSE;
+ }
+ break;
+ }
+ default:
+ NS_ABORT_IF_FALSE(0, "Unknown type - don't know how to prepare the output value");
+ break; // Nothing to do!
+ }
+ }
+ return rc;
+}
+
+
+PyObject *PyXPCOM_InterfaceVariantHelper::MakeSinglePythonResult(int index)
+{
+ nsXPTCVariant &ns_v = m_var_array[index];
+ PyObject *ret = nsnull;
+ NS_ABORT_IF_FALSE(ns_v.IsPtrData() || ns_v.IsValDOMString(), "expecting a pointer if you want a result!");
+
+ // Re-fetch the type descriptor.
+ PythonTypeDescriptor &td = m_python_type_desc_array[index];
+ // Make sure the type tag of the variant hasnt changed on us.
+ NS_ABORT_IF_FALSE(ns_v.type==td.type_flags, "variant type has changed under us!");
+
+ // If the pointer is NULL, we can get out now!
+ if (ns_v.ptr==nsnull) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ switch (XPT_TDP_TAG(ns_v.type)) {
+ case nsXPTType::T_I8:
+ ret = PyInt_FromLong( *((PRInt8 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_I16:
+ ret = PyInt_FromLong( *((PRInt16 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_I32:
+ ret = PyInt_FromLong( *((PRInt32 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_I64:
+ ret = PyLong_FromLongLong( *((PRInt64 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_U8:
+ ret = PyInt_FromLong( *((PRUint8 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_U16:
+ ret = PyInt_FromLong( *((PRUint16 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_U32:
+ ret = PyInt_FromLong( *((PRUint32 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_U64:
+ ret = PyLong_FromUnsignedLongLong( *((PRUint64 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_FLOAT:
+ ret = PyFloat_FromDouble( *((float *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_DOUBLE:
+ ret = PyFloat_FromDouble( *((double *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_BOOL:
+ ret = *((PRBool *)ns_v.ptr) ? Py_True : Py_False;
+ Py_INCREF(ret);
+ break;
+ case nsXPTType::T_CHAR:
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromStringAndSize( ((char *)ns_v.ptr), 1 );
+#else
+ ret = PyUnicode_FromStringAndSize( ((char *)ns_v.ptr), 1 );
+#endif
+ break;
+
+ case nsXPTType::T_WCHAR:
+ ret = PyUnicode_FromPRUnichar( ((PRUnichar *)ns_v.ptr), 1 );
+ break;
+// case nsXPTType::T_VOID:
+ case nsXPTType::T_IID:
+ ret = Py_nsIID::PyObjectFromIID( **((nsIID **)ns_v.ptr) );
+ break;
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING: {
+ nsAString *rs = (nsAString *)ns_v.ptr;
+ ret = PyObject_FromNSString(*rs);
+ break;
+ }
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING: {
+ nsCString *rs = (nsCString *)ns_v.ptr;
+ ret = PyObject_FromNSString(*rs, XPT_TDP_TAG(ns_v.type)==nsXPTType::T_UTF8STRING);
+ break;
+ }
+
+ case nsXPTType::T_CHAR_STR:
+ if (*((char **)ns_v.ptr) == NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromString( *((char **)ns_v.ptr) );
+#else
+ ret = PyUnicode_FromString( *((char **)ns_v.ptr) );
+#endif
+ break;
+
+ case nsXPTType::T_WCHAR_STR: {
+ PRUnichar *us = *((PRUnichar **)ns_v.ptr);
+ if (us == NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ ret = PyUnicode_FromPRUnichar( us, nsCRT::strlen(us));
+ }
+ break;
+ }
+ case nsXPTType::T_INTERFACE: {
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(td.extra, &iid))
+ break;
+ nsISupports *iret = *((nsISupports **)ns_v.ptr);
+ // Our cleanup code manages iret reference ownership, and our
+ // new object takes its own.
+ if (iid.Equals(NS_GET_IID(nsIVariant)))
+ ret = PyObject_FromVariant(m_parent, (nsIVariant *)iret);
+ else
+ ret = m_parent->MakeInterfaceResult(iret, iid);
+ break;
+ }
+ case nsXPTType::T_INTERFACE_IS: {
+ nsIID iid;
+ nsXPTCVariant &ns_viid = m_var_array[td.argnum];
+ NS_WARN_IF_FALSE(XPT_TDP_TAG(ns_viid.type)==nsXPTType::T_IID, "The INTERFACE_IS iid describer isnt an IID!");
+ if (XPT_TDP_TAG(ns_viid.type)==nsXPTType::T_IID) {
+ nsIID *piid = (nsIID *)ns_viid.val.p;
+ if (piid==NULL)
+ // Also serious, but like below, not our fault!
+ iid = NS_GET_IID(nsISupports);
+ else
+ iid = *piid;
+ } else {
+ // This is a pretty serious problem, but not Python's fault!
+ // Just return an nsISupports and hope the caller does whatever
+ // QI they need before using it.
+ NS_ERROR("Failed to get the IID for T_INTERFACE_IS!");
+ iid = NS_GET_IID(nsISupports);
+ }
+ nsISupports *iret = *((nsISupports **)ns_v.ptr);
+ if (iid.Equals(NS_GET_IID(nsIVariant)))
+ ret = PyObject_FromVariant(m_parent, (nsIVariant *)iret);
+ else
+ ret = m_parent->MakeInterfaceResult(iret, iid);
+ break;
+ }
+ case nsXPTType::T_ARRAY: {
+ if ( (* ((void **)ns_v.ptr)) == NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ }
+ if (!PyInt_Check(td.extra)) {
+ PyErr_SetString(PyExc_TypeError, "The array info is not valid");
+ break;
+ }
+ PRUint8 array_type = (PRUint8)PyInt_AsLong(td.extra);
+ PRUint32 seq_size = GetSizeIs(index, PR_FALSE);
+ nsXPTCVariant &ns_viid = m_var_array[td.argnum];
+ nsIID iid;
+ nsresult res = GetArrayElementIID(m_parent,
+ m_var_array,
+ m_methodindex,
+ index,
+ &iid);
+ ret = UnpackSingleArray(m_parent, * ((void **)ns_v.ptr),
+ seq_size, array_type&XPT_TDP_TAGMASK,
+ NS_SUCCEEDED(res) ? &iid : NULL);
+ break;
+ }
+
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ if (*((char **)ns_v.ptr) == NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ PRUint32 string_size = GetSizeIs(index, PR_TRUE);
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromStringAndSize( *((char **)ns_v.ptr), string_size );
+#else
+ ret = PyUnicode_FromStringAndSize( *((char **)ns_v.ptr), string_size );
+#endif
+ }
+ break;
+
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ if (*((PRUnichar **)ns_v.ptr) == NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ PRUint32 string_size = GetSizeIs(index, PR_TRUE);
+ ret = PyUnicode_FromPRUnichar( *((PRUnichar **)ns_v.ptr), string_size );
+ }
+ break;
+ default:
+ PyErr_Format(PyExc_ValueError, "Unknown XPCOM type code (0x%x)", XPT_TDP_TAG(ns_v.type));
+ /* ret remains nsnull */
+ break;
+ }
+ return ret;
+}
+
+
+PyObject *PyXPCOM_InterfaceVariantHelper::MakePythonResult()
+{
+ // First we count the results.
+ int i = 0;
+ int n_results = 0;
+ PyObject *ret = NULL;
+ PRBool have_retval = PR_FALSE;
+ for (i=0;i<m_num_array;i++) {
+ PythonTypeDescriptor &td = m_python_type_desc_array[i];
+ if (!td.is_auto_out) {
+ if (XPT_PD_IS_OUT(td.param_flags) || XPT_PD_IS_DIPPER(td.param_flags))
+ n_results++;
+ if (XPT_PD_IS_RETVAL(td.param_flags))
+ have_retval = PR_TRUE;
+ }
+ }
+ if (n_results==0) {
+ ret = Py_None;
+ Py_INCREF(ret);
+ } else {
+ if (n_results > 1) {
+ ret = PyTuple_New(n_results);
+ if (ret==NULL)
+ return NULL;
+ }
+ int ret_index = 0;
+ int max_index = m_num_array;
+ // Stick the retval at the front if we have have
+ if (have_retval && n_results > 1) {
+ PyObject *val = MakeSinglePythonResult(m_num_array-1);
+ if (val==NULL) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+ PyTuple_SET_ITEM(ret, 0, val);
+ max_index--;
+ ret_index++;
+
+ }
+ for (i=0;ret_index < n_results && i < max_index;i++) {
+ if (!m_python_type_desc_array[i].is_auto_out) {
+ if (XPT_PD_IS_OUT(m_python_type_desc_array[i].param_flags) || XPT_PD_IS_DIPPER(m_python_type_desc_array[i].param_flags)) {
+ PyObject *val = MakeSinglePythonResult(i);
+ if (val==NULL) {
+ Py_XDECREF(ret);
+ return NULL;
+ }
+ if (n_results > 1) {
+ PyTuple_SET_ITEM(ret, ret_index, val);
+ ret_index++;
+ } else {
+ NS_ABORT_IF_FALSE(ret==NULL, "shouldnt already have a ret!");
+ ret = val;
+ }
+ }
+ }
+ }
+
+ }
+ return ret;
+}
+
+/*************************************************************************
+**************************************************************************
+
+ Helpers when IMPLEMENTING interfaces.
+
+**************************************************************************
+*************************************************************************/
+
+PyXPCOM_GatewayVariantHelper::PyXPCOM_GatewayVariantHelper( PyG_Base *gw, int method_index, const nsXPTMethodInfo *info, nsXPTCMiniVariant* params )
+{
+ m_params = params;
+ m_info = info;
+ // no references added - this class is only alive for
+ // a single gateway invocation
+ m_gateway = gw;
+ m_method_index = method_index;
+ m_python_type_desc_array = NULL;
+ m_num_type_descs = 0;
+}
+
+PyXPCOM_GatewayVariantHelper::~PyXPCOM_GatewayVariantHelper()
+{
+ delete [] m_python_type_desc_array;
+}
+
+PyObject *PyXPCOM_GatewayVariantHelper::MakePyArgs()
+{
+ NS_PRECONDITION(sizeof(XPTParamDescriptor) == sizeof(nsXPTParamInfo), "We depend on nsXPTParamInfo being a wrapper over the XPTParamDescriptor struct");
+ // Setup our array of Python typedescs, and determine the number of objects we
+ // pass to Python.
+ m_num_type_descs = m_info->num_args;
+ m_python_type_desc_array = new PythonTypeDescriptor[m_num_type_descs];
+ if (m_python_type_desc_array==nsnull)
+ return PyErr_NoMemory();
+
+ // First loop to count the number of objects
+ // we pass to Python
+ int i;
+ for (i=0;i<m_info->num_args;i++) {
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+i;
+ PythonTypeDescriptor &td = m_python_type_desc_array[i];
+ td.param_flags = pi->flags;
+ td.type_flags = pi->type.prefix.flags;
+ td.argnum = pi->type.argnum;
+ td.argnum2 = pi->type.argnum2;
+ }
+ int num_args = ProcessPythonTypeDescriptors(m_python_type_desc_array, m_num_type_descs);
+ PyObject *ret = PyTuple_New(num_args);
+ if (ret==NULL)
+ return NULL;
+ int this_arg = 0;
+ for (i=0;i<m_num_type_descs;i++) {
+ PythonTypeDescriptor &td = m_python_type_desc_array[i];
+ if (XPT_PD_IS_IN(td.param_flags) && !td.is_auto_in && !XPT_PD_IS_DIPPER(td.param_flags)) {
+ PyObject *sub = MakeSingleParam( i, td );
+ if (sub==NULL) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+ NS_ABORT_IF_FALSE(this_arg>=0 && this_arg<num_args, "We are going off the end of the array!");
+ PyTuple_SET_ITEM(ret, this_arg, sub);
+ this_arg++;
+ }
+ }
+ return ret;
+}
+
+PRBool PyXPCOM_GatewayVariantHelper::CanSetSizeIs( int var_index, PRBool is_arg1 )
+{
+ NS_ABORT_IF_FALSE(var_index < m_num_type_descs, "var_index param is invalid");
+ PRUint8 argnum = is_arg1 ?
+ m_python_type_desc_array[var_index].argnum :
+ m_python_type_desc_array[var_index].argnum2;
+ NS_ABORT_IF_FALSE(argnum < m_num_type_descs, "size_is param is invalid");
+ return XPT_PD_IS_OUT(m_python_type_desc_array[argnum].param_flags);
+}
+
+PRBool PyXPCOM_GatewayVariantHelper::SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size)
+{
+ NS_ABORT_IF_FALSE(var_index < m_num_type_descs, "var_index param is invalid");
+ PRUint8 argnum = is_arg1 ?
+ m_python_type_desc_array[var_index].argnum :
+ m_python_type_desc_array[var_index].argnum2;
+ NS_ABORT_IF_FALSE(argnum < m_num_type_descs, "size_is param is invalid");
+ PythonTypeDescriptor &td_size = m_python_type_desc_array[argnum];
+ NS_ABORT_IF_FALSE( XPT_PD_IS_OUT(td_size.param_flags), "size param must be out if we want to set it!");
+ NS_ABORT_IF_FALSE(td_size.is_auto_out, "Setting size_is, but param is not marked as auto!");
+
+ nsXPTCMiniVariant &ns_v = m_params[argnum];
+ NS_ABORT_IF_FALSE( (td_size.type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_U32, "size param must be Uint32");
+ NS_ABORT_IF_FALSE(ns_v.val.p, "NULL pointer for size_is value!");
+ if (ns_v.val.p) {
+ if (!td_size.have_set_auto) {
+ *((PRUint32 *)ns_v.val.p) = new_size;
+ td_size.have_set_auto = PR_TRUE;
+ } else {
+ if (*((PRUint32 *)ns_v.val.p) != new_size ) {
+ PyErr_Format(PyExc_ValueError, "Array lengths inconsistent; array size previously set to %d, but second array is of size %d", ns_v.val.u32, new_size);
+ return PR_FALSE;
+ }
+ }
+ }
+ return PR_TRUE;
+}
+
+PRUint32 PyXPCOM_GatewayVariantHelper::GetSizeIs( int var_index, PRBool is_arg1)
+{
+ NS_ABORT_IF_FALSE(var_index < m_num_type_descs, "var_index param is invalid");
+ PRUint8 argnum = is_arg1 ?
+ m_python_type_desc_array[var_index].argnum :
+ m_python_type_desc_array[var_index].argnum2;
+ NS_ABORT_IF_FALSE(argnum < m_num_type_descs, "size_is param is invalid");
+ if (argnum >= m_num_type_descs) {
+ PyErr_SetString(PyExc_ValueError, "dont have a valid size_is indicator for this param");
+ return PR_FALSE;
+ }
+ PRBool is_out = XPT_PD_IS_OUT(m_python_type_desc_array[argnum].param_flags);
+ nsXPTCMiniVariant &ns_v = m_params[argnum];
+ NS_ABORT_IF_FALSE( (m_python_type_desc_array[argnum].type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_U32, "size param must be Uint32");
+ return is_out ? *((PRUint32 *)ns_v.val.p) : ns_v.val.u32;
+}
+
+#undef DEREF_IN_OR_OUT
+#define DEREF_IN_OR_OUT( element, ret_type ) (ret_type)(is_out ? *((ret_type *)ns_v.val.p) : (ret_type)(element))
+
+PyObject *PyXPCOM_GatewayVariantHelper::MakeSingleParam(int index, PythonTypeDescriptor &td)
+{
+ NS_PRECONDITION(XPT_PD_IS_IN(td.param_flags), "Must be an [in] param!");
+ nsXPTCMiniVariant &ns_v = m_params[index];
+ PyObject *ret = NULL;
+ PRBool is_out = XPT_PD_IS_OUT(td.param_flags);
+
+ switch (td.type_flags & XPT_TDP_TAGMASK) {
+ case nsXPTType::T_I8:
+ ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.i8, PRInt8 ) );
+ break;
+ case nsXPTType::T_I16:
+ ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.i16, PRInt16) );
+ break;
+ case nsXPTType::T_I32:
+ ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.i32, PRInt32) );
+ break;
+ case nsXPTType::T_I64:
+ ret = PyLong_FromLongLong( DEREF_IN_OR_OUT(ns_v.val.i64, PRInt64) );
+ break;
+ case nsXPTType::T_U8:
+ ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.u8, PRUint8) );
+ break;
+ case nsXPTType::T_U16:
+ ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.u16, PRUint16) );
+ break;
+ case nsXPTType::T_U32:
+ ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.u32, PRUint32) );
+ break;
+ case nsXPTType::T_U64:
+ ret = PyLong_FromUnsignedLongLong( DEREF_IN_OR_OUT(ns_v.val.u64, PRUint64) );
+ break;
+ case nsXPTType::T_FLOAT:
+ ret = PyFloat_FromDouble( DEREF_IN_OR_OUT(ns_v.val.f, float) );
+ break;
+ case nsXPTType::T_DOUBLE:
+ ret = PyFloat_FromDouble( DEREF_IN_OR_OUT(ns_v.val.d, double) );
+ break;
+ case nsXPTType::T_BOOL: {
+ PRBool temp = DEREF_IN_OR_OUT(ns_v.val.b, PRBool);
+ ret = temp ? Py_True : Py_False;
+ Py_INCREF(ret);
+ break;
+ }
+ case nsXPTType::T_CHAR: {
+ char temp = DEREF_IN_OR_OUT(ns_v.val.c, char);
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromStringAndSize(&temp, 1);
+#else
+ ret = PyUnicode_FromStringAndSize(&temp, 1);
+#endif
+ break;
+ }
+ case nsXPTType::T_WCHAR: {
+ PRUnichar temp = (PRUnichar)DEREF_IN_OR_OUT(ns_v.val.wc, PRUnichar);
+ ret = PyUnicode_FromPRUnichar(&temp, 1);
+ break;
+ }
+// case nsXPTType::T_VOID:
+ case nsXPTType::T_IID: {
+ ret = Py_nsIID::PyObjectFromIID( * DEREF_IN_OR_OUT(ns_v.val.p, const nsIID *) );
+ break;
+ }
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING: {
+ NS_ABORT_IF_FALSE(is_out || !XPT_PD_IS_DIPPER(td.param_flags), "DOMStrings can't be inout");
+ const nsAString *rs = (const nsAString *)ns_v.val.p;
+ ret = PyObject_FromNSString(*rs);
+ break;
+ }
+ case nsXPTType::T_CSTRING:
+ case nsXPTType::T_UTF8STRING: {
+ NS_ABORT_IF_FALSE(is_out || !XPT_PD_IS_DIPPER(td.param_flags), "DOMStrings can't be inout");
+ const nsCString *rs = (const nsCString *)ns_v.val.p;
+ ret = PyObject_FromNSString(*rs, (td.type_flags & XPT_TDP_TAGMASK)==nsXPTType::T_UTF8STRING);
+ break;
+ }
+ case nsXPTType::T_CHAR_STR: {
+ char *t = DEREF_IN_OR_OUT(ns_v.val.p, char *);
+ if (t==NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromString(t);
+#else
+ ret = PyUnicode_FromString(t);
+#endif
+ break;
+ }
+
+ case nsXPTType::T_WCHAR_STR: {
+ PRUnichar *us = DEREF_IN_OR_OUT(ns_v.val.p, PRUnichar *);
+ if (us==NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ ret = PyUnicode_FromPRUnichar( us, nsCRT::strlen(us));
+ }
+ break;
+ }
+ case nsXPTType::T_INTERFACE_IS: // our Python code does it :-)
+ case nsXPTType::T_INTERFACE: {
+ nsISupports *iret = DEREF_IN_OR_OUT(ns_v.val.p, nsISupports *);
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+index;
+ ret = m_gateway->MakeInterfaceParam(iret, NULL, m_method_index, pi, index);
+ break;
+ }
+/***
+ nsISupports *iret = DEREF_IN_OR_OUT(ns_v.val.p, nsISupports *);
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+index;
+ nsXPTCMiniVariant &ns_viid = m_params[td.argnum];
+ NS_ABORT_IF_FALSE((m_python_type_desc_array[td.argnum].type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_IID, "The INTERFACE_IS iid describer isnt an IID!");
+ const nsIID * iid = NULL;
+ if (XPT_PD_IS_IN(m_python_type_desc_array[td.argnum].param_flags))
+ // may still be inout!
+ iid = DEREF_IN_OR_OUT(ns_v.val.p, const nsIID *);
+
+ ret = m_gateway->MakeInterfaceParam(iret, iid, m_method_index, pi, index);
+ break;
+ }
+****/
+ case nsXPTType::T_ARRAY: {
+ void *t = DEREF_IN_OR_OUT(ns_v.val.p, void *);
+ if (t==NULL) {
+ // JS may send us a NULL here occasionally - as the
+ // type is array, we silently convert this to a zero
+ // length list, a-la JS.
+ ret = PyList_New(0);
+ } else {
+ PRUint8 array_type;
+ nsIID *piid;
+ nsresult ns = GetArrayType(index, &array_type, &piid);
+ if (NS_FAILED(ns)) {
+ PyXPCOM_BuildPyException(ns);
+ break;
+ }
+ PRUint32 seq_size = GetSizeIs(index, PR_FALSE);
+ ret = UnpackSingleArray(NULL, t, seq_size, array_type&XPT_TDP_TAGMASK, piid);
+ }
+ break;
+ }
+ case nsXPTType::T_PSTRING_SIZE_IS: {
+ char *t = DEREF_IN_OR_OUT(ns_v.val.p, char *);
+ PRUint32 string_size = GetSizeIs(index, PR_TRUE);
+ if (t==NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromStringAndSize(t, string_size);
+#else
+ ret = PyUnicode_FromStringAndSize(t, string_size);
+#endif
+ break;
+ }
+ case nsXPTType::T_PWSTRING_SIZE_IS: {
+ PRUnichar *t = DEREF_IN_OR_OUT(ns_v.val.p, PRUnichar *);
+ PRUint32 string_size = GetSizeIs(index, PR_TRUE);
+ if (t==NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ ret = PyUnicode_FromPRUnichar(t, string_size);
+ }
+ break;
+ }
+ default:
+ // As this is called by external components,
+ // we return _something_ rather than failing before any user code has run!
+ {
+ char buf[128];
+ sprintf(buf, "Unknown XPCOM type flags (0x%x)", td.type_flags);
+ PyXPCOM_LogWarning("%s - returning a string object with this message!\n", buf);
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromString(buf);
+#else
+ ret = PyUnicode_FromString(buf);
+#endif
+ break;
+ }
+ }
+ return ret;
+}
+
+nsresult PyXPCOM_GatewayVariantHelper::GetArrayType(PRUint8 index, PRUint8 *ret, nsIID **iid)
+{
+ nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
+ NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+ NS_ABORT_IF_FALSE(iim != nsnull, "Cant get interface from IIM!");
+ if (iim==nsnull)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIInterfaceInfo> ii;
+ nsresult rc = iim->GetInfoForIID( &m_gateway->m_iid, getter_AddRefs(ii));
+ if (NS_FAILED(rc))
+ return rc;
+ nsXPTType datumType;
+ const nsXPTParamInfo& param_info = m_info->GetParam((PRUint8)index);
+ rc = ii->GetTypeForParam(m_method_index, &param_info, 1, &datumType);
+ if (NS_FAILED(rc))
+ return rc;
+ if (iid) {
+ *iid = (nsIID *)&NS_GET_IID(nsISupports);
+ if (XPT_TDP_TAG(datumType)==nsXPTType::T_INTERFACE ||
+ XPT_TDP_TAG(datumType)==nsXPTType::T_INTERFACE_IS ||
+ XPT_TDP_TAG(datumType)==nsXPTType::T_ARRAY)
+ ii->GetIIDForParam(m_method_index, &param_info, iid);
+ }
+ *ret = datumType.flags;
+ return NS_OK;
+}
+
+PRBool PyXPCOM_GatewayVariantHelper::GetIIDForINTERFACE_ID(int index, const nsIID **ppret)
+{
+ // Not sure if the IID pointed at by by this is allows to be
+ // in or out, so we will allow it.
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+index;
+ nsXPTType typ = pi->GetType();
+ NS_WARN_IF_FALSE(XPT_TDP_TAG(typ) == nsXPTType::T_IID, "INTERFACE_IS IID param isnt an IID!");
+ NS_ABORT_IF_FALSE(typ.IsPointer(), "Expecting to re-fill a pointer value.");
+ if (XPT_TDP_TAG(typ) != nsXPTType::T_IID)
+ *ppret = &NS_GET_IID(nsISupports);
+ else {
+ nsXPTCMiniVariant &ns_v = m_params[index];
+ if (pi->IsOut()) {
+ nsIID **pp = (nsIID **)ns_v.val.p;
+ if (pp && *pp)
+ *ppret = *pp;
+ else
+ *ppret = &NS_GET_IID(nsISupports);
+ } else if (pi->IsIn()) {
+ nsIID *p = (nsIID *)ns_v.val.p;
+ if (p)
+ *ppret = p;
+ else
+ *ppret = &NS_GET_IID(nsISupports);
+ } else {
+ NS_ERROR("Param is not in or out!");
+ *ppret = &NS_GET_IID(nsISupports);
+ }
+ }
+ return PR_TRUE;
+}
+
+nsIInterfaceInfo *PyXPCOM_GatewayVariantHelper::GetInterfaceInfo()
+{
+ if (!m_interface_info) {
+ nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
+ NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+ if (iim)
+ iim->GetInfoForIID(&m_gateway->m_iid, getter_AddRefs(m_interface_info));
+ }
+ return m_interface_info;
+}
+
+#undef FILL_SIMPLE_POINTER
+#define FILL_SIMPLE_POINTER( type, ob ) *((type *)ns_v.val.p) = (type)(ob)
+
+nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index)
+{
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+index;
+ NS_ABORT_IF_FALSE(pi->IsOut() || pi->IsDipper(), "The value must be marked as [out] (or a dipper) to be back-filled!");
+ NS_ABORT_IF_FALSE(!pi->IsShared(), "Dont know how to back-fill a shared out param");
+ nsXPTCMiniVariant &ns_v = m_params[index];
+
+ nsXPTType typ = pi->GetType();
+ PyObject* val_use = NULL;
+
+ NS_ABORT_IF_FALSE(pi->IsDipper() || ns_v.val.p, "No space for result!");
+ if (!pi->IsDipper() && !ns_v.val.p) return NS_ERROR_INVALID_POINTER;
+
+ PRBool rc = PR_TRUE;
+ switch (XPT_TDP_TAG(typ)) {
+ case nsXPTType::T_I8:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt8, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_I16:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt16, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_I32:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt32, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_I64:
+ if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt64, PyLong_AsLongLong(val_use) );
+ break;
+ case nsXPTType::T_U8:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint8, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_U16:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint16, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_U32:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint32, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_U64:
+ if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint64, PyLong_AsUnsignedLongLong(val_use) );
+ break;
+ case nsXPTType::T_FLOAT:
+ if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
+ FILL_SIMPLE_POINTER( float, PyFloat_AsDouble(val_use) );
+ break;
+ case nsXPTType::T_DOUBLE:
+ if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
+ FILL_SIMPLE_POINTER( double, PyFloat_AsDouble(val_use) );
+ break;
+ case nsXPTType::T_BOOL:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ FILL_SIMPLE_POINTER( PRBool, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_CHAR:
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+ FILL_SIMPLE_POINTER( char, *PyString_AS_STRING(val_use) );
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+# ifndef Py_LIMITED_API
+ FILL_SIMPLE_POINTER( char, *PyUnicode_AS_UNICODE(val) );
+# else
+ FILL_SIMPLE_POINTER( char, PyUnicode_ReadChar(val, 0) );
+# endif
+#endif
+ break;
+
+ case nsXPTType::T_WCHAR:
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a Unicode object");
+ BREAK_FALSE;
+ }
+#endif
+ if ((val_use = PyUnicode_FromObject(val))==NULL)
+ BREAK_FALSE;
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+ // Lossy!
+#ifndef Py_LIMITED_API
+ FILL_SIMPLE_POINTER( PRUnichar, *PyUnicode_AS_UNICODE(val_use) );
+#else
+ FILL_SIMPLE_POINTER( PRUnichar, PyUnicode_ReadChar(val_use, 0) );
+#endif
+ break;
+
+// case nsXPTType::T_VOID:
+ case nsXPTType::T_IID: {
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(val, &iid))
+ BREAK_FALSE;
+ nsIID **pp = (nsIID **)ns_v.val.p;
+ // If there is an existing [in] IID, free it.
+ if (*pp && pi->IsIn())
+ nsMemory::Free(*pp);
+ *pp = (nsIID *)nsMemory::Alloc(sizeof(nsIID));
+ if (*pp==NULL) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ memcpy(*pp, &iid, sizeof(iid));
+ break;
+ }
+
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING: {
+ nsAString *ws = (nsAString *)ns_v.val.p;
+ NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??");
+ if (!PyObject_AsNSString(val, *ws))
+ BREAK_FALSE;
+ break;
+ }
+ case nsXPTType::T_CSTRING: {
+ nsCString *ws = (nsCString *)ns_v.val.p;
+ NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??");
+ if (val == Py_None) {
+ NS_ABORT_IF_FALSE(0, "dont handle None here yet");
+ } else {
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ val_use = PyObject_Str(val);
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+ const char *sz = PyString_AS_STRING(val_use);
+ ws->Assign(sz, PyString_GET_SIZE(val_use));
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ val_use = PyUnicode_AsUTF8String(val);
+ const char *sz = PyBytes_AS_STRING(val_use);
+ ws->Assign(sz, PyBytes_GET_SIZE(val_use));
+#endif
+ }
+ break;
+ }
+ case nsXPTType::T_UTF8STRING: {
+ nsCString *ws = (nsCString *)ns_v.val.p;
+ NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??");
+ if (val == Py_None) {
+ NS_ABORT_IF_FALSE(0, "dont handle None here yet");
+ } else {
+#if PY_MAJOR_VERSION <= 2
+ if (PyString_Check(val)) {
+ val_use = val;
+ Py_INCREF(val);
+ }
+ else
+#endif
+ if (PyUnicode_Check(val)) {
+ val_use = PyUnicode_AsUTF8String(val);
+ } else {
+#if PY_MAJOR_VERSION <= 2
+ PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be string or Unicode objects");
+#else
+ PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be unicode objects");
+#endif
+ BREAK_FALSE;
+ }
+#if PY_MAJOR_VERSION <= 2
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "must have a string object!");
+ const char *sz = PyString_AS_STRING(val_use);
+ ws->Assign(sz, PyString_GET_SIZE(val_use));
+#else
+ NS_ABORT_IF_FALSE(PyBytes_Check(val_use), "must have a bytes object!");
+ const char *sz = PyBytes_AS_STRING(val_use);
+ ws->Assign(sz, PyBytes_GET_SIZE(val_use));
+#endif
+ }
+ break;
+ }
+
+ case nsXPTType::T_CHAR_STR: {
+ // If it is an existing string, free it.
+ char **pp = (char **)ns_v.val.p;
+ if (*pp && pi->IsIn())
+ nsMemory::Free(*pp);
+ *pp = nsnull;
+
+ if (val == Py_None)
+ break; // Remains NULL.
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+
+ const char *sz = PyString_AS_STRING(val_use);
+ int nch = PyString_GET_SIZE(val_use);
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_AsUTF8String(val))==NULL)
+ BREAK_FALSE;
+
+ const char *sz = PyBytes_AS_STRING(val_use);
+ int nch = PyBytes_GET_SIZE(val_use);
+#endif
+
+ *pp = (char *)nsMemory::Alloc(nch+1);
+ if (*pp==NULL) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ strncpy(*pp, sz, nch+1);
+ break;
+ }
+ case nsXPTType::T_WCHAR_STR: {
+ // If it is an existing string, free it.
+ PRUnichar **pp = (PRUnichar **)ns_v.val.p;
+ if (*pp && pi->IsIn())
+ nsMemory::Free(*pp);
+ *pp = nsnull;
+ if (val == Py_None)
+ break; // Remains NULL.
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ val_use = PyUnicode_FromObject(val);
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ val_use = val;
+ Py_INCREF(val_use);
+#endif
+ if (PyUnicode_AsPRUnichar(val_use, pp, NULL) < 0)
+ BREAK_FALSE;
+ break;
+ }
+ case nsXPTType::T_INTERFACE: {
+ nsISupports *pnew = nsnull;
+ // Find out what IID we are declared to use.
+ nsIID *iid = NULL;
+ nsIInterfaceInfo *ii = GetInterfaceInfo();
+ if (ii)
+ ii->GetIIDForParam(m_method_index, pi, &iid);
+
+ // Get it the "standard" way.
+ // We do allow NULL here, even tho doing so will no-doubt crash some objects.
+ // (but there will certainly be objects out there that will allow NULL :-(
+ nsIID iid_use = iid ? *iid : NS_GET_IID(nsISupports);
+ if (!Py_nsISupports::InterfaceFromPyObject(val, iid_use, &pnew, PR_TRUE))
+ BREAK_FALSE;
+ nsISupports **pp = (nsISupports **)ns_v.val.p;
+ if (*pp && pi->IsIn()) {
+ Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
+ (*pp)->Release();
+ Py_END_ALLOW_THREADS;
+ }
+
+ *pp = pnew; // ref-count added by InterfaceFromPyObject
+ break;
+ }
+ case nsXPTType::T_INTERFACE_IS: {
+ const nsIID *piid;
+ if (!GetIIDForINTERFACE_ID(pi->type.argnum, &piid))
+ BREAK_FALSE;
+
+ nsISupports *pnew = nsnull;
+ // Get it the "standard" way.
+ // We do allow NULL here, even tho doing so will no-doubt crash some objects.
+ // (but there will certainly be objects out there that will allow NULL :-(
+ if (!Py_nsISupports::InterfaceFromPyObject(val, *piid, &pnew, PR_TRUE))
+ BREAK_FALSE;
+ nsISupports **pp = (nsISupports **)ns_v.val.p;
+ if (*pp && pi->IsIn()) {
+ Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
+ (*pp)->Release();
+ Py_END_ALLOW_THREADS;
+ }
+
+ *pp = pnew; // ref-count added by InterfaceFromPyObject
+ break;
+ }
+
+ case nsXPTType::T_PSTRING_SIZE_IS: {
+ const char *sz = nsnull;
+ PRUint32 nch = 0;
+ if (val != Py_None) {
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+
+ sz = PyString_AS_STRING(val_use);
+ nch = PyString_GET_SIZE(val_use);
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_AsUTF8String(val))==NULL)
+ BREAK_FALSE;
+
+ sz = PyBytes_AS_STRING(val_use);
+ nch = PyBytes_GET_SIZE(val_use);
+#endif
+ }
+ PRBool bBackFill = PR_FALSE;
+ PRBool bCanSetSizeIs = CanSetSizeIs(index, PR_TRUE);
+ // If we can not change the size, check our sequence is correct.
+ if (!bCanSetSizeIs) {
+ PRUint32 existing_size = GetSizeIs(index, PR_TRUE);
+ if (nch != existing_size) {
+ PyErr_Format(PyExc_ValueError, "This function is expecting a string of exactly length %d - %d characters were passed", existing_size, nch);
+ BREAK_FALSE;
+ }
+ // It we have an "inout" param, but an "in" count, then
+ // it is probably a buffer the caller expects us to
+ // fill in-place!
+ bBackFill = pi->IsIn();
+ }
+ if (bBackFill) {
+ memcpy(*(char **)ns_v.val.p, sz, nch);
+ } else {
+ // If we have an existing string, free it!
+ char **pp = (char **)ns_v.val.p;
+ if (*pp && pi->IsIn())
+ nsMemory::Free(*pp);
+ *pp = nsnull;
+ if (sz==nsnull) // None specified.
+ break; // Remains NULL.
+ *pp = (char *)nsMemory::Alloc(nch);
+ if (*pp==NULL) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ memcpy(*pp, sz, nch);
+ if (bCanSetSizeIs)
+ rc = SetSizeIs(index, PR_TRUE, nch);
+ else {
+ NS_ABORT_IF_FALSE(GetSizeIs(index, PR_TRUE) == nch, "Can't set sizeis, but string isnt correct size");
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_PWSTRING_SIZE_IS: {
+ PRUnichar *sz = nsnull;
+ PRUint32 nch = 0;
+ PRUint32 nbytes = 0;
+
+ if (val != Py_None) {
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ val_use = PyUnicode_FromObject(val);
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ val_use = val;
+ Py_INCREF(val_use);
+#endif
+ if (PyUnicode_AsPRUnichar(val_use, &sz, &nch) < 0)
+ BREAK_FALSE;
+ nbytes = sizeof(PRUnichar) * nch;
+ }
+ PRBool bBackFill = PR_FALSE;
+ PRBool bCanSetSizeIs = CanSetSizeIs(index, PR_TRUE);
+ // If we can not change the size, check our sequence is correct.
+ if (!bCanSetSizeIs) {
+ // It is a buffer the caller prolly wants us to fill in-place!
+ PRUint32 existing_size = GetSizeIs(index, PR_TRUE);
+ if (nch != existing_size) {
+ PyErr_Format(PyExc_ValueError, "This function is expecting a string of exactly length %d - %d characters were passed", existing_size, nch);
+ BREAK_FALSE;
+ }
+ // It we have an "inout" param, but an "in" count, then
+ // it is probably a buffer the caller expects us to
+ // fill in-place!
+ bBackFill = pi->IsIn();
+ }
+ if (bBackFill) {
+ memcpy(*(PRUnichar **)ns_v.val.p, sz, nbytes);
+ } else {
+ // If it is an existing string, free it.
+ PRUnichar **pp = (PRUnichar **)ns_v.val.p;
+ if (*pp && pi->IsIn())
+ nsMemory::Free(*pp);
+ *pp = sz;
+ sz = nsnull;
+ if (bCanSetSizeIs)
+ rc = SetSizeIs(index, PR_TRUE, nch);
+ else {
+ NS_ABORT_IF_FALSE(GetSizeIs(index, PR_TRUE) == nch, "Can't set sizeis, but string isnt correct size");
+ }
+ }
+ if (sz)
+ nsMemory::Free(sz);
+ break;
+ }
+ case nsXPTType::T_ARRAY: {
+ // If it is an existing array of the correct size, keep it.
+ PRUint32 sequence_size = 0;
+ PRUint8 array_type;
+ nsIID *piid;
+ nsresult ns = GetArrayType(index, &array_type, &piid);
+ if (NS_FAILED(ns))
+ return ns;
+ PRUint32 element_size = GetArrayElementSize(array_type);
+ if (val != Py_None) {
+ if (!PySequence_Check(val)) {
+ PyErr_Format(PyExc_TypeError, "Object for xpcom array must be a sequence, not type '%s'", PyXPCOM_ObTypeName(val));
+ BREAK_FALSE;
+ }
+ sequence_size = PySequence_Length(val);
+ }
+ PRUint32 existing_size = GetSizeIs(index, PR_FALSE);
+ PRBool bBackFill = PR_FALSE;
+ PRBool bCanSetSizeIs = CanSetSizeIs(index, PR_FALSE);
+ // If we can not change the size, check our sequence is correct.
+ if (!bCanSetSizeIs) {
+ // It is a buffer the caller prolly wants us to fill in-place!
+ if (sequence_size != existing_size) {
+ PyErr_Format(PyExc_ValueError, "This function is expecting a sequence of exactly length %d - %d items were passed", existing_size, sequence_size);
+ BREAK_FALSE;
+ }
+ // It we have an "inout" param, but an "in" count, then
+ // it is probably a buffer the caller expects us to
+ // fill in-place!
+ bBackFill = pi->IsIn();
+ }
+ if (bBackFill)
+ rc = FillSingleArray(*(void **)ns_v.val.p, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK, piid);
+ else {
+ // If it is an existing array, free it.
+ void **pp = (void **)ns_v.val.p;
+ if (*pp && pi->IsIn()) {
+ FreeSingleArray(*pp, existing_size, array_type);
+ nsMemory::Free(*pp);
+ }
+ *pp = nsnull;
+ if (val == Py_None)
+ break; // Remains NULL.
+ size_t nbytes = sequence_size * element_size;
+ if (nbytes==0) nbytes = 1; // avoid assertion about 0 bytes
+ *pp = (void *)nsMemory::Alloc(nbytes);
+ memset(*pp, 0, nbytes);
+ rc = FillSingleArray(*pp, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK, piid);
+ if (!rc) break;
+ if (bCanSetSizeIs)
+ rc = SetSizeIs(index, PR_FALSE, sequence_size);
+ else {
+ NS_ABORT_IF_FALSE(GetSizeIs(index, PR_FALSE) == sequence_size, "Can't set sizeis, but string isnt correct size");
+ }
+ }
+ break;
+ }
+ default:
+ // try and limp along in this case.
+ // leave rc TRUE
+ PyXPCOM_LogWarning("Converting Python object for an [out] param - The object type (0x%x) is unknown - leaving param alone!\n", XPT_TDP_TAG(typ));
+ break;
+ }
+ Py_XDECREF(val_use);
+ if (!rc)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+nsresult PyXPCOM_GatewayVariantHelper::ProcessPythonResult(PyObject *ret_ob)
+{
+ // NOTE - although we return an nresult, if we leave a Python
+ // exception set, then our caller may take additional action
+ // (ie, translating our nsresult to a more appropriate nsresult
+ // for the Python exception.)
+ NS_PRECONDITION(!PyErr_Occurred(), "Expecting no Python exception to be pending when processing the return result");
+
+ nsresult rc = NS_OK;
+ // If we dont get a tuple back, then the result is only
+ // an int nresult for the underlying function.
+ // (ie, the policy is expected to return (NS_OK, user_retval),
+ // but can also return (say), NS_ERROR_FAILURE
+ if (PyInt_Check(ret_ob))
+ return PyInt_AsLong(ret_ob);
+ // Now it must be the tuple.
+ if (!PyTuple_Check(ret_ob) ||
+ PyTuple_Size(ret_ob)!=2 ||
+ !PyInt_Check(PyTuple_GET_ITEM(ret_ob, 0))) {
+ PyErr_SetString(PyExc_TypeError, "The Python result must be a single integer or a tuple of length==2 and first item an int.");
+ return NS_ERROR_FAILURE;
+ }
+ PyObject *user_result = PyTuple_GET_ITEM(ret_ob, 1);
+ // Count up how many results our function needs.
+ int i;
+ int num_results = 0;
+ int last_result = -1; // optimization if we only have one - this is it!
+ int index_retval = -1;
+ for (i=0;i<m_num_type_descs;i++) {
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+i;
+ if (!m_python_type_desc_array[i].is_auto_out) {
+ if (pi->IsOut() || pi->IsDipper()) {
+ num_results++;
+ last_result = i;
+ }
+ if (pi->IsRetval())
+ index_retval = i;
+ }
+ }
+
+ if (num_results==0) {
+ ; // do nothing
+ } else if (num_results==1) {
+ // May or may not be the nominated retval - who cares!
+ NS_ABORT_IF_FALSE(last_result >=0 && last_result < m_num_type_descs, "Have one result, but dont know its index!");
+ rc = BackFillVariant( user_result, last_result );
+ } else {
+ // Loop over each one, filling as we go.
+ // We allow arbitary sequences here, but _not_ strings
+ // or Unicode!
+ // NOTE - We ALWAYS do the nominated retval first.
+ // The Python pattern is always:
+ // return retval [, byref1 [, byref2 ...] ]
+ // But the retval is often the last param described in the info.
+ if (!PySequence_Check(user_result) ||
+#if PY_MAJOR_VERSION <= 2
+ PyString_Check(user_result) ||
+#else
+ PyBytes_Check(user_result) ||
+#endif
+ PyUnicode_Check(user_result)) {
+ PyErr_SetString(PyExc_TypeError, "This function has multiple results, but a sequence was not given to fill them");
+ return NS_ERROR_FAILURE;
+ }
+ int num_user_results = PySequence_Length(user_result);
+ // If they havent given enough, we dont really care.
+ // although a warning is probably appropriate.
+ if (num_user_results != num_results) {
+ const char *method_name = m_info->GetName();
+ PyXPCOM_LogWarning("The method '%s' has %d out params, but %d were supplied by the Python code\n",
+ method_name,
+ num_results,
+ num_user_results);
+ }
+ int this_py_index = 0;
+ if (index_retval != -1) {
+ // We always return the nominated result first!
+ PyObject *sub = PySequence_GetItem(user_result, 0);
+ if (sub==NULL)
+ return NS_ERROR_FAILURE;
+ rc = BackFillVariant(sub, index_retval);
+ Py_DECREF(sub);
+ this_py_index = 1;
+ }
+ for (i=0;NS_SUCCEEDED(rc) && i<m_info->GetParamCount();i++) {
+ // If weve already done it, or dont need to do it!
+ if (i==index_retval || m_python_type_desc_array[i].is_auto_out)
+ continue;
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+i;
+ if (pi->IsOut()) {
+ PyObject *sub = PySequence_GetItem(user_result, this_py_index);
+ if (sub==NULL)
+ return NS_ERROR_FAILURE;
+ rc = BackFillVariant(sub, i);
+ Py_DECREF(sub);
+ this_py_index++;
+ }
+ }
+ }
+ return rc;
+}
diff --git a/src/libs/xpcom18a4/python/src/dllmain.cpp b/src/libs/xpcom18a4/python/src/dllmain.cpp
new file mode 100644
index 00000000..4cc08578
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/dllmain.cpp
@@ -0,0 +1,352 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <prthread.h>
+#include "nsIThread.h"
+#include "nsILocalFile.h"
+
+#ifdef XP_WIN
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include "windows.h"
+#endif
+
+static PRInt32 g_cLockCount = 0;
+static PRLock *g_lockMain = nsnull;
+
+PYXPCOM_EXPORT PyObject *PyXPCOM_Error = NULL;
+
+PyXPCOM_INTERFACE_DEFINE(Py_nsIComponentManager, nsIComponentManager, PyMethods_IComponentManager)
+PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfoManager, nsIInterfaceInfoManager, PyMethods_IInterfaceInfoManager)
+PyXPCOM_INTERFACE_DEFINE(Py_nsIEnumerator, nsIEnumerator, PyMethods_IEnumerator)
+PyXPCOM_INTERFACE_DEFINE(Py_nsISimpleEnumerator, nsISimpleEnumerator, PyMethods_ISimpleEnumerator)
+PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfo, nsIInterfaceInfo, PyMethods_IInterfaceInfo)
+PyXPCOM_INTERFACE_DEFINE(Py_nsIInputStream, nsIInputStream, PyMethods_IInputStream)
+PyXPCOM_INTERFACE_DEFINE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassInfo)
+PyXPCOM_INTERFACE_DEFINE(Py_nsIVariant, nsIVariant, PyMethods_IVariant)
+// deprecated, but retained for backward compatibility:
+PyXPCOM_INTERFACE_DEFINE(Py_nsIComponentManagerObsolete, nsIComponentManagerObsolete, PyMethods_IComponentManagerObsolete)
+
+#ifndef PYXPCOM_USE_PYGILSTATE
+
+////////////////////////////////////////////////////////////
+// Thread-state helpers/global functions.
+// Only used if there is no Python PyGILState_* API
+//
+static PyThreadState *ptsGlobal = nsnull;
+PyInterpreterState *PyXPCOM_InterpreterState = nsnull;
+PRUintn tlsIndex = 0;
+
+
+// This function must be called at some time when the interpreter lock and state is valid.
+// Called by init{module} functions and also COM factory entry point.
+void PyXPCOM_InterpreterState_Ensure()
+{
+ if (PyXPCOM_InterpreterState==NULL) {
+ PyThreadState *threadStateSave = PyThreadState_Swap(NULL);
+ if (threadStateSave==NULL)
+ Py_FatalError("Can not setup interpreter state, as current state is invalid");
+
+ PyXPCOM_InterpreterState = threadStateSave->interp;
+ PyThreadState_Swap(threadStateSave);
+ }
+}
+
+void PyXPCOM_InterpreterState_Free()
+{
+ PyXPCOM_ThreadState_Free();
+ PyXPCOM_InterpreterState = NULL; // Eek - should I be freeing something?
+}
+
+// This structure is stored in the TLS slot. At this stage only a Python thread state
+// is kept, but this may change in the future...
+struct ThreadData{
+ PyThreadState *ts;
+};
+
+// Ensure that we have a Python thread state available to use.
+// If this is called for the first time on a thread, it will allocate
+// the thread state. This does NOT change the state of the Python lock.
+// Returns TRUE if a new thread state was created, or FALSE if a
+// thread state already existed.
+PRBool PyXPCOM_ThreadState_Ensure()
+{
+ ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
+ if (pData==NULL) { /* First request on this thread */
+ /* Check we have an interpreter state */
+ if (PyXPCOM_InterpreterState==NULL) {
+ Py_FatalError("Can not setup thread state, as have no interpreter state");
+ }
+ pData = (ThreadData *)nsMemory::Alloc(sizeof(ThreadData));
+ if (!pData)
+ Py_FatalError("Out of memory allocating thread state.");
+ memset(pData, 0, sizeof(*pData));
+ if (NS_FAILED( PR_SetThreadPrivate( tlsIndex, pData ) ) ) {
+ NS_ABORT_IF_FALSE(0, "Could not create thread data for this thread!");
+ Py_FatalError("Could not thread private thread data!");
+ }
+ pData->ts = PyThreadState_New(PyXPCOM_InterpreterState);
+ return PR_TRUE; // Did create a thread state state
+ }
+ return PR_FALSE; // Thread state was previously created
+}
+
+// Asuming we have a valid thread state, acquire the Python lock.
+void PyXPCOM_InterpreterLock_Acquire()
+{
+ ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
+ NS_ABORT_IF_FALSE(pData, "Have no thread data for this thread!");
+ PyThreadState *thisThreadState = pData->ts;
+ PyEval_AcquireThread(thisThreadState);
+}
+
+// Asuming we have a valid thread state, release the Python lock.
+void PyXPCOM_InterpreterLock_Release()
+{
+ ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
+ NS_ABORT_IF_FALSE(pData, "Have no thread data for this thread!");
+ PyThreadState *thisThreadState = pData->ts;
+ PyEval_ReleaseThread(thisThreadState);
+}
+
+// Free the thread state for the current thread
+// (Presumably previously create with a call to
+// PyXPCOM_ThreadState_Ensure)
+void PyXPCOM_ThreadState_Free()
+{
+ ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
+ if (!pData) return;
+ PyThreadState *thisThreadState = pData->ts;
+ PyThreadState_Delete(thisThreadState);
+ PR_SetThreadPrivate(tlsIndex, NULL);
+ nsMemory::Free(pData);
+}
+
+void PyXPCOM_ThreadState_Clear()
+{
+ ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
+ PyThreadState *thisThreadState = pData->ts;
+ PyThreadState_Clear(thisThreadState);
+}
+#endif // PYXPCOM_USE_PYGILSTATE
+
+////////////////////////////////////////////////////////////
+// Lock/exclusion global functions.
+//
+void PyXPCOM_AcquireGlobalLock(void)
+{
+ NS_PRECONDITION(g_lockMain != nsnull, "Cant acquire a NULL lock!");
+ PR_Lock(g_lockMain);
+}
+void PyXPCOM_ReleaseGlobalLock(void)
+{
+ NS_PRECONDITION(g_lockMain != nsnull, "Cant release a NULL lock!");
+ PR_Unlock(g_lockMain);
+}
+
+void PyXPCOM_DLLAddRef(void)
+{
+ // Must be thread-safe, although cant have the Python lock!
+ CEnterLeaveXPCOMFramework _celf;
+ PRInt32 cnt = PR_AtomicIncrement(&g_cLockCount);
+ if (cnt==1) { // First call
+ if (!Py_IsInitialized()) {
+ Py_Initialize();
+ // Make sure our Windows framework is all setup.
+ PyXPCOM_Globals_Ensure();
+ // Make sure we have _something_ as sys.argv.
+ if (PySys_GetObject((char*)"argv")==NULL) {
+ PyObject *path = PyList_New(0);
+#if PY_MAJOR_VERSION <= 2
+ PyObject *str = PyString_FromString("");
+#else
+ PyObject *str = PyUnicode_FromString("");
+#endif
+ PyList_Append(path, str);
+ PySys_SetObject((char*)"argv", path);
+ Py_XDECREF(path);
+ Py_XDECREF(str);
+ }
+
+ // Must force Python to start using thread locks, as
+ // we are free-threaded (maybe, I think, sometimes :-)
+ PyEval_InitThreads();
+#ifndef PYXPCOM_USE_PYGILSTATE
+ // Release Python lock, as first thing we do is re-get it.
+ ptsGlobal = PyEval_SaveThread();
+#endif
+ // NOTE: We never finalize Python!!
+ }
+ }
+}
+void PyXPCOM_DLLRelease(void)
+{
+ PR_AtomicDecrement(&g_cLockCount);
+}
+
+void pyxpcom_construct(void)
+{
+ g_lockMain = PR_NewLock();
+#ifndef PYXPCOM_USE_PYGILSTATE
+ PRStatus status;
+ status = PR_NewThreadPrivateIndex( &tlsIndex, NULL );
+ NS_WARN_IF_FALSE(status==0, "Could not allocate TLS storage");
+ if (NS_FAILED(status)) {
+ PR_DestroyLock(g_lockMain);
+ return; // PR_FALSE;
+ }
+#endif // PYXPCOM_USE_PYGILSTATE
+ return; // PR_TRUE;
+}
+
+void pyxpcom_destruct(void)
+{
+ PR_DestroyLock(g_lockMain);
+#ifndef PYXPCOM_USE_PYGILSTATE
+ // I can't locate a way to kill this -
+ // should I pass a dtor to PR_NewThreadPrivateIndex??
+ // TlsFree(tlsIndex);
+#endif // PYXPCOM_USE_PYGILSTATE
+}
+
+// Yet another attempt at cross-platform library initialization and finalization.
+struct DllInitializer {
+ DllInitializer() {
+ pyxpcom_construct();
+ }
+ ~DllInitializer() {
+ pyxpcom_destruct();
+ }
+} dll_initializer;
+
+////////////////////////////////////////////////////////////
+// Other helpers/global functions.
+//
+PRBool PyXPCOM_Globals_Ensure()
+{
+ PRBool rc = PR_TRUE;
+
+#ifndef PYXPCOM_USE_PYGILSTATE
+ PyXPCOM_InterpreterState_Ensure();
+#endif
+
+ // The exception object - we load it from .py code!
+ if (PyXPCOM_Error == NULL) {
+ rc = PR_FALSE;
+ PyObject *mod = NULL;
+
+ mod = PyImport_ImportModule("xpcom");
+ if (mod!=NULL) {
+ PyXPCOM_Error = PyObject_GetAttrString(mod, "Exception");
+ Py_DECREF(mod);
+ }
+ rc = (PyXPCOM_Error != NULL);
+ }
+ if (!rc)
+ return rc;
+
+ static PRBool bHaveInitXPCOM = PR_FALSE;
+ if (!bHaveInitXPCOM) {
+ nsCOMPtr<nsIThread> thread_check;
+ // xpcom appears to assert if already initialized
+ // Is there an official way to determine this?
+ if (NS_FAILED(nsIThread::GetMainThread(getter_AddRefs(thread_check)))) {
+ // not already initialized.
+#ifdef XP_WIN
+ // On Windows, we need to locate the Mozilla bin
+ // directory. This by using locating a Moz DLL we depend
+ // on, and assume it lives in that bin dir. Different
+ // moz build types (eg, xulrunner, suite) package
+ // XPCOM itself differently - but all appear to require
+ // nspr4.dll - so this is what we use.
+ char landmark[MAX_PATH+1];
+ HMODULE hmod = GetModuleHandle("nspr4.dll");
+ if (hmod==NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "We dont appear to be linked against nspr4.dll.");
+ return PR_FALSE;
+ }
+ GetModuleFileName(hmod, landmark, sizeof(landmark)/sizeof(landmark[0]));
+ char *end = landmark + (strlen(landmark)-1);
+ while (end > landmark && *end != '\\')
+ end--;
+ if (end > landmark) *end = '\0';
+
+ nsCOMPtr<nsILocalFile> ns_bin_dir;
+ NS_ConvertASCIItoUCS2 strLandmark(landmark);
+ NS_NewLocalFile(strLandmark, PR_FALSE, getter_AddRefs(ns_bin_dir));
+ nsresult rv = NS_InitXPCOM2(nsnull, ns_bin_dir, nsnull);
+#else
+ // Elsewhere, Mozilla can find it itself (we hope!)
+ nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+#endif // XP_WIN
+ if (NS_FAILED(rv)) {
+ PyErr_SetString(PyExc_RuntimeError, "The XPCOM subsystem could not be initialized");
+ return PR_FALSE;
+ }
+ }
+ // Even if xpcom was already init, we want to flag it as init!
+ bHaveInitXPCOM = PR_TRUE;
+ // Register our custom interfaces.
+
+ Py_nsISupports::InitType();
+ Py_nsIComponentManager::InitType();
+ Py_nsIInterfaceInfoManager::InitType();
+ Py_nsIEnumerator::InitType();
+ Py_nsISimpleEnumerator::InitType();
+ Py_nsIInterfaceInfo::InitType();
+ Py_nsIInputStream::InitType();
+ Py_nsIClassInfo::InitType();
+ Py_nsIVariant::InitType();
+ // for backward compatibility:
+ Py_nsIComponentManagerObsolete::InitType();
+
+ }
+ return rc;
+}
+
diff --git a/src/libs/xpcom18a4/python/src/loader/pyloader.cpp b/src/libs/xpcom18a4/python/src/loader/pyloader.cpp
new file mode 100644
index 00000000..dc116f1d
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/loader/pyloader.cpp
@@ -0,0 +1,435 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// pyloader
+//
+// Not part of the main Python _xpcom package, but a separate, thin DLL.
+//
+// The main loader and registrar for Python. A thin DLL that is designed to live in
+// the xpcom "components" directory. Simply locates and loads the standard
+// pyxpcom core library and transfers control to that.
+
+#include <PyXPCOM.h>
+
+#include "nsDirectoryServiceDefs.h"
+#include "nsILocalFile.h"
+
+#include "nspr.h" // PR_fprintf
+
+#if (PY_VERSION_HEX >= 0x02030000)
+#define PYXPCOM_USE_PYGILSTATE
+#endif
+
+static char *PyTraceback_AsString(PyObject *exc_tb);
+
+#ifdef XP_WIN
+#include "windows.h"
+#endif
+
+#ifdef XP_UNIX
+#include <dlfcn.h>
+#include <sys/stat.h>
+
+#endif
+
+#include "nsITimelineService.h"
+
+typedef nsresult (*pfnPyXPCOM_NSGetModule)(nsIComponentManager *servMgr,
+ nsIFile* location,
+ nsIModule** result);
+
+
+static void LogError(const char *fmt, ...);
+static void LogDebug(const char *fmt, ...);
+
+// Ensure that any paths guaranteed by this package exist on sys.path
+// Only called once as we are first loaded into the process.
+void AddStandardPaths()
+{
+ // Put {bin}\Python on the path if it exists.
+ nsresult rv;
+ nsCOMPtr<nsIFile> aFile;
+ rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, getter_AddRefs(aFile));
+ if (NS_FAILED(rv)) {
+ LogError("The Python XPCOM loader could not locate the 'bin' directory\n");
+ return;
+ }
+ aFile->Append(NS_LITERAL_STRING("python"));
+ nsAutoString pathBuf;
+ aFile->GetPath(pathBuf);
+ PyObject *obPath = PySys_GetObject("path");
+ if (!obPath) {
+ LogError("The Python XPCOM loader could not get the Python sys.path variable\n");
+ return;
+ }
+ NS_LossyConvertUCS2toASCII pathCBuf(pathBuf);
+ LogDebug("The Python XPCOM loader is adding '%s' to sys.path\n", pathCBuf.get());
+ PyObject *newStr = PyString_FromString(pathCBuf.get());
+ PyList_Insert(obPath, 0, newStr);
+ Py_XDECREF(newStr);
+ // And now try and get Python to process this directory as a "site dir"
+ // - ie, look for .pth files, etc
+ nsCAutoString cmdBuf(NS_LITERAL_CSTRING("import site;site.addsitedir(r'") + pathCBuf + NS_LITERAL_CSTRING("')\n"));
+ if (0 != PyRun_SimpleString((char *)cmdBuf.get())) {
+ LogError("The directory '%s' could not be added as a site directory", pathCBuf.get());
+ PyErr_Clear();
+ }
+ // and somewhat like Python itself (site, citecustomize), we attempt
+ // to import "sitepyxpcom" ignoring ImportError
+ if (NULL==PyImport_ImportModule("sitepyxpcom")) {
+ if (!PyErr_ExceptionMatches(PyExc_ImportError))
+ LogError("Failed to import 'sitepyxpcom'");
+ PyErr_Clear();
+ }
+}
+
+////////////////////////////////////////////////////////////
+// This is the main entry point that delegates into Python
+nsresult PyXPCOM_NSGetModule(nsIComponentManager *servMgr,
+ nsIFile* location,
+ nsIModule** result)
+{
+ NS_PRECONDITION(result!=NULL, "null result pointer in PyXPCOM_NSGetModule!");
+ NS_PRECONDITION(location!=NULL, "null nsIFile pointer in PyXPCOM_NSGetModule!");
+ NS_PRECONDITION(servMgr!=NULL, "null servMgr pointer in PyXPCOM_NSGetModule!");
+#ifndef LOADER_LINKS_WITH_PYTHON
+ if (!Py_IsInitialized()) {
+ Py_Initialize();
+ if (!Py_IsInitialized()) {
+ PyXPCOM_LogError("Python initialization failed!\n");
+ return NS_ERROR_FAILURE;
+ }
+ PyEval_InitThreads();
+#ifndef PYXPCOM_USE_PYGILSTATE
+ PyXPCOM_InterpreterState_Ensure();
+#endif
+ PyEval_SaveThread();
+ }
+#endif // LOADER_LINKS_WITH_PYTHON
+ CEnterLeavePython _celp;
+ PyObject *func = NULL;
+ PyObject *obServMgr = NULL;
+ PyObject *obLocation = NULL;
+ PyObject *wrap_ret = NULL;
+ PyObject *args = NULL;
+ PyObject *mod = PyImport_ImportModule("xpcom.server");
+ if (!mod) goto done;
+ func = PyObject_GetAttrString(mod, "NS_GetModule");
+ if (func==NULL) goto done;
+ obServMgr = Py_nsISupports::PyObjectFromInterface(servMgr, NS_GET_IID(nsIComponentManager));
+ if (obServMgr==NULL) goto done;
+ obLocation = Py_nsISupports::PyObjectFromInterface(location, NS_GET_IID(nsIFile));
+ if (obLocation==NULL) goto done;
+ args = Py_BuildValue("OO", obServMgr, obLocation);
+ if (args==NULL) goto done;
+ wrap_ret = PyEval_CallObject(func, args);
+ if (wrap_ret==NULL) goto done;
+ Py_nsISupports::InterfaceFromPyObject(wrap_ret, NS_GET_IID(nsIModule), (nsISupports **)result, PR_FALSE, PR_FALSE);
+done:
+ nsresult nr = NS_OK;
+ if (PyErr_Occurred()) {
+ PyXPCOM_LogError("Obtaining the module object from Python failed.\n");
+ nr = PyXPCOM_SetCOMErrorFromPyException();
+ }
+ Py_XDECREF(func);
+ Py_XDECREF(obServMgr);
+ Py_XDECREF(obLocation);
+ Py_XDECREF(wrap_ret);
+ Py_XDECREF(mod);
+ Py_XDECREF(args);
+ return nr;
+}
+
+extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
+ nsIFile* location,
+ nsIModule** result)
+{
+#ifdef XP_UNIX
+ // *sob* - seems necessary to open the .so as RTLD_GLOBAL
+ dlopen(PYTHON_SO,RTLD_NOW | RTLD_GLOBAL);
+#endif
+ PRBool bDidInitPython = !Py_IsInitialized(); // well, I will next line, anyway :-)
+ if (bDidInitPython) {
+ NS_TIMELINE_START_TIMER("PyXPCOM: Python initializing");
+ Py_Initialize();
+ if (!Py_IsInitialized()) {
+ LogError("Python initialization failed!\n");
+ return NS_ERROR_FAILURE;
+ }
+#ifndef NS_DEBUG
+ Py_OptimizeFlag = 1;
+#endif // NS_DEBUG
+ PyEval_InitThreads();
+ NS_TIMELINE_STOP_TIMER("PyXPCOM: Python initializing");
+ NS_TIMELINE_MARK_TIMER("PyXPCOM: Python initializing");
+ }
+ // Get the Python interpreter state
+ NS_TIMELINE_START_TIMER("PyXPCOM: Python threadstate setup");
+#ifndef PYXPCOM_USE_PYGILSTATE
+ PyThreadState *threadStateCreated = NULL;
+ PyThreadState *threadState = PyThreadState_Swap(NULL);
+ if (threadState==NULL) {
+ // no thread-state - set one up.
+ // *sigh* - what I consider a bug is that Python
+ // will deadlock unless we own the lock before creating
+ // a new interpreter (it appear Py_NewInterpreter has
+ // really only been tested/used with no thread lock
+ PyEval_AcquireLock();
+ threadState = threadStateCreated = Py_NewInterpreter();
+ PyThreadState_Swap(NULL);
+ }
+ PyEval_ReleaseLock();
+ PyEval_AcquireThread(threadState);
+#else
+ PyGILState_STATE state = PyGILState_Ensure();
+#endif // PYXPCOM_USE_PYGILSTATE
+#ifdef MOZ_TIMELINE
+ // If the timeline service is installed, see if we can install our hooks.
+ if (NULL==PyImport_ImportModule("timeline_hook")) {
+ if (!PyErr_ExceptionMatches(PyExc_ImportError))
+ LogError("Failed to import 'timeline_hook'");
+ PyErr_Clear(); // but don't care if we can't.
+ }
+#endif
+ // Add the standard paths always - we may not have been the first to
+ // init Python.
+ AddStandardPaths();
+
+#ifndef PYXPCOM_USE_PYGILSTATE
+ // Abandon the thread-lock, as the first thing Python does
+ // is re-establish the lock (the Python thread-state story SUCKS!!!)
+ if (threadStateCreated) {
+ Py_EndInterpreter(threadStateCreated);
+ PyEval_ReleaseLock(); // see Py_NewInterpreter call above
+ } else {
+ PyEval_ReleaseThread(threadState);
+ PyThreadState *threadStateSave = PyThreadState_Swap(NULL);
+ if (threadStateSave)
+ PyThreadState_Delete(threadStateSave);
+ }
+#else
+ // If we initialized Python, then we will also have acquired the thread
+ // lock. In that case, we want to leave it unlocked, so other threads
+ // are free to run, even if they aren't running Python code.
+ PyGILState_Release(bDidInitPython ? PyGILState_UNLOCKED : state);
+#endif
+
+ NS_TIMELINE_STOP_TIMER("PyXPCOM: Python threadstate setup");
+ NS_TIMELINE_MARK_TIMER("PyXPCOM: Python threadstate setup");
+ NS_TIMELINE_START_TIMER("PyXPCOM: PyXPCOM NSGetModule entry point");
+ nsresult rc = PyXPCOM_NSGetModule(servMgr, location, result);
+ NS_TIMELINE_STOP_TIMER("PyXPCOM: PyXPCOM NSGetModule entry point");
+ NS_TIMELINE_MARK_TIMER("PyXPCOM: PyXPCOM NSGetModule entry point");
+ return rc;
+}
+
+// The internal helper that actually moves the
+// formatted string to the target!
+
+void LogMessage(const char *prefix, const char *pszMessageText)
+{
+ PR_fprintf(PR_STDERR, "%s", pszMessageText);
+}
+
+void LogMessage(const char *prefix, nsACString &text)
+{
+ LogMessage(prefix, nsPromiseFlatCString(text).get());
+}
+
+// A helper for the various logging routines.
+static void VLogF(const char *prefix, const char *fmt, va_list argptr)
+{
+ char buff[512];
+
+ vsprintf(buff, fmt, argptr);
+
+ LogMessage(prefix, buff);
+}
+
+static void LogError(const char *fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+ VLogF("PyXPCOM Loader Error: ", fmt, marker);
+ // If we have a Python exception, also log that:
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
+ if (exc_typ) {
+ nsCAutoString streamout;
+
+ if (exc_tb) {
+ const char *szTraceback = PyTraceback_AsString(exc_tb);
+ if (szTraceback == NULL)
+ streamout += "Can't get the traceback info!";
+ else {
+ streamout += "Traceback (most recent call last):\n";
+ streamout += szTraceback;
+ PyMem_Free((void *)szTraceback);
+ }
+ }
+ PyObject *temp = PyObject_Str(exc_typ);
+ if (temp) {
+ streamout += PyString_AsString(temp);
+ Py_DECREF(temp);
+ } else
+ streamout += "Can convert exception to a string!";
+ streamout += ": ";
+ if (exc_val != NULL) {
+ temp = PyObject_Str(exc_val);
+ if (temp) {
+ streamout += PyString_AsString(temp);
+ Py_DECREF(temp);
+ } else
+ streamout += "Can convert exception value to a string!";
+ }
+ streamout += "\n";
+ LogMessage("PyXPCOM Exception:", streamout);
+ }
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+ va_end(marker);
+}
+/*** - not currently used - silence compiler warning.
+static void LogWarning(const char *fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+ VLogF("PyXPCOM Loader Warning: ", fmt, marker);
+}
+***/
+#ifdef DEBUG
+static void LogDebug(const char *fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+ VLogF("PyXPCOM Loader Debug: ", fmt, marker);
+ va_end(marker);
+}
+#else
+static void LogDebug(const char *fmt, ...)
+{
+}
+#endif
+
+/* Obtains a string from a Python traceback.
+ This is the exact same string as "traceback.print_exc" would return.
+
+ Pass in a Python traceback object (probably obtained from PyErr_Fetch())
+ Result is a string which must be free'd using PyMem_Free()
+*/
+#define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;}
+
+char *PyTraceback_AsString(PyObject *exc_tb)
+{
+ char *errMsg = NULL; /* a static that hold a local error message */
+ char *result = NULL; /* a valid, allocated result. */
+ PyObject *modStringIO = NULL;
+ PyObject *modTB = NULL;
+ PyObject *obFuncStringIO = NULL;
+ PyObject *obStringIO = NULL;
+ PyObject *obFuncTB = NULL;
+ PyObject *argsTB = NULL;
+ PyObject *obResult = NULL;
+
+ /* Import the modules we need - cStringIO and traceback */
+ modStringIO = PyImport_ImportModule("cStringIO");
+ if (modStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant import cStringIO\n");
+
+ modTB = PyImport_ImportModule("traceback");
+ if (modTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant import traceback\n");
+ /* Construct a cStringIO object */
+ obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
+ if (obFuncStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant find cStringIO.StringIO\n");
+ obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
+ if (obStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cStringIO.StringIO() failed\n");
+ /* Get the traceback.print_exception function, and call it. */
+ obFuncTB = PyObject_GetAttrString(modTB, "print_tb");
+ if (obFuncTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant find traceback.print_tb\n");
+
+ argsTB = Py_BuildValue("OOO",
+ exc_tb ? exc_tb : Py_None,
+ Py_None,
+ obStringIO);
+ if (argsTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant make print_tb arguments\n");
+
+ obResult = PyObject_CallObject(obFuncTB, argsTB);
+ if (obResult==NULL)
+ TRACEBACK_FETCH_ERROR("traceback.print_tb() failed\n");
+ /* Now call the getvalue() method in the StringIO instance */
+ Py_DECREF(obFuncStringIO);
+ obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
+ if (obFuncStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant find getvalue function\n");
+ Py_DECREF(obResult);
+ obResult = PyObject_CallObject(obFuncStringIO, NULL);
+ if (obResult==NULL)
+ TRACEBACK_FETCH_ERROR("getvalue() failed.\n");
+
+ /* And it should be a string all ready to go - duplicate it. */
+ if (!PyString_Check(obResult))
+ TRACEBACK_FETCH_ERROR("getvalue() did not return a string\n");
+
+ { // a temp scope so I can use temp locals.
+ char *tempResult = PyString_AsString(obResult);
+ result = (char *)PyMem_Malloc(strlen(tempResult)+1);
+ if (result==NULL)
+ TRACEBACK_FETCH_ERROR("memory error duplicating the traceback string");
+
+ strcpy(result, tempResult);
+ } // end of temp scope.
+done:
+ /* All finished - first see if we encountered an error */
+ if (result==NULL && errMsg != NULL) {
+ result = (char *)PyMem_Malloc(strlen(errMsg)+1);
+ if (result != NULL)
+ /* if it does, not much we can do! */
+ strcpy(result, errMsg);
+ }
+ Py_XDECREF(modStringIO);
+ Py_XDECREF(modTB);
+ Py_XDECREF(obFuncStringIO);
+ Py_XDECREF(obStringIO);
+ Py_XDECREF(obFuncTB);
+ Py_XDECREF(argsTB);
+ Py_XDECREF(obResult);
+ return result;
+}
diff --git a/src/libs/xpcom18a4/python/src/module/_xpcom.cpp b/src/libs/xpcom18a4/python/src/module/_xpcom.cpp
new file mode 100644
index 00000000..d40d2b52
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/module/_xpcom.cpp
@@ -0,0 +1,950 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM.h"
+#include "nsXPCOM.h"
+#include "nsISupportsPrimitives.h"
+#include "nsIFile.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIComponentManagerObsolete.h"
+#include "nsIConsoleService.h"
+#include "nspr.h" // PR_fprintf
+#ifdef VBOX
+# include "nsEventQueueUtils.h"
+#endif
+
+#ifdef XP_WIN
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include "windows.h"
+#endif
+
+#include "nsIEventQueue.h"
+#include "nsIProxyObjectManager.h"
+
+#define LOADER_LINKS_WITH_PYTHON
+
+#ifndef PYXPCOM_USE_PYGILSTATE
+extern PYXPCOM_EXPORT void PyXPCOM_InterpreterState_Ensure();
+#endif
+
+#ifdef VBOX_PYXPCOM
+# include <iprt/cdefs.h>
+# include <VBox/com/com.h>
+# ifndef MODULE_NAME_SUFFIX
+# define MANGLE_MODULE_NAME(a_szName) a_szName
+# define MANGLE_MODULE_INIT(a_Name) a_Name
+# else
+# define MANGLE_MODULE_NAME(a_szName) a_szName RT_XSTR(MODULE_NAME_SUFFIX)
+# define MANGLE_MODULE_INIT(a_Name) RT_CONCAT(a_Name, MODULE_NAME_SUFFIX)
+# endif
+# if defined(VBOX_PYXPCOM_VERSIONED) && !defined(VBOX_PYXPCOM_MAJOR_VERSIONED)
+# if PY_VERSION_HEX >= 0x030a0000 && PY_VERSION_HEX < 0x030b0000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_10")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_10)
+
+# elif PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_9")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_9)
+
+# elif PY_VERSION_HEX >= 0x03080000 && PY_VERSION_HEX < 0x03090000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_8")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_8)
+
+# elif PY_VERSION_HEX >= 0x03070000 && PY_VERSION_HEX < 0x03080000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_7")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_7)
+
+# elif PY_VERSION_HEX >= 0x03060000 && PY_VERSION_HEX < 0x03070000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_6")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_6)
+
+# elif PY_VERSION_HEX >= 0x03050000 && PY_VERSION_HEX < 0x03060000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_5")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_5)
+
+# elif PY_VERSION_HEX >= 0x03040000 && PY_VERSION_HEX < 0x03050000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_4")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_4)
+
+# elif PY_VERSION_HEX >= 0x03030000 && PY_VERSION_HEX < 0x03040000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_3")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_3)
+
+# elif PY_VERSION_HEX >= 0x03020000 && PY_VERSION_HEX < 0x03030000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_2")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_2)
+
+# elif PY_VERSION_HEX >= 0x03010000 && PY_VERSION_HEX < 0x03020000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_1")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_1)
+
+# elif PY_VERSION_HEX >= 0x02080000 && PY_VERSION_HEX < 0x02090000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython2_8")
+# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython2_8)
+
+# elif PY_VERSION_HEX >= 0x02070000 && PY_VERSION_HEX < 0x02080000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython2_7")
+# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython2_7)
+
+# elif PY_VERSION_HEX >= 0x02060000 && PY_VERSION_HEX < 0x02070000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython2_6")
+# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython2_6)
+# else
+# error "Fix module versioning. This Python version is not recognized."
+# endif
+# else
+# if PY_MAJOR_VERSION <= 2 && defined(VBOX_PYXPCOM_MAJOR_VERSIONED)
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython2")
+# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython2)
+# elif PY_MAJOR_VERSION <= 2
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython")
+# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython)
+# elif defined(Py_LIMITED_API) || defined(VBOX_PYXPCOM_MAJOR_VERSIONED)
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3)
+# else
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython)
+# endif
+# endif
+#else
+#define MODULE_NAME "_xpcom"
+#endif
+
+// "boot-strap" methods - interfaces we need to get the base
+// interface support!
+
+#ifndef VBOX
+/* deprecated, included for backward compatibility */
+static PyObject *
+PyXPCOMMethod_NS_GetGlobalComponentManager(PyObject *self, PyObject *args)
+{
+ if (PyErr_Warn(PyExc_DeprecationWarning, "Use GetComponentManager instead") < 0)
+ return NULL;
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ nsCOMPtr<nsIComponentManager> cm;
+ nsresult rv;
+ Py_BEGIN_ALLOW_THREADS;
+ rv = NS_GetComponentManager(getter_AddRefs(cm));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(rv) )
+ return PyXPCOM_BuildPyException(rv);
+
+ nsCOMPtr<nsIComponentManagerObsolete> ocm(do_QueryInterface(cm, &rv));
+ if ( NS_FAILED(rv) )
+ return PyXPCOM_BuildPyException(rv);
+
+ return Py_nsISupports::PyObjectFromInterface(ocm, NS_GET_IID(nsIComponentManagerObsolete), PR_FALSE);
+}
+#endif
+
+static PyObject *
+PyXPCOMMethod_GetComponentManager(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ nsCOMPtr<nsIComponentManager> cm;
+ nsresult rv;
+ Py_BEGIN_ALLOW_THREADS;
+ rv = NS_GetComponentManager(getter_AddRefs(cm));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(rv) )
+ return PyXPCOM_BuildPyException(rv);
+
+ return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsIComponentManager), PR_FALSE);
+}
+
+// No xpcom callable way to get at the registrar, even though the interface
+// is scriptable.
+static PyObject *
+PyXPCOMMethod_GetComponentRegistrar(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ nsCOMPtr<nsIComponentRegistrar> cm;
+ nsresult rv;
+ Py_BEGIN_ALLOW_THREADS;
+ rv = NS_GetComponentRegistrar(getter_AddRefs(cm));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(rv) )
+ return PyXPCOM_BuildPyException(rv);
+
+ return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsISupports), PR_FALSE);
+}
+
+static PyObject *
+PyXPCOMMethod_GetServiceManager(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ nsCOMPtr<nsIServiceManager> sm;
+ nsresult rv;
+ Py_BEGIN_ALLOW_THREADS;
+ rv = NS_GetServiceManager(getter_AddRefs(sm));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(rv) )
+ return PyXPCOM_BuildPyException(rv);
+
+ // Return a type based on the IID.
+ return Py_nsISupports::PyObjectFromInterface(sm, NS_GET_IID(nsIServiceManager));
+}
+
+#ifndef VBOX
+/* deprecated, included for backward compatibility */
+static PyObject *
+PyXPCOMMethod_GetGlobalServiceManager(PyObject *self, PyObject *args)
+{
+ if (PyErr_Warn(PyExc_DeprecationWarning, "Use GetServiceManager instead") < 0)
+ return NULL;
+
+ return PyXPCOMMethod_GetComponentManager(self, args);
+}
+#endif
+
+static PyObject *
+PyXPCOMMethod_XPTI_GetInterfaceInfoManager(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ nsIInterfaceInfoManager* im;
+ Py_BEGIN_ALLOW_THREADS;
+ im = XPTI_GetInterfaceInfoManager();
+ Py_END_ALLOW_THREADS;
+ if ( im == nsnull )
+ return PyXPCOM_BuildPyException(NS_ERROR_FAILURE);
+
+ /* Return a type based on the IID (with no extra ref) */
+ // Can not auto-wrap the interface info manager as it is critical to
+ // building the support we need for autowrap.
+ PyObject *ret = Py_nsISupports::PyObjectFromInterface(im, NS_GET_IID(nsIInterfaceInfoManager), PR_FALSE);
+ NS_IF_RELEASE(im);
+ return ret;
+}
+
+static PyObject *
+PyXPCOMMethod_XPTC_InvokeByIndex(PyObject *self, PyObject *args)
+{
+ PyObject *obIS, *obParams;
+ nsCOMPtr<nsISupports> pis;
+ int index;
+
+ // We no longer rely on PyErr_Occurred() for our error state,
+ // but keeping this assertion can't hurt - it should still always be true!
+ NS_WARN_IF_FALSE(!PyErr_Occurred(), "Should be no pending Python error!");
+
+ if (!PyArg_ParseTuple(args, "OiO", &obIS, &index, &obParams))
+ return NULL;
+
+ if (!Py_nsISupports::Check(obIS)) {
+ return PyErr_Format(PyExc_TypeError,
+ "First param must be a native nsISupports wrapper (got %s)",
+ PyXPCOM_ObTypeName(obIS));
+ }
+ // Ack! We must ask for the "native" interface supported by
+ // the object, not specifically nsISupports, else we may not
+ // back the same pointer (eg, Python, following identity rules,
+ // will return the "original" gateway when QI'd for nsISupports)
+ if (!Py_nsISupports::InterfaceFromPyObject(
+ obIS,
+ Py_nsIID_NULL,
+ getter_AddRefs(pis),
+ PR_FALSE))
+ return NULL;
+
+ PyXPCOM_InterfaceVariantHelper arg_helper((Py_nsISupports *)obIS, index);
+ if (!arg_helper.Init(obParams))
+ return NULL;
+
+ if (!arg_helper.FillArray())
+ return NULL;
+
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = XPTC_InvokeByIndex(pis, index, arg_helper.m_num_array, arg_helper.m_var_array);
+/** @todo bird: Maybe we could processing pending XPCOM events here to make
+ * life a bit simpler inside python? */
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ return arg_helper.MakePythonResult();
+}
+
+static PyObject *
+PyXPCOMMethod_WrapObject(PyObject *self, PyObject *args)
+{
+ PyObject *ob, *obIID;
+ int bWrapClient = 1;
+ if (!PyArg_ParseTuple(args, "OO|i", &ob, &obIID, &bWrapClient))
+ return NULL;
+
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+
+ nsCOMPtr<nsISupports> ret;
+ nsresult r = PyXPCOM_XPTStub::CreateNew(ob, iid, getter_AddRefs(ret));
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ // _ALL_ wrapped objects are associated with a weak-ref
+ // to their "main" instance.
+ AddDefaultGateway(ob, ret); // inject a weak reference to myself into the instance.
+
+ // Now wrap it in an interface.
+ return Py_nsISupports::PyObjectFromInterface(ret, iid, bWrapClient);
+}
+
+static PyObject *
+PyXPCOMMethod_UnwrapObject(PyObject *self, PyObject *args)
+{
+ PyObject *ob;
+ if (!PyArg_ParseTuple(args, "O", &ob))
+ return NULL;
+
+ nsISupports *uob = NULL;
+ nsIInternalPython *iob = NULL;
+ PyObject *ret = NULL;
+ if (!Py_nsISupports::InterfaceFromPyObject(ob,
+ NS_GET_IID(nsISupports),
+ &uob,
+ PR_FALSE))
+ goto done;
+ if (NS_FAILED(uob->QueryInterface(NS_GET_IID(nsIInternalPython), reinterpret_cast<void **>(&iob)))) {
+ PyErr_SetString(PyExc_ValueError, "This XPCOM object is not implemented by Python");
+ goto done;
+ }
+ ret = iob->UnwrapPythonObject();
+done:
+ Py_BEGIN_ALLOW_THREADS;
+ NS_IF_RELEASE(uob);
+ NS_IF_RELEASE(iob);
+ Py_END_ALLOW_THREADS;
+ return ret;
+}
+
+// @pymethod int|pythoncom|_GetInterfaceCount|Retrieves the number of interface objects currently in existance
+static PyObject *
+PyXPCOMMethod_GetInterfaceCount(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":_GetInterfaceCount"))
+ return NULL;
+ return PyInt_FromLong(_PyXPCOM_GetInterfaceCount());
+ // @comm If is occasionally a good idea to call this function before your Python program
+ // terminates. If this function returns non-zero, then you still have PythonCOM objects
+ // alive in your program (possibly in global variables).
+}
+
+#ifdef VBOX_DEBUG_LIFETIMES
+// @pymethod int|pythoncom|_DumpInterfaces|Dumps the interfaces still in existance to standard output
+static PyObject *
+PyXPCOMMethod_DumpInterfaces(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":_DumpInterfaces"))
+ return NULL;
+ return PyInt_FromLong(_PyXPCOM_DumpInterfaces());
+}
+#endif
+
+// @pymethod int|pythoncom|_GetGatewayCount|Retrieves the number of gateway objects currently in existance
+static PyObject *
+PyXPCOMMethod_GetGatewayCount(PyObject *self, PyObject *args)
+{
+ // @comm This is the number of Python object that implement COM servers which
+ // are still alive (ie, serving a client). The only way to reduce this count
+ // is to have the process which uses these PythonCOM servers release its references.
+ if (!PyArg_ParseTuple(args, ":_GetGatewayCount"))
+ return NULL;
+ return PyInt_FromLong(_PyXPCOM_GetGatewayCount());
+}
+
+static PyObject *
+PyXPCOMMethod_NS_ShutdownXPCOM(PyObject *self, PyObject *args)
+{
+ // @comm This is the number of Python object that implement COM servers which
+ // are still alive (ie, serving a client). The only way to reduce this count
+ // is to have the process which uses these PythonCOM servers release its references.
+ if (!PyArg_ParseTuple(args, ":NS_ShutdownXPCOM"))
+ return NULL;
+ nsresult nr;
+ Py_BEGIN_ALLOW_THREADS;
+ nr = NS_ShutdownXPCOM(nsnull);
+ Py_END_ALLOW_THREADS;
+
+#ifdef VBOX_DEBUG_LIFETIME
+ Py_nsISupports::dumpList();
+#endif
+
+ // Dont raise an exception - as we are probably shutting down
+ // and dont really case - just return the status
+ return PyInt_FromLong(nr);
+}
+
+static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
+
+// A hack to work around their magic constants!
+static PyObject *
+PyXPCOMMethod_GetProxyForObject(PyObject *self, PyObject *args)
+{
+ PyObject *obQueue, *obIID, *obOb;
+ int flags;
+ if (!PyArg_ParseTuple(args, "OOOi", &obQueue, &obIID, &obOb, &flags))
+ return NULL;
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ nsCOMPtr<nsISupports> pob;
+ if (!Py_nsISupports::InterfaceFromPyObject(obOb, iid, getter_AddRefs(pob), PR_FALSE))
+ return NULL;
+ nsIEventQueue *pQueue = NULL;
+ nsIEventQueue *pQueueRelease = NULL;
+
+ if (PyInt_Check(obQueue)) {
+ pQueue = (nsIEventQueue *)PyInt_AsLong(obQueue);
+ } else {
+ if (!Py_nsISupports::InterfaceFromPyObject(obQueue, NS_GET_IID(nsIEventQueue), (nsISupports **)&pQueue, PR_TRUE))
+ return NULL;
+ pQueueRelease = pQueue;
+ }
+
+ nsresult rv_proxy;
+ nsCOMPtr<nsISupports> presult;
+ Py_BEGIN_ALLOW_THREADS;
+ nsCOMPtr<nsIProxyObjectManager> proxyMgr =
+ do_GetService(kProxyObjectManagerCID, &rv_proxy);
+
+ if ( NS_SUCCEEDED(rv_proxy) ) {
+ rv_proxy = proxyMgr->GetProxyForObject(pQueue,
+ iid,
+ pob,
+ flags,
+ getter_AddRefs(presult));
+ }
+ if (pQueueRelease)
+ pQueueRelease->Release();
+ Py_END_ALLOW_THREADS;
+
+ PyObject *result;
+ if (NS_SUCCEEDED(rv_proxy) ) {
+ result = Py_nsISupports::PyObjectFromInterface(presult, iid);
+ } else {
+ result = PyXPCOM_BuildPyException(rv_proxy);
+ }
+ return result;
+}
+
+static PyObject *
+PyXPCOMMethod_MakeVariant(PyObject *self, PyObject *args)
+{
+ PyObject *ob;
+ if (!PyArg_ParseTuple(args, "O:MakeVariant", &ob))
+ return NULL;
+ nsCOMPtr<nsIVariant> pVar;
+ nsresult nr = PyObject_AsVariant(ob, getter_AddRefs(pVar));
+ if (NS_FAILED(nr))
+ return PyXPCOM_BuildPyException(nr);
+ if (pVar == nsnull) {
+ NS_ERROR("PyObject_AsVariant worked but returned a NULL ptr!");
+ return PyXPCOM_BuildPyException(NS_ERROR_UNEXPECTED);
+ }
+ return Py_nsISupports::PyObjectFromInterface(pVar, NS_GET_IID(nsIVariant));
+}
+
+static PyObject *
+PyXPCOMMethod_GetVariantValue(PyObject *self, PyObject *args)
+{
+ PyObject *ob, *obParent = NULL;
+ if (!PyArg_ParseTuple(args, "O|O:GetVariantValue", &ob, &obParent))
+ return NULL;
+
+ nsCOMPtr<nsIVariant> var;
+ if (!Py_nsISupports::InterfaceFromPyObject(ob,
+ NS_GET_IID(nsISupports),
+ getter_AddRefs(var),
+ PR_FALSE))
+ return PyErr_Format(PyExc_ValueError,
+ "Object is not an nsIVariant (got %s)",
+ PyXPCOM_ObTypeName(ob));
+
+ Py_nsISupports *parent = nsnull;
+ if (obParent && obParent != Py_None) {
+ if (!Py_nsISupports::Check(obParent)) {
+ PyErr_SetString(PyExc_ValueError,
+ "Object not an nsISupports wrapper");
+ return NULL;
+ }
+ parent = (Py_nsISupports *)obParent;
+ }
+ return PyObject_FromVariant(parent, var);
+}
+
+PyObject *PyGetSpecialDirectory(PyObject *self, PyObject *args)
+{
+ char *dirname;
+ if (!PyArg_ParseTuple(args, "s:GetSpecialDirectory", &dirname))
+ return NULL;
+ nsCOMPtr<nsIFile> file;
+ nsresult r = NS_GetSpecialDirectory(dirname, getter_AddRefs(file));
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ // returned object swallows our reference.
+ return Py_nsISupports::PyObjectFromInterface(file, NS_GET_IID(nsIFile));
+}
+
+PyObject *AllocateBuffer(PyObject *self, PyObject *args)
+{
+ int bufSize;
+ if (!PyArg_ParseTuple(args, "i", &bufSize))
+ return NULL;
+#if PY_MAJOR_VERSION <= 2
+ return PyBuffer_New(bufSize);
+#else
+ return PyBytes_FromStringAndSize(NULL, bufSize);
+#endif
+}
+
+// Writes a message to the console service. This could be done via pure
+// Python code, but is useful when the logging code is actually the
+// xpcom .py framework itself (ie, we don't want our logging framework to
+// call back into the very code generating the log messages!
+PyObject *LogConsoleMessage(PyObject *self, PyObject *args)
+{
+ char *msg;
+ if (!PyArg_ParseTuple(args, "s", &msg))
+ return NULL;
+
+ nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+ if (consoleService)
+ consoleService->LogStringMessage(NS_ConvertASCIItoUCS2(msg).get());
+ else {
+ // This either means no such service, or in shutdown - hardly worth
+ // the warning, and not worth reporting an error to Python about - its
+ // log handler would just need to catch and ignore it.
+ // And as this is only called by this logging setup, any messages should
+ // still go to stderr or a logfile.
+ NS_WARNING("pyxpcom can't log console message.");
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#ifdef VBOX
+
+# include <VBox/com/NativeEventQueue.h>
+# include <iprt/err.h>
+
+static PyObject *
+PyXPCOMMethod_WaitForEvents(PyObject *self, PyObject *args)
+{
+ long lTimeout;
+ if (!PyArg_ParseTuple(args, "l", &lTimeout))
+ return NULL;
+
+ int rc;
+ com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue();
+ NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue");
+ if (!aEventQ)
+ {
+ PyErr_SetString(PyExc_TypeError, "the main event queue is NULL");
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+
+ RTMSINTERVAL cMsTimeout = (RTMSINTERVAL)lTimeout;
+ if (lTimeout < 0 || (long)cMsTimeout != lTimeout)
+ cMsTimeout = RT_INDEFINITE_WAIT;
+ rc = aEventQ->processEventQueue(cMsTimeout);
+
+ Py_END_ALLOW_THREADS
+ if (RT_SUCCESS(rc))
+ return PyInt_FromLong(0);
+
+ if ( rc == VERR_TIMEOUT
+ || rc == VERR_INTERRUPTED)
+ return PyInt_FromLong(1);
+
+ if (rc == VERR_INVALID_CONTEXT)
+ {
+ PyErr_SetString(PyExc_Exception, "wrong thread, use the main thread");
+ return NULL;
+ }
+
+ return PyInt_FromLong(2);
+}
+
+static PyObject*
+PyXPCOMMethod_InterruptWait(PyObject *self, PyObject *args)
+{
+ com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue();
+ NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue");
+ if (!aEventQ)
+ return NULL;
+
+ int rc = aEventQ->interruptEventQueueProcessing();
+ return PyBool_FromLong(RT_SUCCESS(rc));
+}
+
+static nsresult deinitVBoxPython();
+
+static PyObject*
+PyXPCOMMethod_DeinitCOM(PyObject *self, PyObject *args)
+{
+ nsresult nr;
+ Py_BEGIN_ALLOW_THREADS;
+ nr = deinitVBoxPython();
+ Py_END_ALLOW_THREADS;
+ return PyInt_FromLong(nr);
+}
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+static PyObject*
+PyXPCOMMethod_AttachThread(PyObject *self, PyObject *args)
+{
+ nsresult rv;
+ PRInt32 result = 0;
+ nsCOMPtr<nsIEventQueueService> eqs;
+
+ // Create the Event Queue for this thread...
+ Py_BEGIN_ALLOW_THREADS;
+ eqs =
+ do_GetService(kEventQueueServiceCID, &rv);
+ Py_END_ALLOW_THREADS;
+ if (NS_FAILED(rv))
+ {
+ result = 1;
+ goto done;
+ }
+
+ Py_BEGIN_ALLOW_THREADS;
+ rv = eqs->CreateThreadEventQueue();
+ Py_END_ALLOW_THREADS;
+ if (NS_FAILED(rv))
+ {
+ result = 2;
+ goto done;
+ }
+
+ done:
+ /** @todo: better throw an exception on error */
+ return PyInt_FromLong(result);
+}
+
+static PyObject*
+PyXPCOMMethod_DetachThread(PyObject *self, PyObject *args)
+{
+ nsresult rv;
+ PRInt32 result = 0;
+ nsCOMPtr<nsIEventQueueService> eqs;
+
+ // Destroy the Event Queue for this thread...
+ Py_BEGIN_ALLOW_THREADS;
+ eqs =
+ do_GetService(kEventQueueServiceCID, &rv);
+ Py_END_ALLOW_THREADS;
+ if (NS_FAILED(rv))
+ {
+ result = 1;
+ goto done;
+ }
+
+ Py_BEGIN_ALLOW_THREADS;
+ rv = eqs->DestroyThreadEventQueue();
+ Py_END_ALLOW_THREADS;
+ if (NS_FAILED(rv))
+ {
+ result = 2;
+ goto done;
+ }
+
+ done:
+ /** @todo: better throw an exception on error */
+ return PyInt_FromLong(result);
+}
+
+#endif /* VBOX */
+
+extern PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args);
+
+static struct PyMethodDef xpcom_methods[]=
+{
+ {"GetComponentManager", PyXPCOMMethod_GetComponentManager, 1},
+ {"GetComponentRegistrar", PyXPCOMMethod_GetComponentRegistrar, 1},
+#ifndef VBOX
+ {"NS_GetGlobalComponentManager", PyXPCOMMethod_NS_GetGlobalComponentManager, 1}, // deprecated
+#endif
+ {"XPTI_GetInterfaceInfoManager", PyXPCOMMethod_XPTI_GetInterfaceInfoManager, 1},
+ {"XPTC_InvokeByIndex", PyXPCOMMethod_XPTC_InvokeByIndex, 1},
+ {"GetServiceManager", PyXPCOMMethod_GetServiceManager, 1},
+#ifndef VBOX
+ {"GetGlobalServiceManager", PyXPCOMMethod_GetGlobalServiceManager, 1}, // deprecated
+ {"IID", PyXPCOMMethod_IID, 1}, // IID is wrong - deprecated - not just IID, but CID, etc.
+#endif
+ {"ID", PyXPCOMMethod_IID, 1}, // This is the official name.
+ {"NS_ShutdownXPCOM", PyXPCOMMethod_NS_ShutdownXPCOM, 1},
+ {"WrapObject", PyXPCOMMethod_WrapObject, 1},
+ {"UnwrapObject", PyXPCOMMethod_UnwrapObject, 1},
+ {"_GetInterfaceCount", PyXPCOMMethod_GetInterfaceCount, 1},
+ {"_GetGatewayCount", PyXPCOMMethod_GetGatewayCount, 1},
+ {"getProxyForObject", PyXPCOMMethod_GetProxyForObject, 1},
+ {"GetProxyForObject", PyXPCOMMethod_GetProxyForObject, 1},
+ {"GetSpecialDirectory", PyGetSpecialDirectory, 1},
+ {"AllocateBuffer", AllocateBuffer, 1},
+ {"LogConsoleMessage", LogConsoleMessage, 1, "Write a message to the xpcom console service"},
+ {"MakeVariant", PyXPCOMMethod_MakeVariant, 1},
+ {"GetVariantValue", PyXPCOMMethod_GetVariantValue, 1},
+#ifdef VBOX
+ {"WaitForEvents", PyXPCOMMethod_WaitForEvents, 1},
+ {"InterruptWait", PyXPCOMMethod_InterruptWait, 1},
+ {"DeinitCOM", PyXPCOMMethod_DeinitCOM, 1},
+ {"AttachThread", PyXPCOMMethod_AttachThread, 1},
+ {"DetachThread", PyXPCOMMethod_DetachThread, 1},
+#endif
+#ifdef VBOX_DEBUG_LIFETIMES
+ {"_DumpInterfaces", PyXPCOMMethod_DumpInterfaces, 1},
+#endif
+ // These should no longer be used - just use the logging.getLogger('pyxpcom')...
+ /* bird: The above comment refers to LogWarning and LogError. Both now removed. */
+ { NULL }
+};
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef xpcom_module =
+{
+ PyModuleDef_HEAD_INIT,
+ MODULE_NAME, /* name of module */
+ NULL, /* module documentation */
+ -1, /* size of per-interpreter state or -1 if using globals */
+ xpcom_methods
+};
+#endif
+
+
+#define REGISTER_IID(t) { \
+ PyObject *iid_ob = Py_nsIID::PyObjectFromIID(NS_GET_IID(t)); \
+ PyDict_SetItemString(dict, "IID_"#t, iid_ob); \
+ Py_DECREF(iid_ob); \
+ }
+
+#define REGISTER_INT(val) { \
+ PyObject *ob = PyInt_FromLong(val); \
+ PyDict_SetItemString(dict, #val, ob); \
+ Py_DECREF(ob); \
+ }
+
+
+////////////////////////////////////////////////////////////
+// The module init code.
+//
+#if PY_MAJOR_VERSION <= 2
+extern "C" NS_EXPORT
+void
+#else
+PyObject *
+#endif
+init_xpcom() {
+ PyObject *oModule;
+
+ // ensure the framework has valid state to work with.
+ if (!PyXPCOM_Globals_Ensure())
+#if PY_MAJOR_VERSION <= 2
+ return;
+#else
+ return NULL;
+#endif
+
+ // Must force Python to start using thread locks
+ PyEval_InitThreads();
+
+ // Create the module and add the functions
+#if PY_MAJOR_VERSION <= 2
+ oModule = Py_InitModule(MODULE_NAME, xpcom_methods);
+#else
+ oModule = PyModule_Create(&xpcom_module);
+#endif
+
+ PyObject *dict = PyModule_GetDict(oModule);
+ PyObject *pycom_Error = PyXPCOM_Error;
+ if (pycom_Error == NULL || PyDict_SetItemString(dict, "error", pycom_Error) != 0)
+ {
+ PyErr_SetString(PyExc_MemoryError, "can't define error");
+#if PY_MAJOR_VERSION <= 2
+ return;
+#else
+ return NULL;
+#endif
+ }
+#ifndef Py_LIMITED_API
+ PyDict_SetItemString(dict, "IIDType", (PyObject *)&Py_nsIID::type);
+#else
+ PyDict_SetItemString(dict, "IIDType", (PyObject *)Py_nsIID::GetTypeObject());
+#endif
+
+ REGISTER_IID(nsISupports);
+ REGISTER_IID(nsISupportsCString);
+ REGISTER_IID(nsISupportsString);
+ REGISTER_IID(nsIModule);
+ REGISTER_IID(nsIFactory);
+ REGISTER_IID(nsIWeakReference);
+ REGISTER_IID(nsISupportsWeakReference);
+ REGISTER_IID(nsIClassInfo);
+ REGISTER_IID(nsIServiceManager);
+ REGISTER_IID(nsIComponentRegistrar);
+
+ // Register our custom interfaces.
+ REGISTER_IID(nsIComponentManager);
+ REGISTER_IID(nsIInterfaceInfoManager);
+ REGISTER_IID(nsIEnumerator);
+ REGISTER_IID(nsISimpleEnumerator);
+ REGISTER_IID(nsIInterfaceInfo);
+ REGISTER_IID(nsIInputStream);
+ REGISTER_IID(nsIClassInfo);
+ REGISTER_IID(nsIVariant);
+ // for backward compatibility:
+ REGISTER_IID(nsIComponentManagerObsolete);
+
+ // No good reason not to expose this impl detail, and tests can use it
+ REGISTER_IID(nsIInternalPython);
+ // We have special support for proxies - may as well add their constants!
+ REGISTER_INT(PROXY_SYNC);
+ REGISTER_INT(PROXY_ASYNC);
+ REGISTER_INT(PROXY_ALWAYS);
+ // Build flags that may be useful.
+ PyObject *ob = PyBool_FromLong(
+#ifdef NS_DEBUG
+ 1
+#else
+ 0
+#endif
+ );
+ PyDict_SetItemString(dict, "NS_DEBUG", ob);
+ Py_DECREF(ob);
+#if PY_MAJOR_VERSION >= 3
+ return oModule;
+#endif
+}
+
+#ifdef VBOX_PYXPCOM
+# include <VBox/com/com.h>
+using namespace com;
+
+# include <iprt/initterm.h>
+# include <iprt/string.h>
+# include <iprt/alloca.h>
+# include <iprt/stream.h>
+
+/** Set if NS_ShutdownXPCOM has been called successfully already and we don't
+ * need to do it again during module termination. This avoids assertion in the
+ * VBoxCOM glue code. */
+static bool g_fComShutdownAlready = true;
+
+# if PY_MAJOR_VERSION <= 2
+extern "C" NS_EXPORT
+void
+# else
+/** @todo r=klaus this is hacky, but as Python3 doesn't deal with ELF
+ * visibility, assuming that all globals are visible (which is ugly and not
+ * true in our case). */
+# undef PyMODINIT_FUNC
+# define PyMODINIT_FUNC extern "C" NS_EXPORT PyObject*
+PyMODINIT_FUNC
+# endif
+initVBoxPython() { /* NOTE! This name is redefined at the top of the file! */
+ static bool s_vboxInited = false;
+ if (!s_vboxInited) {
+ int rc = 0; /* Error handling in this code is NON-EXISTING. Sigh. */
+
+# if defined(VBOX_PATH_APP_PRIVATE_ARCH) && defined(VBOX_PATH_SHARED_LIBS)
+ rc = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
+# else
+ const char *home = getenv("VBOX_PROGRAM_PATH");
+ if (home) {
+ size_t len = strlen(home);
+ char *exepath = (char *)alloca(len + 32);
+ memcpy(exepath, home, len);
+ memcpy(exepath + len, "/pythonfake", sizeof("/pythonfake"));
+ rc = RTR3InitEx(RTR3INIT_VER_CUR, RTR3INIT_FLAGS_DLL | RTR3INIT_FLAGS_UNOBTRUSIVE, 0, NULL, exepath);
+ } else {
+ rc = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
+ }
+# endif
+
+ rc = com::Initialize();
+ g_fComShutdownAlready = false;
+
+# if PY_MAJOR_VERSION <= 2
+ init_xpcom();
+# else
+ return init_xpcom();
+# endif
+ }
+# if PY_MAJOR_VERSION >= 3
+ return NULL;
+# endif
+}
+
+static
+nsresult deinitVBoxPython()
+{
+ nsresult nr;
+ if (!g_fComShutdownAlready)
+ {
+ nr = com::Shutdown();
+ if (!NS_FAILED(nr))
+ g_fComShutdownAlready = true;
+ }
+ else
+ nr = NS_ERROR_NOT_INITIALIZED;
+ return nr;
+}
+
+#endif /* VBOX_PYXPCOM */
diff --git a/src/libs/xpcom18a4/python/src/readme.html b/src/libs/xpcom18a4/python/src/readme.html
new file mode 100644
index 00000000..b049dbad
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/readme.html
@@ -0,0 +1,99 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is PyXPCOM.
+ -
+ - The Initial Developer of the Original Code is
+ - ActiveState Tool Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2000-2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<html>
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<title>Building the Python XPCOM package</title>
+</head>
+
+<body>
+
+<h1>Building the Python XPCOM package.</h1>
+
+<p>This file describes how to build the Python XPCOM C++ sources.</p>
+<p>There are the following steps</p>
+<ul>
+ <li><a href="#ConfiguringTheEnvironment">Configure environment variables</a></li>
+ <li><a href="#BuildingTheSources">Building the sources</a></li>
+</ul>
+<p>Testing etc is described in the <a href="../readme.html">main readme</a>.</p>
+<h2><a name="ConfiguringTheEnvironment">Configuring environment variables</a></h2>
+<h3> MOZ_SRC&nbsp;</h3>
+<p><b>Windows: </b>Run the standard MOZENV.BAT used to build Mozilla.&nbsp; This
+sets MOZ_SRC</p>
+<p><b>Unix:</b> Set MOZ_SRC to point to the base source directory - assumes
+&quot;mozilla&quot; sub-directory with mozilla directory tree under that. eg: assuming
+<i>/home/user/src/mozilla/dist/...</i>&quot;</p>
+<pre>export MOZ_SRC=/home/user/src</pre>
+<h3>PYTHON_SRC</h3>
+<p><b>Windows:</b> Set <i> PYTHON_SRC</i> to point to the base Python source directory.&nbsp;
+eg: assuming <i>c:\src\python\PCBuild\...</i><pre>set PYTHON_SRC=c:\src\python</pre>
+<p>Unix: Set PYTHON_SRC to point to the base of an &quot;installed&quot; Python
+tree. eg:<pre>export PYTHON_SRC=/usr/local/ActivePython-1.6</pre>
+<h2><a name="BuildingTheSources">Building the sources</a></h2>
+<p>You must ensure some environment variables are setup.&nbsp; The section on <a href="#ConfiguringTheEnvironment">configuring
+environment variables explains how.</a></p>
+<p>There are 2 build processes to run All C++ sources are in the <i>xpcom\src</i>
+ directory.:</p>
+<h3>Windows</h3>
+<ul>
+ <li> Execute &quot;compile.py&quot; in this directory. This will take <i>Setup.in</i>, create an MSDev project, and build
+ <i>..\_xpcom.pyd</i> and <i>..\_xpcom_d.pyd</i>&quot;</li>
+ <li> Change to the <i>loader</i> directory.</li>
+ <li> Run <i>nmake -f makefile.win</i>. This will create <i>pyloader.dll</i>, and
+ automatically copy it to the Mozilla build directory.</li>
+ <a href="#ConfiguringTheEnvironment">
+ </ul>
+ <p>Finally, </a><a href="../readme.html#RunningTheTests">run the tests</a>,
+ where we also test everything imports correctly.</p>
+<h3>Linux</h3>
+<p><b> NOTE:</b> Do not attempt to use &quot;Setup.in&quot; to create a Makefile&nbsp;</p>
+<ul>
+ <li>Run &quot;make&quot; in this directory.&nbsp; This will create <i>../_xpcommodule.so</i></li>
+ <li> Run "make" in the loader directory. This will create <i>libpyloader.so</i>,
+ and copy it to the Mozilla directory.</li>
+ <a href="#ConfiguringTheEnvironment">
+ </ul>
+ <p>Finally, </a><a href="../readme.html#RunningTheTests">running the tests</a>,
+ where we also test everything imports correctly.</p>
+
+</body>
+
+</html>