Index: trunk/src/libs/xpcom18a4/python/.cvsignore
===================================================================
--- trunk/src/libs/xpcom18a4/python/.cvsignore	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/.cvsignore	(revision 11746)
@@ -0,0 +1,4 @@
+*.pyc
+*.pyo
+*.idb
+*.pdb
Index: trunk/src/libs/xpcom18a4/python/README.vbox
===================================================================
--- trunk/src/libs/xpcom18a4/python/README.vbox	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/README.vbox	(revision 11746)
@@ -0,0 +1,5 @@
+ PyXPCOM sources (see http://developer.mozilla.org/en/docs/PyXPCOM) 
+were taken from :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot, 
+directory extensions/python/xpcom, branch DOM_AGNOSTIC2_BRANCH, Aug 14 2008. 
+
+ Imported to VirtualBox codebase in revision 34814.
Index: trunk/src/libs/xpcom18a4/python/__init__.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/__init__.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/__init__.py	(revision 11746)
@@ -0,0 +1,164 @@
+# ***** 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>
+#
+# 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 *****
+#
+
+# The XPCOM (Cross Platform COM) package.
+import exceptions
+
+# A global "verbose" flag - currently used by the
+# server package to print trace messages
+verbose = 0
+# Map of nsresult -> constant_name.
+hr_map = {}
+
+# The standard XPCOM exception object.
+# Instances of this class are raised by the XPCOM extension module.
+class Exception(exceptions.Exception):
+    def __init__(self, errno, message = None):
+        assert int(errno) == errno, "The errno param must be an integer"
+        self.errno = errno
+        self.message = message
+        exceptions.Exception.__init__(self, errno)
+    def __str__(self):
+        if not hr_map:
+            import nsError
+            for name, val in nsError.__dict__.items():
+                if type(val)==type(0):
+                    hr_map[val] = name
+        message = self.message
+        if message is None:
+            message = hr_map.get(self.errno)
+            if message is None:
+                message = ""
+        return "%d (%s)" % (self.errno, message)
+
+# An alias for Exception - allows code to say "from xpcom import COMException"
+# rather than "Exception", preventing clashes with the builtin Exception
+COMException = Exception
+
+# Exceptions thrown by servers.  It can be good for diagnostics to
+# differentiate between a ServerException (which was presumably explicitly thrown)
+# and a normal exception which may simply be propagating down.
+# (When ServerException objects are thrown across the XPConnect
+# gateway they will be converted back to normal client exceptions if
+# subsequently re-caught by Python)
+class ServerException(Exception):
+    def __init__(self, errno=None, *args, **kw):
+        if errno is None:
+            import nsError
+            errno = nsError.NS_ERROR_FAILURE
+        Exception.__init__(self, errno, *args, **kw)
+
+# Logging support - setup the 'xpcom' logger to write to the Mozilla
+# console service, and also to sys.stderr, or optionally a file.
+# Environment variables supports:
+# PYXPCOM_LOG_FILE=filename - if set, used instead of sys.stderr.
+# PYXPCOM_LOG_LEVEL=level - level may be a number or a logging level
+#                           constant (eg, 'debug', 'error')
+# Later it may make sense to allow a different log level to be set for
+# the file than for the console service.
+import logging
+class ConsoleServiceStream:
+    # enough of a stream to keep logging happy
+    def flush(self):
+        pass
+    def write(self, msg):
+        import _xpcom
+        _xpcom.LogConsoleMessage(msg)
+    def close(self):
+        pass
+
+def setupLogging():
+    import sys, os, threading, thread
+    hdlr = logging.StreamHandler(ConsoleServiceStream())
+    fmt = logging.Formatter(logging.BASIC_FORMAT)
+    hdlr.setFormatter(fmt)
+    # There is a bug in 2.3 and 2.4.x logging module in that it doesn't
+    # use an RLock, leading to deadlocks in some cases (specifically,
+    # logger.warning("ob is %r", ob), and where repr(ob) itself tries to log)
+    # Later versions of logging use an RLock, so we detect an "old" style
+    # handler and update its lock
+    if type(hdlr.lock) == thread.LockType:
+        hdlr.lock = threading.RLock()
+
+    logger.addHandler(hdlr)
+    # The console handler in mozilla does not go to the console!?
+    # Add a handler to print to stderr, or optionally a file
+    # PYXPCOM_LOG_FILE can specify a filename
+    filename = os.environ.get("PYXPCOM_LOG_FILE")
+    stream = sys.stderr # this is what logging uses as default
+    if filename:
+        try:
+            # open without buffering so never pending output
+            stream = open(filename, "wU", 0)
+        except IOError, why:
+            print >> sys.stderr, "pyxpcom failed to open log file '%s': %s" \
+                                 % (filename, why)
+            # stream remains default
+
+    hdlr = logging.StreamHandler(stream)
+    # see above - fix a deadlock problem on this handler too.
+    if type(hdlr.lock) == thread.LockType:
+        hdlr.lock = threading.RLock()
+
+    fmt = logging.Formatter(logging.BASIC_FORMAT)
+    hdlr.setFormatter(fmt)
+    logger.addHandler(hdlr)
+    # Allow PYXPCOM_LOG_LEVEL to set the level
+    level = os.environ.get("PYXPCOM_LOG_LEVEL")
+    if level:
+        try:
+            level = int(level)
+        except ValueError:
+            try:
+                # might be a symbolic name - all are upper-case
+                level = int(getattr(logging, level.upper()))
+            except (AttributeError, ValueError):
+                logger.warning("The PYXPCOM_LOG_LEVEL variable specifies an "
+                               "invalid level")
+                level = None
+        if level:
+            logger.setLevel(level)
+
+logger = logging.getLogger('xpcom')
+# If someone else has already setup this logger, leave things alone.
+if len(logger.handlers) == 0:
+    setupLogging()
+
+# Cleanup namespace - but leave 'logger' there for people to use, so they
+# don't need to know the exact name of the logger.
+del ConsoleServiceStream, logging, setupLogging
Index: trunk/src/libs/xpcom18a4/python/client/.cvsignore
===================================================================
--- trunk/src/libs/xpcom18a4/python/client/.cvsignore	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/client/.cvsignore	(revision 11746)
@@ -0,0 +1,2 @@
+*.pyc
+*.pyo
Index: trunk/src/libs/xpcom18a4/python/client/__init__.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/client/__init__.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/client/__init__.py	(revision 11746)
@@ -0,0 +1,532 @@
+# ***** 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, 2001
+# 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 *****
+
+import os
+import new
+import logging
+from xpcom import xpt, COMException, nsError, logger
+
+# Suck in stuff from _xpcom we use regularly to prevent a module lookup
+from xpcom._xpcom import IID_nsISupports, IID_nsIClassInfo, \
+    IID_nsISupportsCString, IID_nsISupportsString, \
+    IID_nsISupportsWeakReference, IID_nsIWeakReference, \
+    XPTI_GetInterfaceInfoManager, GetComponentManager, XPTC_InvokeByIndex
+
+# Attribute names we may be __getattr__'d for, but know we don't want to delegate
+# Could maybe just look for startswith("__") but this may screw things for some objects.
+_special_getattr_names = ["__del__", "__len__", "__nonzero__", "__eq__", "__neq__"]
+
+_just_int_interfaces = ["nsISupportsPRInt32", "nsISupportsPRInt16", "nsISupportsPRUint32", "nsISupportsPRUint16", "nsISupportsPRUint8", "nsISupportsPRBool"]
+_just_long_interfaces = ["nsISupportsPRInt64", "nsISupportsPRUint64"]
+_just_float_interfaces = ["nsISupportsDouble", "nsISupportsFloat"]
+# When doing a specific conversion, the order we try the interfaces in.
+_int_interfaces = _just_int_interfaces + _just_float_interfaces
+_long_interfaces = _just_long_interfaces + _just_int_interfaces + _just_float_interfaces
+_float_interfaces = _just_float_interfaces + _just_long_interfaces + _just_int_interfaces
+
+method_template = """
+def %s(self, %s):
+    return XPTC_InvokeByIndex(self._comobj_, %d, (%s, (%s)))
+"""
+def _MakeMethodCode(method):
+    # Build a declaration
+    param_no = 0
+    param_decls = []
+    param_flags = []
+    param_names = []
+    used_default = 0
+    for param in method.params:
+        param_no = param_no + 1
+        param_name = "Param%d" % (param_no,)
+        param_default = ""
+        if not param.hidden_indicator and param.IsIn() and not param.IsDipper():
+            if param.IsOut() or used_default: # If the param is "inout", provide a useful default for the "in" direction.
+                param_default = " = None"
+                used_default = 1 # Once we have used one once, we must for the rest!
+            param_decls.append(param_name + param_default)
+            param_names.append(param_name)
+
+        type_repr = xpt.MakeReprForInvoke(param)
+        param_flags.append( (param.param_flags,) +  type_repr )
+    sep = ", "
+    param_decls = sep.join(param_decls)
+    if len(param_names)==1: # Damn tuple reprs.
+        param_names = param_names[0] + ","
+    else:
+        param_names = sep.join(param_names)
+    # A couple of extra newlines make them easier to read for debugging :-)
+    return method_template % (method.name, param_decls, method.method_index, tuple(param_flags), param_names)
+
+# Keyed by IID, each item is a tuple of (methods, getters, setters)
+interface_cache = {}
+# Keyed by [iid][name], each item is an unbound method.
+interface_method_cache = {}
+
+# Keyed by clsid from nsIClassInfo - everything ever queried for the CID.
+contractid_info_cache = {}
+have_shutdown = 0
+
+def _shutdown():
+    interface_cache.clear()
+    interface_method_cache.clear()
+    contractid_info_cache.clear()
+    global have_shutdown
+    have_shutdown = 1
+
+# Fully process the named method, generating method code etc.
+def BuildMethod(method_info, iid):
+    name = method_info.name
+    try:
+        return interface_method_cache[iid][name]
+    except KeyError:
+        pass
+    # Generate it.
+    assert not (method_info.IsSetter() or method_info.IsGetter()), "getters and setters should have been weeded out by now"
+    method_code = _MakeMethodCode(method_info)
+    # Build the method - We only build a function object here
+    # - they are bound to each instance as needed.
+    
+##    print "Method Code for %s (%s):" % (name, iid)
+##    print method_code
+    codeObject = compile(method_code, "<XPCOMObject method '%s'>" % (name,), "exec")
+    # Exec the code object
+    tempNameSpace = {}
+    exec codeObject in globals(), tempNameSpace
+    ret = tempNameSpace[name]
+    if not interface_method_cache.has_key(iid):
+        interface_method_cache[iid] = {}
+    interface_method_cache[iid][name] = ret
+    return ret
+
+from xpcom.xpcom_consts import XPT_MD_GETTER, XPT_MD_SETTER, XPT_MD_NOTXPCOM, XPT_MD_CTOR, XPT_MD_HIDDEN
+FLAGS_TO_IGNORE = XPT_MD_NOTXPCOM | XPT_MD_CTOR | XPT_MD_HIDDEN
+
+# Pre-process the interface - generate a list of methods, constants etc,
+# but don't actually generate the method code.
+def BuildInterfaceInfo(iid):
+    assert not have_shutdown, "Can't build interface info after a shutdown"
+    ret = interface_cache.get(iid, None)
+    if ret is None:
+        # Build the data for the cache.
+        method_code_blocks = []
+        getters = {}
+        setters = {}
+        method_infos = {}
+        
+        interface = xpt.Interface(iid)
+        for m in interface.methods:
+            flags = m.flags
+            if flags & FLAGS_TO_IGNORE == 0:
+                if flags & XPT_MD_SETTER:
+                    param_flags = map(lambda x: (x.param_flags,) + xpt.MakeReprForInvoke(x), m.params)
+                    setters[m.name] = m.method_index, param_flags
+                elif flags & XPT_MD_GETTER:
+                    param_flags = map(lambda x: (x.param_flags,) + xpt.MakeReprForInvoke(x), m.params)
+                    getters[m.name] = m.method_index, param_flags
+                else:
+                    method_infos[m.name] = m
+
+        # Build the constants.
+        constants = {}
+        for c in interface.constants:
+            constants[c.name] = c.value
+        ret = method_infos, getters, setters, constants
+        interface_cache[iid] = ret
+    return ret
+
+class _XPCOMBase:
+    def __cmp__(self, other):
+        try:
+            other = other._comobj_
+        except AttributeError:
+            pass
+        return cmp(self._comobj_, other)
+
+    def __hash__(self):
+        return hash(self._comobj_)
+
+    # The basic rich compare ops for equality
+    def __eq__(self, other):
+        try:
+            other = other._comobj_
+        except AttributeError:
+            pass
+        return self._comobj_ == other
+
+    def __neq__(self, other):
+        try:
+            other = other._comobj_
+        except AttributeError:
+            pass
+        return self._comobj_ != other
+
+    # See if the object support strings.
+    def __str__(self):
+        try:
+            self._comobj_.QueryInterface(IID_nsISupportsCString, 0)
+            return str(self._comobj_)
+        except COMException:
+            return self.__repr__()
+
+    def __unicode__(self):
+        try:
+            prin = self._comobj_.QueryInterface(IID_nsISupportsString)
+        except COMException:
+            return unicode(str(self))
+        return prin.data
+
+    # Try the numeric support.
+    def _do_conversion(self, interface_names, cvt):
+        iim = XPTI_GetInterfaceInfoManager()
+        for interface_name in interface_names:
+            iid = iim.GetInfoForName(interface_name).GetIID()
+            try:
+                prim = self._comobj_.QueryInterface(iid)
+                return cvt(prim.data)
+            except COMException:
+                pass
+        raise ValueError, "This object does not support automatic numeric conversion to this type"
+
+    def __int__(self):
+        return self._do_conversion(_int_interfaces, int)
+
+    def __long__(self):
+        return self._do_conversion(_long_interfaces, long)
+
+    def __float__(self):
+        return self._do_conversion(_float_interfaces, float)
+    
+class Component(_XPCOMBase):
+    def __init__(self, ob, iid = IID_nsISupports):
+        assert not hasattr(ob, "_comobj_"), "Should be a raw nsIWhatever, not a wrapped one"
+        ob_name = None
+        if not hasattr(ob, "IID"):
+            ob_name = ob
+            cm = GetComponentManager()
+            ob = cm.createInstanceByContractID(ob)
+            assert not hasattr(ob, "_comobj_"), "The created object should be a raw nsIWhatever, not a wrapped one"
+        # Keep a reference to the object in the component too
+        self.__dict__['_comobj_'] = ob
+        # hit __dict__ directly to avoid __setattr__()
+        self.__dict__['_interfaces_'] = {} # keyed by IID
+        self.__dict__['_interface_names_'] = {} # keyed by IID name
+        self.__dict__['_interface_infos_'] = {} # keyed by IID
+        self.__dict__['_name_to_interface_iid_'] = {}
+        self.__dict__['_tried_classinfo_'] = 0
+
+        if ob_name is None:
+            ob_name = "<unknown>"
+        self.__dict__['_object_name_'] = ob_name
+        self.QueryInterface(iid)
+
+    def _build_all_supported_interfaces_(self):
+        # Use nsIClassInfo, but don't do it at object construction to keep perf up.
+        # Only pay the penalty when we really need it.
+        assert not self._tried_classinfo_, "already tried to get the class info."
+        self.__dict__['_tried_classinfo_'] = 1
+        # See if nsIClassInfo is supported.
+        try:
+            classinfo = self._comobj_.QueryInterface(IID_nsIClassInfo, 0)
+        except COMException:
+            classinfo = None
+        if classinfo is not None:
+            try:
+                real_cid = classinfo.contractID
+            except COMException:
+                real_cid = None
+            if real_cid:
+                self.__dict__['_object_name_'] = real_cid
+                contractid_info = contractid_info_cache.get(real_cid)
+            else:
+                contractid_info = None
+            if contractid_info is None:
+                try:
+                    interface_infos = classinfo.getInterfaces()
+                except COMException:
+                    interface_infos = []
+                for nominated_iid in interface_infos:
+                    # Interface may appear twice in the class info list, so check this here.
+                    if not self.__dict__['_interface_infos_'].has_key(nominated_iid):
+                        # Just invoke our QI on the object
+                        self.queryInterface(nominated_iid)
+                if real_cid is not None:
+                    contractid_info = {}
+                    contractid_info['_name_to_interface_iid_'] = self.__dict__['_name_to_interface_iid_']
+                    contractid_info['_interface_infos_'] = self.__dict__['_interface_infos_']
+                    contractid_info_cache[real_cid] = contractid_info
+            else:
+                for key, val in contractid_info.items():
+                    self.__dict__[key].update(val)
+
+        self.__dict__['_com_classinfo_'] = classinfo
+
+    def _remember_interface_info(self, iid):
+        # XXX - there is no good reason to cache this only in each instance
+        # It should be cached at the module level, so we don't need to
+        # rebuild the world for each new object.
+        iis = self.__dict__['_interface_infos_']
+        assert not iis.has_key(iid), "Already remembered this interface!"
+        try:
+            method_infos, getters, setters, constants = BuildInterfaceInfo(iid)
+        except COMException, why:
+            # Failing to build an interface info generally isn't a real
+            # problem - its probably just that the interface is non-scriptable.
+            logger.info("Failed to build interface info for %s: %s", iid, why)
+            # Remember the fact we failed.
+            iis[iid] = None
+            return
+
+        # Remember all the names so we can delegate
+        iis[iid] = method_infos, getters, setters, constants
+        names = self.__dict__['_name_to_interface_iid_']
+        for name in method_infos.keys(): names[name] = iid
+        for name in getters.keys(): names[name] = iid
+        for name in setters.keys(): names[name] = iid
+        for name in constants.keys():  names[name] = iid
+
+    def QueryInterface(self, iid):
+        if self._interfaces_.has_key(iid):
+            assert self._interface_names_.has_key(iid.name), "_interfaces_ has the key, but _interface_names_ does not!"
+            return self
+        # Haven't seen this before - do a real QI.
+        if not self._interface_infos_.has_key(iid):
+            self._remember_interface_info(iid)
+        iface_info = self._interface_infos_[iid]
+        if iface_info is None:
+            # We have tried, but failed, to get this interface info.  Its
+            # unlikely to work later either - its probably non-scriptable.
+            # That means our component wrappers are useless - so just return a
+            # raw nsISupports object with no wrapper.            
+            return self._comobj_.QueryInterface(iid, 0)
+
+        raw_iface = self._comobj_.QueryInterface(iid, 0)
+
+        method_infos, getters, setters, constants = iface_info
+        new_interface = _Interface(raw_iface, iid, method_infos,
+                                   getters, setters, constants)
+        self._interfaces_[iid] = new_interface
+        self._interface_names_[iid.name] = new_interface
+        # As we 'flatten' objects when possible, a QI on an object just
+        # returns ourself - all the methods etc on this interface are
+        # available.
+        return self
+
+    queryInterface = QueryInterface # Alternate name.
+
+    def __getattr__(self, attr):
+        if attr in _special_getattr_names:
+            raise AttributeError, attr
+        # First allow the interface name to return the "raw" interface
+        interface = self.__dict__['_interface_names_'].get(attr, None)
+        if interface is not None:
+            return interface
+        # See if we know the IID of an interface providing this attribute
+        iid = self.__dict__['_name_to_interface_iid_'].get(attr, None)
+        # This may be first time trying this interface - get the nsIClassInfo
+        if iid is None and not self._tried_classinfo_:
+            self._build_all_supported_interfaces_()
+            iid = self.__dict__['_name_to_interface_iid_'].get(attr, None)
+            # If the request is for an interface name, it may now be
+            # available.
+            interface = self.__dict__['_interface_names_'].get(attr, None)
+            if interface is not None:
+                return interface
+
+        if iid is not None:
+            interface = self.__dict__['_interfaces_'].get(iid, None)
+            if interface is None:
+                self.QueryInterface(iid)
+                interface = self.__dict__['_interfaces_'][iid]
+            return getattr(interface, attr)
+        # Some interfaces may provide this name via "native" support.
+        # Loop over all interfaces, and if found, cache it for next time.
+        for interface in self.__dict__['_interfaces_'].values():
+            try:
+                ret = getattr(interface, attr)
+                self.__dict__['_name_to_interface_iid_'][attr] = interface._iid_
+                return ret
+            except AttributeError:
+                pass
+        raise AttributeError, "XPCOM component '%s' has no attribute '%s'" % (self._object_name_, attr)
+        
+    def __setattr__(self, attr, val):
+        iid = self._name_to_interface_iid_.get(attr, None)
+        # This may be first time trying this interface - get the nsIClassInfo
+        if iid is None and not self._tried_classinfo_:
+            self._build_all_supported_interfaces_()
+            iid = self.__dict__['_name_to_interface_iid_'].get(attr, None)
+        if iid is not None:
+            interface = self._interfaces_.get(iid, None)
+            if interface is None:
+                self.QueryInterface(iid)
+                interface = self.__dict__['_interfaces_'][iid]
+            setattr(interface, attr, val)
+            return
+        raise AttributeError, "XPCOM component '%s' has no attribute '%s'" % (self._object_name_, attr)
+
+    def _get_classinfo_repr_(self):
+        try:
+            if not self._tried_classinfo_:
+                self._build_all_supported_interfaces_()
+            assert self._tried_classinfo_, "Should have tried the class info by now!"
+        except COMException:
+            # Error building the info - ignore the error, but ensure that
+            # we are flagged as *not* having built, so the error is seen
+            # by the first caller who actually *needs* this to work.
+            self.__dict__['_tried_classinfo_'] = 0
+
+        iface_names = self.__dict__['_interface_names_'].keys()
+        try:
+            iface_names.remove("nsISupports")
+        except ValueError:
+            pass
+        iface_names.sort()
+        
+        iface_desc = "implementing %s" % (",".join(iface_names),)
+        return iface_desc
+        
+    def __repr__(self):
+        # We can advantage from nsIClassInfo - use it.
+        iface_desc = self._get_classinfo_repr_()
+        return "<XPCOM component '%s' (%s)>" % (self._object_name_,iface_desc)
+
+class _Interface(_XPCOMBase):
+    def __init__(self, comobj, iid, method_infos, getters, setters, constants):
+        self.__dict__['_comobj_'] = comobj
+        self.__dict__['_iid_'] = iid
+        self.__dict__['_property_getters_'] = getters
+        self.__dict__['_property_setters_'] = setters
+        self.__dict__['_method_infos_'] = method_infos # method infos waiting to be turned into real methods.
+        self.__dict__['_methods_'] = {} # unbound methods
+        self.__dict__['_object_name_'] = iid.name
+        self.__dict__.update(constants)
+        # We remember the constant names to prevent the user trying to assign to them!
+        self.__dict__['_constant_names_'] = constants.keys()
+
+    def __getattr__(self, attr):
+        # Allow the underlying interface to provide a better implementation if desired.
+        if attr in _special_getattr_names:
+            raise AttributeError, attr
+
+        ret = getattr(self.__dict__['_comobj_'], attr, None)
+        if ret is not None:
+            return ret
+        # Do the function thing first.
+        unbound_method = self.__dict__['_methods_'].get(attr, None)
+        if unbound_method is not None:
+            return new.instancemethod(unbound_method, self, self.__class__)
+
+        getters = self.__dict__['_property_getters_']
+        info = getters.get(attr)
+        if info is not None:
+            method_index, param_infos = info
+            if len(param_infos)!=1: # Only expecting a retval
+                raise RuntimeError, "Can't get properties with this many args!"
+            args = ( param_infos, () )
+            return XPTC_InvokeByIndex(self._comobj_, method_index, args)
+
+        # See if we have a method info waiting to be turned into a method.
+        # Do this last as it is a one-off hit.
+        method_info = self.__dict__['_method_infos_'].get(attr, None)
+        if method_info is not None:
+            unbound_method = BuildMethod(method_info, self._iid_)
+            # Cache it locally
+            self.__dict__['_methods_'][attr] = unbound_method
+            return new.instancemethod(unbound_method, self, self.__class__)
+
+        raise AttributeError, "XPCOM component '%s' has no attribute '%s'" % (self._object_name_, attr)
+
+    def __setattr__(self, attr, val):
+        # If we already have a __dict__ item of that name, and its not one of
+        # our constants, we just directly set it, and leave.
+        if self.__dict__.has_key(attr) and attr not in self.__dict__['_constant_names_']:
+            self.__dict__[attr] = val
+            return
+        # Start sniffing for what sort of attribute this might be?
+        setters = self.__dict__['_property_setters_']
+        info = setters.get(attr)
+        if info is None:
+            raise AttributeError, "XPCOM component '%s' can not set attribute '%s'" % (self._object_name_, attr)
+        method_index, param_infos = info
+        if len(param_infos)!=1: # Only expecting a single input val
+            raise RuntimeError, "Can't set properties with this many args!"
+        real_param_infos = ( param_infos, (val,) )
+        return XPTC_InvokeByIndex(self._comobj_, method_index, real_param_infos)
+
+    def __repr__(self):
+        return "<XPCOM interface '%s'>" % (self._object_name_,)
+
+
+# Called by the _xpcom C++ framework to wrap interfaces up just
+# before they are returned.
+def MakeInterfaceResult(ob, iid):
+    return Component(ob, iid)
+
+class WeakReference:
+    """A weak-reference object.  You construct a weak reference by passing
+    any COM object you like.  If the object does not support weak
+    refs, you will get a standard NS_NOINTERFACE exception.
+
+    Once you have a weak-reference, you can "call" the object to get
+    back a strong reference.  Eg:
+
+    >>> some_ob = components.classes['...']
+    >>> weak_ref = WeakReference(some_ob)
+    >>> new_ob = weak_ref() # new_ob is effectively "some_ob" at this point
+    >>> # EXCEPT: new_ob may be None if some_ob has already died - a
+    >>> # weak reference does not keep the object alive (that is the point)
+
+    You should never hold onto this resulting strong object for a long time,
+    or else you defeat the purpose of the weak-reference.
+    """
+    def __init__(self, ob, iid = None):
+        swr = Component(ob._comobj_, IID_nsISupportsWeakReference)
+        self._comobj_ = Component(swr.GetWeakReference()._comobj_, IID_nsIWeakReference)
+        if iid is None:
+            try:
+                iid = ob.IID
+            except AttributeError:
+                iid = IID_nsISupports
+        self._iid_ = iid
+    def __call__(self, iid = None):
+        if iid is None: iid = self._iid_
+        try:
+            return Component(self._comobj_.QueryReferent(iid)._comobj_, iid)
+        except COMException, details:
+            if details.errno != nsError.NS_ERROR_NULL_POINTER:
+                raise
+            return None
Index: trunk/src/libs/xpcom18a4/python/components.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/components.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/components.py	(revision 11746)
@@ -0,0 +1,240 @@
+# ***** 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, 2001
+# 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 module provides the JavaScript "components" interface
+import xpt
+import xpcom, _xpcom
+import xpcom.client
+import xpcom.server
+import types
+
+StringTypes = [types.StringType, types.UnicodeType]
+
+def _get_good_iid(iid):
+    if iid is None:
+        iid = _xpcom.IID_nsISupports
+    elif type(iid) in StringTypes and len(iid)>0 and iid[0] != "{":
+        iid = getattr(interfaces, iid)
+    return iid
+
+# The "manager" object.
+manager = xpcom.client.Component(_xpcom.GetComponentManager(), _xpcom.IID_nsIComponentManager)
+
+# The component registrar
+registrar = xpcom.client.Component(_xpcom.GetComponentManager(), _xpcom.IID_nsIComponentRegistrar)
+
+# The "interfaceInfoManager" object - JS doesnt have this.
+interfaceInfoManager = _xpcom.XPTI_GetInterfaceInfoManager()
+
+# The serviceManager - JS doesnt have this either!
+serviceManager = _xpcom.GetServiceManager()
+
+# The "Exception" object
+Exception = xpcom.COMException
+
+# Base class for our collections.
+# It appears that all objects supports "." and "[]" notation.
+# eg, "interface.nsISupports" or interfaces["nsISupports"]
+class _ComponentCollection:
+    # Bases are to over-ride 2 methods.
+    # _get_one(self, name) - to return one object by name
+    # _build_dict - to return a dictionary which provide access into
+    def __init__(self):
+        self._dict_data = None
+    def keys(self):
+        if self._dict_data is None:
+            self._dict_data = self._build_dict()
+        return self._dict_data.keys()
+    def items(self):
+        if self._dict_data is None:
+            self._dict_data = self._build_dict()
+        return self._dict_data.items()
+    def values(self):
+        if self._dict_data is None:
+            self._dict_data = self._build_dict()
+        return self._dict_data.values()
+    def has_key(self, key):
+        if self._dict_data is None:
+            self._dict_data = self._build_dict()
+        return self._dict_data.has_key(key)
+
+    def __len__(self):
+        if self._dict_data is None:
+            self._dict_data = self._build_dict()
+        return len(self._dict_data)
+
+    def __getattr__(self, attr):
+        if self._dict_data is not None and self._dict_data.has_key(attr):
+            return self._dict_data[attr]
+        return self._get_one(attr)
+    def __getitem__(self, item):
+        if self._dict_data is not None and self._dict_data.has_key(item):
+            return self._dict_data[item]
+        return self._get_one(item)
+
+_constants_by_iid_map = {}
+
+class _Interface:
+    # An interface object.
+    def __init__(self, name, iid):
+        # Bypass self.__setattr__ when initializing attributes.
+        d = self.__dict__
+        d['_iidobj_'] = iid # Allows the C++ framework to treat this as a native IID.
+        d['name'] = name
+    def __cmp__(self, other):
+        this_iid = self._iidobj_
+        other_iid = getattr(other, "_iidobj_", other)
+        return cmp(this_iid, other_iid)
+    def __hash__(self):
+        return hash(self._iidobj_)
+    def __str__(self):
+        return str(self._iidobj_)
+    def __getitem__(self, item):
+        raise TypeError, "components.interface objects are not subscriptable"
+    def __setitem__(self, item, value):
+        raise TypeError, "components.interface objects are not subscriptable"
+    def __setattr__(self, attr, value):
+        raise AttributeError, "Can not set attributes on components.Interface objects"
+    def __getattr__(self, attr):
+        # Support constants as attributes.
+        c = _constants_by_iid_map.get(self._iidobj_)
+        if c is None:
+            c = {}
+            i = xpt.Interface(self._iidobj_)
+            for c_ob in i.constants:
+                c[c_ob.name] = c_ob.value
+            _constants_by_iid_map[self._iidobj_] = c
+        if c.has_key(attr):
+            return c[attr]
+        raise AttributeError, "'%s' interfaces do not define a constant '%s'" % (self.name, attr)
+
+
+class _Interfaces(_ComponentCollection):
+    def _get_one(self, name):
+        try:
+            item = interfaceInfoManager.GetInfoForName(name)
+        except xpcom.COMException, why:
+            # Present a better exception message, and give a more useful error code.
+            import nsError
+            raise xpcom.COMException(nsError.NS_ERROR_NO_INTERFACE, "The interface '%s' does not exist" % (name,))
+        return _Interface(item.GetName(), item.GetIID())
+
+    def _build_dict(self):
+        ret = {}
+        enum = interfaceInfoManager.EnumerateInterfaces()
+        while not enum.IsDone():
+            # Call the Python-specific FetchBlock, to keep the loop in C.
+            items = enum.FetchBlock(500, _xpcom.IID_nsIInterfaceInfo)
+            # This shouldnt be necessary, but appears to be so!
+            for item in items:
+                ret[item.GetName()] = _Interface(item.GetName(), item.GetIID())
+        return ret
+
+# And the actual object people use.
+interfaces = _Interfaces()
+
+del _Interfaces # Keep our namespace clean.
+
+#################################################
+class _Class:
+    def __init__(self, contractid):
+        self.contractid = contractid
+    def __getattr__(self, attr):
+        if attr == "clsid":
+            rc = registrar.contractIDToCID(self.contractid)
+            # stash it away - it can never change!
+            self.clsid = rc
+            return rc
+        raise AttributeError, "%s class has no attribute '%s'" % (self.contractid, attr)
+    def createInstance(self, iid = None):
+        import xpcom.client
+        try:
+            return xpcom.client.Component(self.contractid, _get_good_iid(iid))
+        except xpcom.COMException, details:
+            import nsError
+            # Handle "no such component" in a cleaner way for the user.
+            if details.errno == nsError.NS_ERROR_FACTORY_NOT_REGISTERED:
+                raise xpcom.COMException(details.errno, "No such component '%s'" % (self.contractid,))
+            raise # Any other exception reraise.
+    def getService(self, iid = None):
+        return serviceManager.getServiceByContractID(self.contractid, _get_good_iid(iid))
+
+class _Classes(_ComponentCollection):
+    def __init__(self):
+        _ComponentCollection.__init__(self)
+    def _get_one(self, name):
+        # XXX - Need to check the contractid is valid!
+        return _Class(name)
+
+    def _build_dict(self):
+        ret = {}
+        enum = registrar.enumerateContractIDs()
+        while enum.hasMoreElements():
+            # Call the Python-specific FetchBlock, to keep the loop in C.
+            items = enum.fetchBlock(2000, _xpcom.IID_nsISupportsCString)
+            for item in items:
+                name = str(item.data)
+                ret[name] = _Class(name)
+        return ret
+
+classes = _Classes()
+
+del _Classes
+
+del _ComponentCollection
+
+# The ID function
+ID = _xpcom.IID
+
+# A helper to cleanup our namespace as xpcom shuts down.
+class _ShutdownObserver:
+    _com_interfaces_ = interfaces.nsIObserver
+    def observe(self, service, topic, extra):
+        global manager, registrar, classes, interfaces, interfaceInfoManager, _shutdownObserver, serviceManager, _constants_by_iid_map
+        manager = registrar = classes = interfaces = interfaceInfoManager = _shutdownObserver = serviceManager = _constants_by_iid_map = None
+        xpcom.client._shutdown()
+        xpcom.server._shutdown()
+
+svc = _xpcom.GetServiceManager().getServiceByContractID("@mozilla.org/observer-service;1", interfaces.nsIObserverService)
+# Observers will be QI'd for a weak-reference, so we must keep the
+# observer alive ourself, and must keep the COM object alive,
+# _not_ just the Python instance!!!
+_shutdownObserver = xpcom.server.WrapObject(_ShutdownObserver(), interfaces.nsIObserver)
+# Say we want a weak ref due to an assertion failing.  If this is fixed, we can pass 0,
+# and remove the lifetime hacks above!  See http://bugzilla.mozilla.org/show_bug.cgi?id=99163
+svc.addObserver(_shutdownObserver, "xpcom-shutdown", 1)
+del svc, _ShutdownObserver
Index: trunk/src/libs/xpcom18a4/python/doc/advanced.html
===================================================================
--- trunk/src/libs/xpcom18a4/python/doc/advanced.html	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/doc/advanced.html	(revision 11746)
@@ -0,0 +1,176 @@
+<html>
+<!-- ***** 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 ***** -->
+
+<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>Python XPCOM Advanced Topics</title>
+</head>
+
+<body>
+
+<h1>Python XPCOM Advanced Topics</h1>
+
+<p>This document contains a series of tidbits that don't fit
+anywhere else. As the Python XPCOM Package documentation matures, most of
+these topics will have another home.</p>
+
+<h2>XPCOM Services</h2>
+<p>An XPCOM service is simply a singleton registered by name.&nbsp; Python has
+full support for both using and implementing XPCOM services.&nbsp; To use a
+service, use <i>xpcom.components.services</i> just like the JavaScript
+counterpart.&nbsp; There is nothing special about implementing a service in
+Python; see the standard XPCOM documentation on services for more information.</p>
+
+<h2>nsIVariant</h2>
+
+<p>There is (almost) full support for <i>nsIVariant</i>.&nbsp; Any <i>nsIVariant</i>
+parameters will automatically be translated to and from regular Python objects
+giving, in effect, a multi-type parameter.&nbsp; This should be automatic, so
+there is not much else to say!&nbsp; Note that if you really want, you can
+create and pass your own <i>nsIVariant</i> object instead of a regular Python
+object, thereby allowing explicit control over the type of variant created.</p>
+
+<h2>nsISupports Primitives.</h2>
+
+<p>There is a set of interfaces described in <i>nsISupportsPrimitives.idl</i>, which I
+term collectively the <i>nsISupports Primitives Interfaces</i>.&nbsp; These
+are a set of interfaces a component can support to allow automatic conversion to
+and from many basic types.&nbsp; For example, an interface can define that it
+supports the <i>nsISupportsCString</i> interface, and this could be used by any
+program that wishes to get a string representation of the object.&nbsp; If an
+interface wishes to expose itself as a &quot;boolean value&quot;, it may choose
+to support the <i>nsISupportsPRBool</i> interface.</p>
+<p>When you call an XPCOM object (i.e., you have an XPCOM interface you are
+calling), you can use
+the builtin functions <i>str()</i>, <i>int()</i>, <i>long()</i> etc., on the
+object<i>.</i>&nbsp; In the
+case of <i>str()</i>, if the object does not support the <i>nsISupportsCString</i>
+or <i>nsISupportsString</i> interfaces, the default string <i>str()</i> for the
+object will be returned (i.e., what is normally returned for most XPCOM objects -
+support for these interface is not very common!).&nbsp; In the case of the numeric functions, a <i>ValueError</i>
+exception will be raised if the objects do not support any interface that can be
+used for the conversion.&nbsp;<i>ValueError</i> is used instead of <i>TypeError</i>,
+as the type itself (i.e., an XPCOM object) can sometimes be used in this context -
+hence it is the specific <i>value</i> of the object that is the problem.</p>
+<p>The use of <i>repr()</i> on an XPCOM interface object prevents support
+attempts for these interfaces, and allows you to see the
+&quot;real&quot; object, rather than what the object wants you to see!</p>
+<p>When you implement an XPCOM object, you have two choices for implementation
+of these interfaces:</p>
+<ul>
+  <li>You can explicitly handle these interfaces like any other interface.&nbsp;
+    In this case, you have full control.&nbsp; However, if you
+    implement only one of these standard interfaces, then you are only
+    overriding the default behavior for that specific interface - all other
+    interfaces not explicitly listed in your class will still get the behavior
+    described below.<br>
+  </li>
+  <li>If your class does not define support for these interfaces, the framework
+    will use standard Python class semantics to implement them - i.e., if your
+    class provides a <i>__str__</i> method, it will be used to implement <i>nsISupportsCString</i>
+    and <i>nsISupportsString</i>, if you provide <i>__int__</i>, <i>__long__</i>,
+    <i>__float__</i> etc., methods, they will be used to implement the numeric
+    interfaces.&nbsp; If your class defines no such special methods, then the <i>
+    QueryInterface()</i> for those interfaces fails (rather than the QI succeeding
+    and the operation to fetch the data failing).</li>
+</ul>
+<blockquote>
+<p>This allows for an interesting feature that would not normally be
+possible.&nbsp; Consider Python code that does a <i>str()</i> on an&nbsp; XPCOM
+interface, and where the XPCOM interface itself is implemented in Python and
+provides a <i>__str__</i> method.&nbsp; The <i>str()</i> on the original
+interface queries for the <i>nsISupportsCString</i> interface.&nbsp; The
+Python implemented object responds to this interface and delegates to the <i>__str__</i>
+method. At the end of all this, <i>str()</i> returns the same result
+as if the objects were native Python objects with no XPCOM layer in between.</p>
+
+</blockquote>
+
+<h2>Enumerators</h2>
+
+<p>The primary enumerator used by XPCOM is <i>nsISimpleEnumerator</i>.
+Although the Python XPCOM package has full support for <i>nsIEnumerator</i>,
+since this interface is not &quot;scriptable&quot;, you should avoided using it in interfaces
+you design.</p>
+
+<p>When you use <i>nsISimpleEnumerator</i> from Python, the following enhancements
+are available:</p>
+<ul>
+  <li>The <i>GetNext()</i> method takes an optional IID as a parameter. If
+    this is specified, the returned object will be of this interface.&nbsp; This
+    prevents the manual <i>QueryInterface()</i> generally required from other
+    languages.</li>
+  <li>There is a <i>FetchBlock(num, [iid])</i> method, which fetches the
+    specified number of elements in one operation and returns a Python
+    list. This can be useful for large enumerator sets, so the loop
+    iterating the elements runs at full C++ speed.</li>
+</ul>
+<p><i>nsIEnumerator</i> has similar enhancements.</p>
+<p>When implementing a Python XPCOM object, the Python class <i>xpcom.server.enumerator.SimpleEnumerator()</i>
+can be used.&nbsp; You can pass a standard Python sequence (list, etc), and it
+will be correctly wrapped in an <i>nsISimpleEnumerator</i> interface.</p>
+<h2>Files</h2>
+<p>The Python XPCOM package provides an <i> xpcom.file</i> module.&nbsp; This implements
+a Python-like file object on top of the XPCOM/Mozilla stream interfaces.&nbsp;
+When run from within the Mozilla environment, this allows you to open almost any
+URL supported by Mozilla (including &quot;chrome://&quot; etc.,).</p>
+<p>See this module for more information, including test code.</p>
+<h2>XPCOM Object Identity</h2>
+<p>XPCOM has defined rules for object identity and for how objects must behave
+in their <i> QueryInterface()</i> implementations.&nbsp; The Python XPCOM framework
+manages this for you; your code can return new Python instances etc., when
+responding to new interfaces, and the framework itself will ensure the XPCOM
+semantics are followed.&nbsp; Critically, the framework provides no mechanism
+for breaking these rules.</p>
+<h2>Policies</h2>
+<p>The Python XPCOM framework has the concept of &quot;policies&quot; that
+define how XPCOM semantics are mapped to Python objects.&nbsp; It is the policy
+that implements delegation of <i> QueryInterface()</i>, translates property
+references into direct property references, and failing that, &quot;get_name&quot;
+and &quot;set_name&quot; calls, decides how to handle exceptions in the
+component, and so on.</p>
+<p>The default policy is very flexible and suitable for most purposes.
+Indeed, the Komodo project has never had to implement a custom policy.
+However, you should be aware the feature exists should you wish to do some
+bizarre things, such as using Python as a bridge between XPCOM and some other
+component technology.</p>
+
+</body>
+
+</html>
Index: trunk/src/libs/xpcom18a4/python/doc/architecture.html
===================================================================
--- trunk/src/libs/xpcom18a4/python/doc/architecture.html	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/doc/architecture.html	(revision 11746)
@@ -0,0 +1,116 @@
+<html>
+<!-- ***** 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 ***** -->
+
+<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>Architecture</title>
+</head>
+
+<body>
+
+<h1>Python XPCOM Package Architecture</h1>
+<h2><a name="Architecture">Architecture</a></h2>
+<p>Much of the design for the Python XPCOM Package has been borrowed from the Python MS-COM
+extensions in <i>win32com</i>. Most of the major limitations and drawbacks in the <i>win32com</i>
+design have been addressed, mainly &quot;auto-wrapping&quot; of
+interface objects, which is not supported by <i>win32com</i>.</p>
+<p>Like <i>win32com</i>, this architecture includes the concept of <i>client COM</i> and <i>server
+COM.</i> </p>
+<p>Client COM:</p>
+<ul>
+  <li>calls other interfaces</li>
+  <li>is supported by <i>PyInterfaces</i> implemented in C++, which assists
+in making the COM calls</li>
+  <li>is supported by <i>PyGateways</i>, which assists in receiving
+external COM calls and dispatching them to the correct Python object</li>
+  <li> is supported in the <i>xpcom/client</i>  package</li>
+</ul>
+<p>Server COM:</p>
+<ul>
+  <li>implements interfaces for use by other XPCOM applications or components</li>
+  <li> is
+supported in the <i>xpcom/server</i>  package</li>
+</ul>
+<p>The XPConnect framework is very powerful, and far exceeds what COM's <i>
+IDispatch</i> can offer.&nbsp; Thus, we are able to get by with far fewer interfaces
+supported in the C++ level, and defer most things to the Python code that uses
+XPConnect.&nbsp; As a result, the requirement for a huge number of interfaces to
+exist in the <i>.pyd</i> does not exist.&nbsp; There are, however, a number of
+interfaces that do require native C++ support: these are interfaces
+required to &quot;boot&quot; the XPConnect support (i.e., the interfaces that are
+used to get information about interfaces), and also two gateways that need to
+work without interface information available. This last requirement is
+due to the XPCOM shutdown-ordering - it may be a bug, but is not an unreasonable
+amount of code anyway.</p>
+<p><b>Auto-wrapping</b> of COM objects is supported by both client COM and
+server COM.&nbsp;For client COM, auto-wrapping means that the
+Python programmer always sees Python &quot;component&quot; objects, rather than
+raw C++ interface objects; to the user, it all appears to &quot;just
+work&quot;.&nbsp; This is a major source of frustration in the <i>win32com</i>
+framework.</p>
+<p>For server COM, auto-wrapping means that you can
+pass Python instances wherever a COM object is expected. If the Python
+instance supports COM interfaces, by virtue of having a <i>_com_interfaces_</i>
+attribute that lists the interface requested, it will be automatically wrapped
+in the correct COM object.&nbsp;</p>
+<p><b>Error Handling:</b> The C++ framework has good error handling support,
+and uses the XPCOM console service to log debug messages, Python exceptions and
+tracebacks.&nbsp; <i>win32com</i> does not have good exception/traceback support
+at the C++ level, mainly because COM does not define a service like
+the console where debug messages can go.&nbsp; This does mean that in Mozilla
+release builds, these debug messages are likely to be lost, but the <i>--console</i>
+command line option to a release Mozilla will get them back.&nbsp; Therefore,
+the other error-support utilities, such as the error callbacks made on the
+policy object, may be used.</p>
+<p><b>Component Loader, Modules and Factories:</b>&nbsp; XPCOM has the concept
+of a component loader - a module used to load all components of a
+particular type.&nbsp; For example, the <i>moz.jsloader.1</i> component loads all
+the JavaScript components.&nbsp;Similarly, the <i>moz.pyloader.1</i>
+component loads all Python components.&nbsp; However, unlike
+JavaScript, the Python component loader is actually implemented in Python
+itself!&nbsp;Since the Python component loader can not be used to load
+itself, this component has some special code, <i>pyloader.dll,</i>  to boot-strap itself.</p>
+<p>This means is that all XPCOM components, including the Python loader itself and all
+XPCOM module and factory interfaces, are implemented in
+Python.&nbsp;<b>There are no components or interfaces implemented purely in C++
+in this entire package!</b></p>
+
+</body>
+
+</html>
Index: trunk/src/libs/xpcom18a4/python/doc/configure.html
===================================================================
--- trunk/src/libs/xpcom18a4/python/doc/configure.html	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/doc/configure.html	(revision 11746)
@@ -0,0 +1,196 @@
+<html>
+<!-- ***** 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 ***** -->
+
+<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>Configuring your Environment</title>
+</head>
+
+<body>
+
+<h1>Building, Configuring and Testing Python XPCOM Package</h1>
+<p>This document attempts to explain how to build, configure and test the
+Python XPCOM Package. This document assumes you have already successfully
+built
+Mozilla from source and your environment is currently set up for such a build -
+see the <a href="http://www.mozilla.org/build/">Mozilla build documentation</a>
+for more information.</p>
+<p>PyXPCOM can be built on Windows using either the <i>nmake makefile.win</i>
+process, or the <i>configure; gmake</i> process used by Linux.</p>
+<h2>configure; gmake Instructions</h2>
+<h3>Preparing for the build</h3>
+<ul>
+  <li>Apply the patch in <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=129216">bugzilla
+    bug 129216</a>. (If this bug is marked as &quot;FIXED&quot;, it probably
+    means there is no need to apply the patch and that these docs are out of
+    date)</li>
+  <li>On Linux, you must have Python built for dynamic linking.&nbsp; <a href="http://aspn.activestate.com/ASPN/Python">ActivePython</a>
+    2.1 is one such build.</li>
+  <li>On Windows, you must have a Python source tree installed and built.&nbsp;
+    Patches gratefully accepted that allow an installed Python to be used (it
+    should not be hard!)</li>
+  <li>Ensure the Python interpreter you wish to use is on your path, such that
+    &quot;python&quot; will execute it correctly.&nbsp; The configure process
+    uses this to locate the Python support files.</li>
+</ul>
+<h3>Building</h3>
+<ul>
+  <li>From the top-level Mozilla directory, execute <i>./configure
+    --enable-extensions=python/xpcom</i>. As per the Mozilla build
+    instructions, you may add this option to your <i>.mozconfig</i> file.&nbsp;
+    If you wish to enable debugging, just enable it as you would normally for
+    Mozilla; PyXPCOM will pick up the same settings.<br>
+    (On Windows you will need to execute <i>sh ./configure ...</i> if running
+    from a Command Prompt.&nbsp; See the <a href="http://www.mozilla.org/build/win32.html#ss2.2b">Mozilla
+    win32 specific gmake build instructions</a> for more details.</li>
+  <li>Build the Mozilla tree as normal; PyXPCOM will automatically be
+    built.&nbsp; Alternatively, change to the top-level PyXPCOM directory and
+    execute <i>gmake</i> in that directory.</li>
+</ul>
+<h2>PyXPCOM outside Mozilla</h2>
+<p>When you are using PyXPCOM from inside mozilla, no additional configuration
+options should be necessary.&nbsp; However, if you wish to use PyXPCOM from
+stand-alone Python (ie, so you can write simple Python scripts that can be
+executed normally and use XPCOM), then additional environment variables must be
+setup.</p>
+<ul>
+  <li><a name="PYTHONPATH"><b>PYTHONPATH</b></a> - <tt>PYTHONPATH</tt>  needs to
+    be set appropriately.&nbsp;You must manually ensure that the <i>mozilla/dist/bin/python</i>
+    directory (which is where PyXPCOM was installed during the build process) is
+    listed.&nbsp; Note that when PyXPCOM is used from within Mozilla (or any
+    other xpcom process), this path will automatically be added to sys.path.&nbsp;
+    It is only when Python directly uses xpcom that this step is necessary.<br>
+    If anything is wrong here you should get a normal <tt>ImportError</tt>.</li>
+</ul>
+<blockquote>
+  <p>Note that on Windows, the PYTHONPATH is generally maintained in the
+  Registry; however, you can set this variable at a DOS prompt, and it will still be
+added to the core PYTHONPATH.
+</blockquote>
+<ul>
+  <li><b><a name="PATH">PATH</a>, LD_LIBRARY_PATH, etc</b> - On Windows, you
+    must ensure that the Mozilla bin directory is listed on your PATH, or that
+    you execute your scripts with the Mozilla bin directory as the current
+    directory.<br>
+    On Linux, you must set your PATH and LD_LIBRARY_PATH variables
+    appropriately.&nbsp; However, you may find it simpler and easier to use the <i>run-mozilla.sh</i>
+    script in the Mozilla bin directory.&nbsp; For example, changing to the
+    Mozilla bin directory and executing:<br>
+    <i>./run-mozilla.sh python ~/src/mozilla/extensions/python/xpcom/test/regrtest.py</i><br>
+    should setup a correct environment and execute the PyXPCOM test suite.</li>
+</ul>
+<h2><a name="RunningTheTests">Testing your Setup</a></h2>
+<p>The Python XPCOM Package has a complete test suite.</p>
+<p>In the rest of this section, we walk through some simpler tests a step at a time,
+to help diagnose any problems.</p>
+<p><b>Note:</b> We recommend you do all your testing outside of <i> mozilla.exe</i>; it is far simpler to test all of
+this using the PyXPCOM package stand-alone.</p>
+<p><b>Note:</b> On Windows, if you use a debug build of Mozilla (i.e., in <i>dist\WIN32_D.OBJ\bin)</i>,
+    you <b>must</b> use <i>python_d.exe</i>; if you use a release build (i.e., in
+    a <i>dist\WIN32_O.OBJ\bin</i> directory), you must use <i>python.exe</i>.&nbsp;
+<i>makefile.stupid.win</i> handles this automatically.</p>
+<p>To test your setup:</p>
+<ol>
+  <li>Start Python, and check<br>
+    &gt;&gt;&gt; <i>import xpcom</i><br>
+    works. If not, <a href="#PYTHONPATH">check your PYTHONPATH</a> - the
+    main PyXPCOM package can not be located.&nbsp; Also check your <a href="#PATH">PATH</a>,
+    and if you are on Linux, remember that executing ./run-mozilla.sh python is
+    the easiest way.</li>
+  <li>Check<i><br>
+    &gt;&gt;&gt; import xpcom._xpcom</i><br>
+
+works. If not, then most likely your <a href="#PATH">Mozilla
+    directory is not on your path</a>, or something is wrong with <i>_xpcom(_d).pyd/_xpcommodule.so</i>.</li>
+
+  <li>Next run a simple test: <i>test/test_misc.py</i>.&nbsp;With a Windows debug build, the command may look like:<br>
+    <i>C:\Anywhere&gt; python_d \src\python\xpcom\test\test_misc.py<br>
+    </i>or on Linux<br>
+    <i>/home/user/src/mozilla/dist/bin$ python /home/user/src/python/xpcom/test/test_misc.py</i></li>
+</ol>
+<p>If you can't get this going, you won't get much further! (You may see a few
+errors - that is OK, as long as it appears something worked!).&nbsp; If
+everything looks OK, the
+next step is to register our test component and run our full test suite.</p>
+<h2><a name="Registration">Registering the Loader and Test Component</a></h2>
+<p>First register the generic Python loader. For instructions, see the <a href="file:///F:/src/as/Komodo/src/pyxpcom/xpcom/doc/architecture.html">architecture
+document</a>.&nbsp;Do this only once, regardless of how many
+Python components you have.&nbsp; Then install the test component itself, and
+finally you can test it!</p>
+<h3>Registering the Python Loader and Component</h3>
+<p>To register the Python Loader and Component:</p>
+<ol>
+  <li>Ensure the build process has put <i>pyloader.dll </i>(or <i>modpyloader.so</i>
+    for Unix), and the files <i> py_test_component.py </i> and <i> py_test_component.idl</i> into
+    the Mozilla <i>bin/components</i> directory.&nbsp; If not, copy the files
+    there manually.</li>
+  <li>Run <i>regxpcom </i>(or .<i>/run-mozilla.sh ./regxpcom</i> if appropriate).&nbsp;<i>regxpcom</i> is a standard Mozilla
+    executable, found in the <i>bin</i>  directory, that detects the new DLL and
+    .py
+    files and registers them accordingly.&nbsp; You should
+    see a few messages that include the following:</li>
+</ol>
+<blockquote>
+  <pre>Registering: PythonComponentLoader
+Registered 1 Python components in pyloader.dll
+nsNativeComponentLoader: autoregistering succeeded
+Auto-registering all Python components in F:\src\mozilla\dist\WIN32_D.OBJ\bin\components
+Registering: PythonTestComponent
+Registered 1 Python components in py_test_component.py</pre>
+</blockquote>
+<p>If so (or you see no message at all), you are ready to run the test suite.</p>
+<p><b>Note</b>: If you execute this same step a second time, you will not
+see any of the above mentioned messages.&nbsp;XPCOM knows that nothing has
+changed since you last ran <i>regxpcom</i>, so nothing is registered.&nbsp; If
+you do not see these messages the first time you run it, there is the
+possibility that some other process, possibly the build process, has already
+executed this step.</p>
+<h2><b>Running the Test Suite</b></h2>
+<p>Before running the test suite, you should change to the <i>mozilla/xpcom/sample</i>
+directory and build it.&nbsp; This will build and install a sample component
+which is used by the test suite.&nbsp; If you do not have this component
+available, some of the Python tests will fail.</p>
+
+<p>To run the test suite, run <i>xpcom/test/regrtest.py.</i>&nbsp; This runs the
+tests and ensures that the test output is as expected.&nbsp; If all tests
+pass, you have a fully functioning Python XPCOM package.&nbsp; Enjoy!</p>
+
+</body>
+
+</html>
Index: trunk/src/libs/xpcom18a4/python/doc/credits.html
===================================================================
--- trunk/src/libs/xpcom18a4/python/doc/credits.html	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/doc/credits.html	(revision 11746)
@@ -0,0 +1,86 @@
+<html>
+<!-- ***** 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 ***** -->
+
+<head>
+<meta http-equiv="Content-Language" content="en-au">
+<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>Credits and Acknowledgements</title>
+</head>
+
+<body>
+
+<h1>Credits and Acknowledgements</h1>
+<h2>ActiveState Tool Corporation</h2>
+<p>The Python XPCOM Package was developed primarily by <a href="mailto:markh@activestate.com">Mark
+Hammond</a> of <a href="http://www.ActiveState.com">ActiveState Tool Corporation</a>.</p>
+<p>The developers on the <a href="http://www.ActiveState.com/Products/Komodo">Komodo
+project</a> deserve high praise for putting up with early versions when almost
+nothing worked, and for believing in Python as a viable XPCOM language.&nbsp;
+Their feedback and patience has allowed the first public release to be amazingly
+functional and bug-free.</p>
+<h3>Komodo Development Team (at December 2000)</h3>
+<p><a href="mailto:davida@activestate.com">David Ascher</a>, <a href="mailto:aaronb@ActiveState.com">Aaron Bingham</a>,
+<a href="mailto:bindu@activestate.com">Bin Du</a>, <a href="mailto:markh@activestate.com">Mark
+Hammond</a>, <a href="mailto:trentm@activestate.com">Trent Mick (build god)</a>,&nbsp;
+<a href="mailto:paulp@activestate.com">Paul Prescod</a>,&nbsp; <a href="mailto:ericp@ActiveState.com">Eric Promislow</a>,
+<a href="mailto:kens@ActiveState.com">Ken Simpson</a>, <a href="mailto:neilw@ActiveState.com">Neil Watkiss</a>,
+<a href="mailto:AudreyS@ActiveState.com">Audrey Schumacher</a>.</p>
+<h2>Mozilla/Netscape</h2>
+<p>The following people at <a href="http://www.netscape.com">Netscape</a> and <a href="http://www.mozilla.org">Mozilla</a>
+(or not there but still heavily involved in the project) have provided enormous
+help in getting things integrated with their build system, answering us on the
+newsgroup, teaching us the finer points of XPCOM, gently slapping us for accidentally
+referring to <i>jscript</i>, etc., and otherwise lending us a clue in the
+Mozilla/Netscape/XPCOM world.</p>
+<p><a href="mailto:jband@netscape.com">John Bandhauer</a>, <a href="mailto:brendan@meer.net">Brendan
+Eich</a>, <a href="mailto:shaver@zeroknowledge.com">Mike Shaver</a>, <a href="mailto:evaughan@netscape.com">Eric Vaughan</a>,
+<a href="mailto:hyatt@netscape.com">David Hyatt</a></p>
+<h2>External Contributors</h2>
+<p>The following people have made contributions to the project, simply because
+they find it useful and enjoy supporting Open Source projects.</p>
+<p><a href="mailto:cmeerw@web.de">Christof Meerwald</a></p>
+<h2>Documentation Credits</h2>
+<p>The following people have contributed to the Python XPCOM Package
+documentation&nbsp;</p>
+<p><a href="mailto:markh@activestate.com">Mark
+Hammond</a>, <a href="mailto:AudreyS@ActiveState.com">Audrey Schumacher</a></p>
+
+</body>
+
+</html>
Index: trunk/src/libs/xpcom18a4/python/doc/tutorial.html
===================================================================
--- trunk/src/libs/xpcom18a4/python/doc/tutorial.html	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/doc/tutorial.html	(revision 11746)
@@ -0,0 +1,286 @@
+<html>
+<!-- ***** 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 ***** -->
+
+<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>Python XPCOM Package Tutorial</title>
+</head>
+
+<body>
+
+<h1>Python XPCOM Package Tutorial</h1>
+<p>This is a quick introduction to the Python XPCOM Package. We assume that you have a good understanding of Python and <a href="http://www.mozilla.org/projects/xpcom/">XPCOM</a>,
+and have experience both using and implementing XPCOM objects in some other
+language (e.g., C++ or JavaScript). We <b><i>do not</i></b> attempt to
+provide a tutorial to XPCOM or Python itself, only to using Python <i>and</i>
+ XPCOM.</p>
+<p>This tutorial contains the following sections:</p>
+<ul>
+  <li><a href="#Using">Using XPCOM Objects and Interfaces</a> - when you wish to
+    <i>use</i> a component written by anyone else in any XPCOM supported
+    language.</li>
+  <li><a href="#Implementing">Implementing XPCOM Objects and Interfaces</a> -
+    when you wish to implement a component for use by anyone else in any xpcom
+    supported language.</li>
+  <li><a href="#Parameters">Parameters and Types</a> - useful information
+    regarding how Python translates XPCOM types, and handles byref parameters.</li>
+</ul>
+<p>For anything not covered here, try the <a href="advanced.html">advanced
+documentation</a>, and if that fails, use the source, Luke!</p>
+<h2><a name="Using">Using XPCOM object and interfaces.</a></h2>
+<p>The techniques for using XPCOM in Python have been borrowed from JavaScript -
+thus, the model described here should be quite familiar to existing JavaScript
+XPCOM programmers.</p>
+<h3>xpcom.components module</h3>
+<p>When using an XPCOM object, the primary module used is the <u><i>xpcom.components</i></u>
+ module.&nbsp; Using this module, you can get a Python object that supports any
+scriptable XPCOM interface. Once you have this Python object, you can
+simply call XPCOM methods on the object, as normal.</p>
+<p>The <u><i>xpcom.components</i></u> module defines the following public
+members:</p>
+<table border="1" width="100%">
+  <tr>
+    <td width="16%"><b>Name</b></td>
+    <td width="84%"><b>Description</b></td>
+  </tr>
+  <tr>
+    <td width="16%">classes</td>
+    <td width="84%">A mapping (dictionary-like object) used to get XPCOM
+      &quot;classes&quot;.&nbsp; These are indexed by XPCOM contract ID, just
+      like the JavaScript object of the same name.&nbsp;&nbsp;
+      <p>Example:</p>
+      <pre>cls = components.classes[&quot;@mozilla.org/sample;1&quot;]
+ob = cls.createInstance() # Now have an nsISupports</pre>
+    </td>
+  </tr>
+  <tr>
+    <td width="16%">interfaces</td>
+    <td width="84%">An object that exposes all XPCOM interface IDs (IIDs).&nbsp;
+      Like the JavaScript object of the same name, this object uses
+      &quot;dot&quot; notation, as demonstrated below.
+      <p>Example:</p>
+      <pre>ob = cls.createInstance(components.interfaces.nsISample) 
+# Now have an nsISample</pre>
+    </td>
+  </tr>
+</table>
+<p>For many people, this is all you need to know. Consider the Mozilla Sample Component.&nbsp; The Mozilla Sample
+Component has a contract ID of <i>@mozilla.org/sample;1</i>,
+and implements the <i>nsISample</i> interface.</p>
+<p>Thus, a complete Python program that uses this component is shown below.</p>
+<pre>from xpcom import components
+cls = components.classes[&quot;@mozilla.org/sample;1&quot;]
+ob = cls.createInstance() # no need to specify an IID for most components
+# nsISample defines a &quot;value&quot; property - let's use it!
+ob.value = &quot;new value&quot;
+if ob.value != &quot;new value&quot;:
+    print &quot;Eeek - what happened?&quot;</pre>
+<p>And that is it - a complete Python program that uses XPCOM.</p>
+<h2><a name="Implementing">Implementing XPCOM Objects and Interfaces.</a></h2>
+<p>Implementing XPCOM objects is almost as simple as using them. The
+basic strategy is this:</p>
+<ol>
+  <li>Create a standard Python source file, with a standard Python class.</li>
+  <li>Add some special <a href="#Attributes"> attributes</a> to your class for use by the Python XPCOM
+    framework. This controls the XPCOM behavior of your object.</li>
+  <li>Implement the XPCOM <a href="#Properties"> properties</a> and methods of your classes as normal.</li>
+  <li>Put the Python source file in the Mozilla <i> components</i> directory.</li>
+  <li>Run <i> regxpcom.</i></li>
+</ol>
+<p>Your component is now ready to be used.</p>
+<h3><a name="Attributes">Attributes</a></h3>
+<p>There are two classes of attributes: those used at runtime to define the object
+behavior and those used at registration time to control object
+registration.&nbsp; Not all objects require registration, thus not all
+Python XPCOM objects will have registration-related attributes.</p>
+<table border="1" width="100%">
+  <tr>
+    <td width="17%"><b>Attribute</b></td>
+    <td width="83%"><b>Description</b></td>
+  </tr>
+  <tr>
+    <td width="17%">_com_interfaces_</td>
+    <td width="83%">The interface IDs (IIDs) supported by the component.&nbsp;
+      For simplicity, this may be either a single IID, or a list of IIDs.&nbsp;
+      There is no need to specify base interfaces, as all parent interfaces are
+      automatically supported. Thus, it is never necessary to nominate <i>
+      nsISupports</i> in the list of interfaces.
+      <p>This attribute is required. Objects without such an attribute are
+      deemed unsuitable for use as a XPCOM object.</td>
+  </tr>
+  <tr>
+    <td width="17%">_reg_contractid_</td>
+    <td width="83%">The contract ID of the component.&nbsp; Required if the
+      component requires registration (i.e., exists in the components directory).</td>
+  </tr>
+  <tr>
+    <td width="17%">_reg_clsid_</td>
+    <td width="83%">The Class ID (CLSID) of the component, as a string in the
+      standard &quot;{XXX-XXX-XXX-XXX}&quot; format. Required if the
+      component requires registration (i.e., exists in the components directory).</td>
+  </tr>
+  <tr>
+    <td width="17%">_reg_registrar_</td>
+    <td width="83%">Nominates a function that is called at registration
+      time. The default is for no extra function to be called. This can
+      be useful if a component has special registration requirements and needs
+      to hook into the registration process.</td>
+  </tr>
+  <tr>
+    <td width="17%">_reg_desc_</td>
+    <td width="83%">The description of the XPCOM object. This may be used by
+      browsers or other such objects.&nbsp; If not specified, the contract ID
+      is used.</td>
+  </tr>
+</table>
+<h3><a name="Properties">Properties</a></h3>
+<p>A Python class can support XPCOM properties in one of two ways.&nbsp; Either
+a standard Python property of the same name can exist - our sample
+component demonstrates this with the <i>boolean_value</i> property.&nbsp;
+Alternatively, the class can provide the <i>get_propertyName(self)</i> and <i>set_propertyName(self,
+value)</i>  functions (with <i>propertyName</i> changed to the appropriate value for the
+property), and these functions will be called instead.</p>
+<h4>Example:&nbsp; The Python XPCOM Test Component</h4>
+<p>As an example, examine the Python XPCOM Test Component.&nbsp; This
+code can be found in <i>py_test_component.py</i>.</p>
+<pre>from xpcom import components
+
+class PythonTestComponent:
+    _com_interfaces_ = components.interfaces.nsIPythonTestInterface
+    _reg_clsid_ = &quot;{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}&quot;
+    _reg_contractid_ = &quot;Python.TestComponent&quot;
+    def __init__(self):
+        self.boolean_value = 1
+        ...
+    def do_boolean(self, p1, p2):
+        ret = p1 ^ p2
+        return ret, not ret, ret
+...</pre>
+<p><b>Note:</b> This component only specifies the mandatory attributes - <i>_com_interfaces</i>,
+<i>_reg_clsid_</i> and <i>_reg_contractid_</i>.</p>
+<p>This sample code demonstrates supporting the <i>boolean_value</i> attribute,
+supported implicitly, as it is defined in the IDL and exists as a real Python
+attribute of that name, and a method called <i>do_boolean</i>.</p>
+<h4>Tip: The xpcom/xpt.py Script</h4>
+<p> The xpcom/xpt.py script is a useful script that can generate the skeleton of a class for
+any XPCOM interface.&nbsp; Just specify the interface name on the command-line,
+and paste the output into your source file.</p>
+<p>This is the output of running this program over the <i>nsISample</i>
+interface (i.e., assuming we wanted to implement a component that supported this
+interface):</p>
+<pre>class nsISample:
+    _com_interfaces_ = xpcom.components.interfaces.nsISample
+    # If this object needs to be registered, the following 2 are also needed.
+    # _reg_clsid_ = {a new clsid generated for this object}
+    # _reg_contractid_ = &quot;The.Object.Name&quot;
+
+    def get_value( self ):
+        # Result: string
+        pass
+    def set_value( self, param0 ):
+        # Result: void - None
+        # In: param0: string
+        pass
+    def writeValue( self, param0 ):
+        # Result: void - None
+        # In: param0: string
+        pass
+    def poke( self, param0 ):
+        # Result: void - None
+        # In: param0: string
+        pass</pre>
+<p><b>Note:</b> The types of the parameters and the function itself are included in
+the comments.&nbsp;You need to implement the functions
+themselves.&nbsp; Another advantage of this script is that the <a href="#HiddenParams">hidden
+parameters</a> are handled for you; the comments indicate when parameters
+have been hidden.</p>
+<h2><a name="Parameters">Parameters and Types</a></h2>
+<p>This section briefly describes the XPCOM type support in
+Python.</p>
+<p>All XPCOM interfaces define parameters of a specific type.&nbsp; There is
+currently no concept of a variant, or union of all types. Thus, the
+conversion rules are very straightforward, and generally surprise free: for
+any given XPCOM method, there is only one possible type for a given parameter.</p>
+<h3>Type Conversion Rules:</h3>
+<ul>
+  <li>All numeric types will attempt to be coerced to the correct type.&nbsp;
+    Thus, you can pass a Python float to an XPCOM method expecting an integer,
+    or vice-versa. Specifically, when an integer is required, you can pass
+    any Python object for which <i>int()</i> would succeed; for a Python float,
+    any object for which <i>float()</i> would succeed is acceptable.&nbsp; This
+    means that you can pass a Python string object as an integer, as long as the
+    string was holding a valid integer.</li>
+  <li>Strings and Unicode objects are interchangeable, but no other automatic
+    string conversions are performed.&nbsp; Thus, you can not pass an integer
+    where a string is expected, even though the reverse is true.</li>
+  <li>Any sequence object can be passed as an array.&nbsp; List objects are
+    always returned for arrays.</li>
+  <li>Any Python instance suitable for use as a XPCOM object (i.e., with the
+    <a href="#Implementing">necessary annotations</a>) can be
+    passed as a XPCOM object. No special wrapping step is needed to turn a
+    Python instance into a XPCOM object.&nbsp; Note you must pass a class <i>instance</i>,
+    not the class itself.</li>
+  <li><a name="HiddenParams">Many XPCOM <b> method signatures</b> specify
+    &quot;count&quot; or &quot;size&quot; parameters.&nbsp; For example, every
+    time an array is passed via XPCOM, the method signature will always specify
+    an integer that holds the count of the array.&nbsp; These parameters are
+    always hidden in Python.&nbsp; As the size param can be implied from the
+    length of the Python sequence passed, the Python programmer need never pass
+    these parameters;&nbsp;in contrast, JavaScript requires these redundant parameters.</a></li>
+</ul>
+
+<h2>Interface Flattening</h2>
+<p>Most people can ignore this information - Python XPCOM objects just
+work.&nbsp; However, if you are familiar with xpcom from C++ and the concept of <i>QueryInterface</i>,
+you may like to read this.</p>
+<p>Most components support the concept of &quot;interface
+flattening&quot;.&nbsp; Such objects can report the interfaces they support,
+allowing languages such as Python and Javascript avoid using <i>QueryInterface</i>.&nbsp;
+When you are using an XPCOM object from Python, you can just call methods and
+reference properties without regard for the interface that implements it.</p>
+<p>When multiple interfaces share the same method or property name, you can use
+the name of the interface as a differentiator.&nbsp; Thus, <i>ob.nsIFoo.close()</i>
+will call close on <i>ob</i>'s <i>nsIFoo</i> interface, while <i>ob.nsIBar.close()</i>
+will use the <i>nsIBar</i> interface.&nbsp; <i>ob.close()</i> is not defined.</p>
+
+</body>
+
+</html>
+
+
Index: trunk/src/libs/xpcom18a4/python/file.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/file.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/file.py	(revision 11746)
@@ -0,0 +1,318 @@
+# ***** 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, 2001
+# 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 *****
+
+"""Implementation of Python file objects for Mozilla/xpcom.
+
+Introduction:
+  This module defines various class that are implemented using 
+  Mozilla streams.  This allows you to open Mozilla URI's, and
+  treat them as Python file object.
+  
+Example:
+>>> file = URIFile("chrome://whatever")
+>>> data = file.read(5) # Pass no arg to read everything.
+
+Known Limitations:
+ * Not all URL schemes will work from "python.exe" - most notably
+   "chrome://" and "http://" URLs - this is because a simple initialization of
+   xpcom by Python does not load up the full set of Mozilla URL handlers.
+   If you can work out how to correctly initialize the chrome registry and
+   setup a message queue.
+
+Known Bugs:
+  * Only read ("r") mode is supported.  Although write ("w") mode doesnt make
+    sense for HTTP type URLs, it potentially does for file:// etc type ones.
+  * No concept of text mode vs binary mode.  It appears Mozilla takes care of
+    this internally (ie, all "text/???" mime types are text, rest are binary)
+
+"""
+
+from xpcom import components, Exception, _xpcom
+import os
+import threading # for locks.
+
+NS_RDONLY        = 0x01
+NS_WRONLY        = 0x02
+NS_RDWR          = 0x04
+NS_CREATE_FILE   = 0x08
+NS_APPEND        = 0x10
+NS_TRUNCATE      = 0x20
+NS_SYNC          = 0x40
+NS_EXCL          = 0x80
+
+# A helper function that may come in useful
+def LocalFileToURL(localFileName):
+    "Convert a filename to an XPCOM nsIFileURL object."
+    # Create an nsILocalFile
+    localFile = components.classes["@mozilla.org/file/local;1"] \
+          .createInstance(components.interfaces.nsILocalFile)
+    localFile.initWithPath(localFileName)
+
+    # Use the IO Service to create the interface, then QI for a FileURL
+    io_service = components.classes["@mozilla.org/network/io-service;1"] \
+                    .getService(components.interfaces.nsIIOService)
+    url = io_service.newFileURI(localFile).queryInterface(components.interfaces.nsIFileURL)
+    # Setting the "file" attribute causes initialization...
+    url.file = localFile
+    return url
+
+# A base class for file objects.
+class _File:
+    def __init__(self, name_thingy = None, mode="r"):
+        self.lockob = threading.Lock()
+        self.inputStream = self.outputStream = None
+        if name_thingy is not None:
+                self.init(name_thingy, mode)
+
+    def __del__(self):
+        self.close()
+
+    # The Moz file streams are not thread safe.
+    def _lock(self):
+        self.lockob.acquire()
+    def _release(self):
+        self.lockob.release()
+    def read(self, n = -1):
+        assert self.inputStream is not None, "Not setup for read!"
+        self._lock()
+        try:
+            return str(self.inputStream.read(n))
+        finally:
+            self._release()
+
+    def readlines(self):
+        # Not part of the xpcom interface, but handy for direct Python users.
+        # Not 100% faithful, but near enough for now!
+        lines = self.read().split("\n")
+        if len(lines) and len(lines[-1]) == 0:
+            lines = lines[:-1]
+        return [s+"\n" for s in lines ]
+
+    def write(self, data):
+        assert self.outputStream is not None, "Not setup for write!"
+        self._lock()
+        try:
+            self.outputStream.write(data, len(data))
+        finally:
+            self._release()
+
+    def close(self):
+        self._lock()
+        try:
+            if self.inputStream is not None:
+                self.inputStream.close()
+                self.inputStream = None
+            if self.outputStream is not None:
+                self.outputStream.close()
+                self.outputStream = None
+            self.channel = None
+        finally:
+            self._release()
+
+    def flush(self):
+        self._lock()
+        try:
+            if self.outputStream is not None: self.outputStream.flush()
+        finally:
+            self._release()
+
+# A synchronous "file object" used to open a URI.
+class URIFile(_File):
+    def init(self, url, mode="r"):
+        self.close()
+        if mode != "r":
+            raise ValueError, "only 'r' mode supported'"
+        io_service = components.classes["@mozilla.org/network/io-service;1"] \
+                        .getService(components.interfaces.nsIIOService)
+        if hasattr(url, "queryInterface"):
+            url_ob = url
+        else:
+            url_ob = io_service.newURI(url, None, None)
+        # Mozilla asserts and starts saying "NULL POINTER" if this is wrong!
+        if not url_ob.scheme:
+            raise ValueError, ("The URI '%s' is invalid (no scheme)" 
+                                  % (url_ob.spec,))
+        self.channel = io_service.newChannelFromURI(url_ob)
+        self.inputStream = self.channel.open()
+
+# A "file object" implemented using Netscape's native file support.
+# Based on io.js - http://lxr.mozilla.org/seamonkey/source/xpcom/tests/utils/io.js
+# You open this file using a local file name (as a string) so it really is pointless - 
+# you may as well be using a standard Python file object!
+class LocalFile(_File):
+    def __init__(self, *args):
+        self.fileIO = None
+        _File.__init__(self, *args)
+
+    def init(self, name, mode = "r"):
+        name = os.path.abspath(name) # Moz libraries under Linux fail with relative paths.
+        self.close()
+        file = components.classes['@mozilla.org/file/local;1'].createInstance("nsILocalFile")
+        file.initWithPath(name)
+        if mode in ["w","a"]:
+            self.fileIO = components.classes["@mozilla.org/network/file-output-stream;1"].createInstance("nsIFileOutputStream")
+            if mode== "w":
+                if file.exists():
+                    file.remove(0)
+                moz_mode = NS_CREATE_FILE | NS_WRONLY
+            elif mode=="a":
+                moz_mode = NS_APPEND
+            else:
+                assert 0, "Can't happen!"
+            self.fileIO.init(file, moz_mode, -1,0)
+            self.outputStream = self.fileIO
+        elif mode == "r":
+            self.fileIO = components.classes["@mozilla.org/network/file-input-stream;1"].createInstance("nsIFileInputStream")
+            self.fileIO.init(file, NS_RDONLY, -1,0)
+            self.inputStream = components.classes["@mozilla.org/scriptableinputstream;1"].createInstance("nsIScriptableInputStream")
+            self.inputStream.init(self.fileIO)
+        else:
+            raise ValueError, "Unknown mode"
+
+    def close(self):
+        if self.fileIO is not None:
+            self.fileIO.close()
+            self.fileIO = None
+        _File.close(self)
+
+    def read(self, n = -1):
+        return _File.read(self, n)
+
+
+##########################################################
+##
+## Test Code
+##
+##########################################################
+def _DoTestRead(file, expected):
+    # read in a couple of chunks, just to test that our various arg combinations work.
+    got = file.read(3)
+    got = got + file.read(300)
+    got = got + file.read(0)
+    got = got + file.read()
+    if got != expected:
+        raise RuntimeError, "Reading '%s' failed - got %d bytes, but expected %d bytes" % (file, len(got), len(expected))
+
+def _DoTestBufferRead(file, expected):
+    # read in a couple of chunks, just to test that our various arg combinations work.
+    buffer = _xpcom.AllocateBuffer(50)
+    got = ''
+    while 1:
+        # Note - we need to reach into the file object so we
+        # can get at the native buffer supported function.
+        num = file.inputStream.read(buffer)
+        if num == 0:
+            break
+        got = got + str(buffer[:num])
+    if got != expected:
+        raise RuntimeError, "Reading '%s' failed - got %d bytes, but expected %d bytes" % (file, len(got), len(expected))
+
+def _TestLocalFile():
+    import tempfile, os
+    fname = tempfile.mktemp()
+    data = "Hello from Python"
+    test_file = LocalFile(fname, "w")
+    try:
+        test_file.write(data)
+        test_file.close()
+        # Make sure Python can read it OK.
+        f = open(fname, "r")
+        assert f.read() == data, "Eeek - Python could not read the data back correctly!"
+        f.close()
+        # For the sake of the test, try a re-init.
+        test_file.init(fname, "r")
+        got = str(test_file.read())
+        assert got == data, got
+        test_file.close()
+        # Try reading in chunks.
+        test_file = LocalFile(fname, "r")
+        got = test_file.read(10) + test_file.read()
+        assert got == data, got
+        test_file.close()
+        # Open the same file again for writing - this should delete the old one.
+        if not os.path.isfile(fname):
+            raise RuntimeError, "The file '%s' does not exist, but we are explicitly testing create semantics when it does" % (fname,)
+        test_file = LocalFile(fname, "w")
+        test_file.write(data)
+        test_file.close()
+        # Make sure Python can read it OK.
+        f = open(fname, "r")
+        assert f.read() == data, "Eeek - Python could not read the data back correctly after recreating an existing file!"
+        f.close()
+
+        # XXX - todo - test "a" mode!
+    finally:
+        os.unlink(fname)
+
+def _TestAll():
+    # A mini test suite.
+    # Get a test file, and convert it to a file:// URI.
+    # check what we read is the same as when
+    # we read this file "normally"
+    fname = components.__file__
+    if fname[-1] in "cCoO": # fix .pyc/.pyo
+            fname = fname[:-1]
+    expected = open(fname, "rb").read()
+    # convert the fname to a URI.
+    url = LocalFileToURL(fname)
+    # First try passing a URL as a string.
+    _DoTestRead( URIFile( url.spec), expected)
+    # Now with a URL object.
+    _DoTestRead( URIFile( url ), expected)
+
+    _DoTestBufferRead( URIFile( url ), expected)
+
+    # For the sake of testing, do our pointless, demo object!
+    _DoTestRead( LocalFile(fname), expected )
+
+    # Now do the full test of our pointless, demo object!
+    _TestLocalFile()
+
+def _TestURI(url):
+    test_file = URIFile(url)
+    print "Opened file is", test_file
+    got = test_file.read()
+    print "Read %d bytes of data from %r" % (len(got), url)
+    test_file.close()
+
+if __name__=='__main__':
+    import sys
+    if len(sys.argv) < 2:
+        print "No URL specified on command line - performing self-test"
+        _TestAll()
+    else:
+        _TestURI(sys.argv[1])
Index: trunk/src/libs/xpcom18a4/python/nsError.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/nsError.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/nsError.py	(revision 11746)
@@ -0,0 +1,154 @@
+# ***** 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) 2000, 2001
+# ActiveState Tool Corp.  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 *****
+
+# Generated by h2py from nsError.h
+# CMD line: h2py.py -i (nsresult) nsError.h
+
+# XXX - NOTE - some manual code at the end, and all literals moved back to ints
+NS_ERROR_MODULE_XPCOM = 1
+NS_ERROR_MODULE_BASE = 2
+NS_ERROR_MODULE_GFX = 3
+NS_ERROR_MODULE_WIDGET = 4
+NS_ERROR_MODULE_CALENDAR = 5
+NS_ERROR_MODULE_NETWORK = 6
+NS_ERROR_MODULE_PLUGINS = 7
+NS_ERROR_MODULE_LAYOUT = 8
+NS_ERROR_MODULE_HTMLPARSER = 9
+NS_ERROR_MODULE_RDF = 10
+NS_ERROR_MODULE_UCONV = 11
+NS_ERROR_MODULE_REG = 12
+NS_ERROR_MODULE_FILES = 13
+NS_ERROR_MODULE_DOM = 14
+NS_ERROR_MODULE_IMGLIB = 15
+NS_ERROR_MODULE_MAILNEWS = 16
+NS_ERROR_MODULE_EDITOR = 17
+NS_ERROR_MODULE_XPCONNECT = 18
+NS_ERROR_MODULE_PROFILE = 19
+def NS_FAILED(_nsresult): return ((_nsresult) & -2147483648)
+
+NS_ERROR_SEVERITY_SUCCESS = 0
+NS_ERROR_SEVERITY_ERROR = 1
+NS_ERROR_MODULE_BASE_OFFSET = 69
+def NS_ERROR_GET_CODE(err): return ((err) & 65535)
+
+def NS_ERROR_GET_MODULE(err): return (((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 8191))
+
+def NS_ERROR_GET_SEVERITY(err): return (((err) >> 31) & 1)
+
+NS_OK = 0
+NS_COMFALSE = 1
+NS_ERROR_BASE = (  -1041039360)
+NS_ERROR_NOT_INITIALIZED = (NS_ERROR_BASE + 1)
+NS_ERROR_ALREADY_INITIALIZED = (NS_ERROR_BASE + 2)
+NS_ERROR_NOT_IMPLEMENTED = (  -2147467263)
+NS_NOINTERFACE = (  -2147467262)
+NS_ERROR_NO_INTERFACE = NS_NOINTERFACE
+NS_ERROR_INVALID_POINTER = (  -2147467261)
+NS_ERROR_NULL_POINTER = NS_ERROR_INVALID_POINTER
+NS_ERROR_ABORT = (  -2147467260)
+NS_ERROR_FAILURE = (  -2147467259)
+NS_ERROR_UNEXPECTED = (  -2147418113)
+NS_ERROR_OUT_OF_MEMORY = (  -2147024882)
+NS_ERROR_ILLEGAL_VALUE = (  -2147024809)
+NS_ERROR_INVALID_ARG = NS_ERROR_ILLEGAL_VALUE
+NS_ERROR_NO_AGGREGATION = (  -2147221232)
+NS_ERROR_NOT_AVAILABLE = (  -2147221231)
+NS_ERROR_FACTORY_NOT_REGISTERED = (  -2147221164)
+NS_ERROR_FACTORY_REGISTER_AGAIN = (  -2147221163)
+NS_ERROR_FACTORY_NOT_LOADED = (  -2147221000)
+NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT = \
+                                           (NS_ERROR_BASE + 257)
+NS_ERROR_FACTORY_EXISTS = (NS_ERROR_BASE + 256)
+NS_ERROR_PROXY_INVALID_IN_PARAMETER = (  -2147418096)
+NS_ERROR_PROXY_INVALID_OUT_PARAMETER = (  -2147418095)
+
+##### END OF GENERATED CODE
+#####
+def NS_ERROR_GENERATE_FAILURE(module,code):
+	# slightly optimized, and avoids 2.3->2.4 long/int changes
+	# return (NS_ERROR_SEVERITY_ERROR<<31) | ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
+	return -2147483648 | ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
+
+def NS_ERROR_GENERATE_SUCCESS(module,code):
+	#return (NS_ERROR_SEVERITY_SUCCESS<<31) | ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
+	return ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
+
+NS_BASE_STREAM_CLOSED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 2)
+NS_BASE_STREAM_OSERROR = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 3)
+NS_BASE_STREAM_ILLEGAL_ARGS = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 4)
+NS_BASE_STREAM_NO_CONVERTER = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 5)
+NS_BASE_STREAM_BAD_CONVERSION = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 6)
+NS_BASE_STREAM_WOULD_BLOCK = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 7)
+NS_ERROR_FILE_UNRECOGNIZED_PATH = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 1)
+NS_ERROR_FILE_UNRESOLVABLE_SYMLINK = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 2)
+NS_ERROR_FILE_EXECUTION_FAILED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 3)
+NS_ERROR_FILE_UNKNOWN_TYPE = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 4)
+NS_ERROR_FILE_DESTINATION_NOT_DIR = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 5)
+NS_ERROR_FILE_TARGET_DOES_NOT_EXIST = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 6)
+NS_ERROR_FILE_COPY_OR_MOVE_FAILED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 7)
+NS_ERROR_FILE_ALREADY_EXISTS = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 8)
+NS_ERROR_FILE_INVALID_PATH = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 9)
+NS_ERROR_FILE_DISK_FULL = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 10)
+NS_ERROR_FILE_CORRUPTED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 11)
+NS_ERROR_FILE_NOT_DIRECTORY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 12)
+NS_ERROR_FILE_IS_DIRECTORY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 13)
+NS_ERROR_FILE_IS_LOCKED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 14)
+NS_ERROR_FILE_TOO_BIG = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 15)
+NS_ERROR_FILE_NO_DEVICE_SPACE = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 16)
+NS_ERROR_FILE_NAME_TOO_LONG = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 17)
+NS_ERROR_FILE_NOT_FOUND = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 18)
+NS_ERROR_FILE_READ_ONLY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 19)
+NS_ERROR_FILE_DIR_NOT_EMPTY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 20)
+NS_ERROR_FILE_ACCESS_DENIED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 21)
+
+## from netCore.h
+NS_ERROR_ALREADY_CONNECTED =  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 11)
+
+NS_ERROR_NOT_CONNECTED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 12)
+NS_ERROR_IN_PROGRESS = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 15)
+NS_ERROR_OFFLINE = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 16)
+
+## from nsISocketTransportService.idl
+NS_ERROR_CONNECTION_REFUSED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 13)
+
+NS_ERROR_NET_TIMEOUT = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 14)
+
+# Status nsresult codes: used with nsIProgressEventSink::OnStatus 
+NS_NET_STATUS_RESOLVING_HOST  = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 3)
+NS_NET_STATUS_CONNECTED_TO    = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 4)
+NS_NET_STATUS_SENDING_TO      = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 5)
+NS_NET_STATUS_RECEIVING_FROM  = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 6)
+NS_NET_STATUS_CONNECTING_TO   = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 7)
Index: trunk/src/libs/xpcom18a4/python/primitives.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/primitives.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/primitives.py	(revision 11746)
@@ -0,0 +1,39 @@
+# Various utilities for working with nsISupportsPrimitive
+from xpcom import components
+
+_primitives_map = {}
+
+def _build_map():
+    ifaces = components.interfaces
+    iface = ifaces.nsISupportsPrimitive
+    m = _primitives_map
+    
+    m[iface.TYPE_ID] = ifaces.nsISupportsID
+    m[iface.TYPE_CSTRING] = ifaces.nsISupportsCString
+    m[iface.TYPE_STRING] = ifaces.nsISupportsString
+    m[iface.TYPE_PRBOOL] = ifaces.nsISupportsPRBool
+    m[iface.TYPE_PRUINT8] = ifaces.nsISupportsPRUint8
+    m[iface.TYPE_PRUINT16] = ifaces.nsISupportsPRUint16
+    m[iface.TYPE_PRUINT32] = ifaces.nsISupportsPRUint32
+    m[iface.TYPE_PRUINT64] = ifaces.nsISupportsPRUint64
+    m[iface.TYPE_PRINT16] = ifaces.nsISupportsPRInt16
+    m[iface.TYPE_PRINT32] = ifaces.nsISupportsPRInt32
+    m[iface.TYPE_PRINT64] = ifaces.nsISupportsPRInt64
+    m[iface.TYPE_PRTIME] = ifaces.nsISupportsPRTime
+    m[iface.TYPE_CHAR] = ifaces.nsISupportsChar
+    m[iface.TYPE_FLOAT] = ifaces.nsISupportsFloat
+    m[iface.TYPE_DOUBLE] = ifaces.nsISupportsDouble
+    # Do interface pointer specially - it provides the IID.
+    #m[iface.TYPE_INTERFACE_POINTER] = ifaces.nsISupportsDouble
+    
+def GetPrimitive(ob):
+    if len(_primitives_map)==0:
+        _build_map()
+
+    prin = ob.QueryInterface(components.interfaces.nsISupportsPrimitive)
+    try:
+        better = _primitives_map[prin.type]
+    except KeyError:
+        raise ValueError, "This primitive type (%d) is not supported" % (prin.type,)
+    prin = prin.QueryInterface(better)
+    return prin.data
Index: trunk/src/libs/xpcom18a4/python/readme.html
===================================================================
--- trunk/src/libs/xpcom18a4/python/readme.html	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/readme.html	(revision 11746)
@@ -0,0 +1,121 @@
+<html>
+<!-- ***** 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 ***** -->
+
+<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>Python XPCOM module</title>
+</head>
+
+<body>
+
+<h1>Python XPCOM Package</h1>
+
+<p>Mozilla CVS Version - Last updated May 2002</p>
+<p>This is the readme for the Python interface to <b>XPCOM</b>.</p>
+<p><b>XPCOM </b>is an acronym for &quot;Cross Platform COM&quot;.&nbsp; It has
+come out of the <a href="http://www.mozilla.org">Mozilla</a>  project, which
+maintains the <a href="http://www.mozilla.org/projects/xpcom/">main XPCOM
+project pages.</a>&nbsp; The Python XPCOM package is a set of Python bindings to
+XPCOM, allowing a Python programmer to both use and implement XPCOM
+interfaces.&nbsp; If you don't know what <a href="http://www.python.org">Python</a>
+is, then none of this probably interests you at all!</p>
+<p>This readme has links to the following information:</p>
+<ul>
+  <li><a href="doc/configure.html">Building, Configuring and
+   Testing the Python
+    XPCOM Package</a></li>
+  <li><a href="doc/tutorial.html">A tutorial for the Python XPCOM package</a></li>
+  <li>Some <a href="doc/advanced.html">advanced
+    topics and other miscellaneous information</a></li>
+  <li><a href="doc/architecture.html">Information on the architecture</a></li>
+  <li>A list of the <a href="#KnownBugs">known issues and bugs</a>, the <a href="#ReleaseHistory">release
+    history</a> and the <a href="doc/credits.html">PyXPCOM acknowledgements</a></li>
+</ul>
+<p>Note: <b>This package requires Python 1.6 or later</b>; we recommend using
+the latest
+official Python version.&nbsp; This package works
+very well with the latest <a href="http://www.ActiveState.com/Products/ActivePython">ActivePython</a>,
+and does not require any external modules or packages beyond what is provided in
+the core Python release for each platform.</p>
+<h2>About the Python XPCOM Package</h2>
+<p>The Python XPCOM Package was developed by <a href="http://www.ActiveState.com">ActiveState
+Tool Corporation</a>, and came out of their <a href="http://www.ActiveState.com/Products/Komodo">Komodo
+project</a>.&nbsp; The Python XPCOM package is released under the <a href="http://www.mozilla.org/MPL/">Mozilla
+Public License (MPL)</a></p>
+<p>Please see the <a href="doc/credits.html">credits file</a> for a list of
+contributors. </p>
+<h2><a name="KnownBugs">Known Bugs</a>/Issues</h2>
+<ul>
+  <li>No attempt is made to recurse sub-directories of the main
+&quot;components&quot; directory.&nbsp; This is because we may decide on some
+smart scheme for recursion (similar to Python packages), and don't want people
+to rely on simple recursive searches.</li>
+  <li>No unregistration support at all.&nbsp;The main Python Component Loader supports
+    unregistration, but the actual Python objects themselves do not support unregistration.&nbsp;It is unclear if the Component Loader
+    unregistration process needs to manually remove each component it is responsible
+for.</li>
+  <li>All Python-implemented components unconditionally support
+weak-references.&nbsp; There is no way to disable this feature for any or all
+components.&nbsp; It is unclear if there is a need to prevent this, but it is
+documented here just in case!</li>
+</ul>
+<h2><a name="ReleaseHistory">Release History</a></h2>
+<h3>Version 0.90 - January 2001</h3>
+<ul>
+  <li>First public release.</li>
+</ul>
+<h3>Version 0.91 - January 2001</h3>
+<ul>
+  <li>Fix a seg fault on Linux when PYTHONPATH is not set.</li>
+  <li>Changes to allow building with stand-alone XPCOM.</li>
+</ul>
+
+<h3>Version 0.92 - May 2001</h3>
+<p>Implement interface flattening.&nbsp; You should (almost) never need to use <i>QueryInterface()</i>!&nbsp;
+We are still 100% backwards compatible, so usage of QI still works - just is
+generally not necessary.</p>
+
+<h3>Version 0.93 - May 2002</h3>
+
+<p>Implement <i>nsIVariant</i> and all new string types.&nbsp; Complete move to
+autoconf build system.</p>
+
+</body>
+
+</html>
Index: trunk/src/libs/xpcom18a4/python/sample/vboxshell.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/sample/vboxshell.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/sample/vboxshell.py	(revision 11746)
@@ -0,0 +1,352 @@
+#!/usr/bin/python
+#
+####################################################################################
+# This program is a simple interactive shell for VirtualBox. You can query         #
+# information and issue commands from a simple command line.                       #
+#                                                                                  #
+# It also provides you with examples on how to use VirtualBox' Python API.         #
+# This shell is even somewhat documented and supports TAB-completion and history   #
+# if you have Python readline installed.                                           #
+#                                                                                  #
+#                                                Enjoy.                            #
+####################################################################################
+#
+# To make it work, the following variables have to be set.
+# Please note the trailing slash in VBOX_PROGRAM_PATH - it's a must.
+# 
+# This is the place where VirtualBox resides
+#  export VBOX_PROGRAM_PATH=/home/nike/work/ws/out/linux.amd64/debug/bin/
+# To allow Python find modules
+#  export PYTHONPATH=$VBOX_PROGRAM_PATH/sdk/bindings/xpcom/python:$VBOX_PROGRAM_PATH
+# To allow library resolution
+#  export LD_LIBRARY_PATH=$VBOX_PROGRAM_PATH
+# Additionally, on 64-bit Solaris, you need to use 64-bit Python from /usr/bin/amd64/python
+# and due to quirks in native modules loading of Python do the following:
+#   mkdir $VBOX_PROGRAM_PATH/64
+#   ln -s $VBOX_PROGRAM_PATH/VBoxPython.so $VBOX_PROGRAM_PATH/64/VBoxPython.so 
+#
+import traceback
+import sys
+import pdb
+
+g_hasreadline = 1
+try:
+    import readline
+    import rlcompleter
+except:
+    g_hasreadline = 0
+
+# this one has to be the first XPCOM related import
+import xpcom.vboxxpcom
+import xpcom
+import xpcom.components
+
+class LocalManager:
+    def getSessionObject(self, vb):
+        return xpcom.components.classes["@virtualbox.org/Session;1"].createInstance()
+
+if g_hasreadline:
+  class CompleterNG(rlcompleter.Completer):
+    def __init__(self, dic, ctx):
+        self.ctx = ctx
+        return rlcompleter.Completer.__init__(self,dic)
+
+    def complete(self, text, state):
+        """
+        taken from:
+        http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496812
+        """
+        if text == "":
+            return ['\t',None][state]
+        else:
+            return rlcompleter.Completer.complete(self,text,state)
+
+    def global_matches(self, text):
+        """
+        Compute matches when text is a simple name.
+        Return a list of all names currently defined
+        in self.namespace that match.
+        """
+        
+        matches = []
+        n = len(text)
+        
+        for list in [ self.namespace ]:
+            for word in list:
+                if word[:n] == text:
+                    matches.append(word)
+
+        for m in getMachines(self.ctx):
+            word = m.name
+            if word[:n] == text:
+                matches.append(word)
+
+        return matches
+
+
+def autoCompletion(commands, ctx):
+  if  not g_hasreadline:
+      return
+  
+  comps = {}
+  for (k,v) in commands.items():
+      comps[k] = None
+  completer = CompleterNG(comps, ctx)
+  readline.set_completer(completer.complete)
+  readline.parse_and_bind("tab: complete")
+
+g_verbose = True
+
+def split_no_quotes(s):
+   return s.split()
+   
+def startVm(mgr,vb,mach,type):
+    session = mgr.getSessionObject(vb)
+    uuid = mach.id
+    progress = vb.openRemoteSession(session, uuid, type, "")
+    progress.waitForCompletion(-1)
+    completed = progress.completed
+    rc = progress.resultCode
+    print "Completed:", completed, "rc:",rc
+    session.close()
+
+def getMachines(ctx):
+    return ctx['vb'].getMachines2()
+
+def asState(var):
+    if var:
+        return 'on'
+    else:
+        return 'off'
+
+def guestStats(ctx,guest):
+    stats = {
+        'Guest statistics for sample': xpcom.components.interfaces.GuestStatisticType.SampleNumber,
+        'CPU Load Idle': xpcom.components.interfaces.GuestStatisticType.CPULoad_Idle,
+        'CPU Load User': xpcom.components.interfaces.GuestStatisticType.CPULoad_User,
+        'CPU Load Kernel': xpcom.components.interfaces.GuestStatisticType.CPULoad_Kernel,
+        'Threads': xpcom.components.interfaces.GuestStatisticType.Threads,
+        'Processes': xpcom.components.interfaces.GuestStatisticType.Processes,
+        'Handles': xpcom.components.interfaces.GuestStatisticType.Handles,
+        }
+    for (k,v) in stats.items(): 
+        try:
+            val = guest.getStatistic(0, v)
+            print "'%s' = '%s'" %(k,str(v))
+        except:
+            print "Cannot get value for '%s'"  %(k)
+            pass
+
+def cmdExistingVm(ctx,mach,cmd):
+    mgr=ctx['mgr']
+    vb=ctx['vb']
+    session = mgr.getSessionObject(vb)
+    uuid = mach.id
+    try:
+        progress = vb.openExistingSession(session, uuid)
+    except Exception,e:
+        print "Session to '%s' not open: %s" %(mach.name,e)
+        if g_verbose:
+            traceback.print_exc()
+        return
+    if session.state != xpcom.components.interfaces.SessionState.Open:
+        print "Session to '%s' in wrong state: %s" %(mach.name, session.state)
+        return
+    console=session.console
+    ops={'pause' :     lambda: console.pause(),
+         'resume':     lambda: console.resume(),
+         'powerdown':  lambda: console.powerDown(),
+         'stats':      lambda: guestStats(ctx, console.guest)}
+    ops[cmd]()
+    session.close()
+
+# can cache known machines, if needed
+def machById(ctx,id):
+    mach = None
+    for m in getMachines(ctx):
+        if m.id == id or m.name == id:
+            mach = m
+            break
+    return mach
+
+def argsToMach(ctx,args):
+    if len(args) < 2:
+        print "usage: %s [vmname|uuid]" %(args[0])
+        return None
+    id = args[1]
+    return machById(ctx, id)
+
+def helpCmd(ctx, args):
+    if len(args) == 1:
+        print "Help page:"
+        for i in commands:
+            print "   ",i,":", commands[i][0] 
+    else:
+        c = commands.get(args[1], None)
+        if c == None:
+            print "Command '%s' not known" %(args[1])
+        else:
+            print "   ",args[1],":", c[0]
+    return 0
+
+def listCmd(ctx, args):
+    for m in getMachines(ctx):
+        print "Machine '%s' [%s], state=%s" %(m.name,m.id,m.sessionState)
+    return 0
+
+def infoCmd(ctx,args):
+    if (len(args) < 2):
+        print "usage: info [vmname|uuid]"
+        return 0
+    mach = argsToMach(ctx,args) 
+    if mach == None:
+        return 0
+    os = ctx['vb'].getGuestOSType(mach.OSTypeId)
+    print "  Name: ",mach.name
+    print "  ID: ",mach.id
+    print "  OS Type: ",os.description
+    print "  RAM:  %dM" %(mach.memorySize)
+    print "  VRAM:  %dM" %(mach.VRAMSize)
+    print "  Monitors:  %d" %(mach.MonitorCount)
+    print "  Clipboard mode:  %d" %(mach.clipboardMode)
+    print "  Machine status: " ,mach.sessionState
+    bios = mach.BIOSSettings
+    print "  BIOS ACPI: ",bios.ACPIEnabled
+    print "  PAE: ",mach.PAEEnabled
+    print "  Hardware virtualization: ",asState(mach.HWVirtExEnabled)
+    print "  Nested paging: ",asState(mach.HWVirtExNestedPagingEnabled)
+    print "  Last changed: ",mach.lastStateChange
+
+    return 0 
+
+def startCmd(ctx, args):
+    mach = argsToMach(ctx,args) 
+    if mach == None:
+        return 0
+    if len(args) > 2:
+        type = args[2]
+    else:
+        type = "gui"
+    startVm(ctx['mgr'], ctx['vb'], mach, type)
+    return 0
+
+def pauseCmd(ctx, args):
+    mach = argsToMach(ctx,args) 
+    if mach == None:
+        return 0
+    cmdExistingVm(ctx, mach, 'pause')
+    return 0
+
+def powerdownCmd(ctx, args):
+    mach = argsToMach(ctx,args) 
+    if mach == None:
+        return 0
+    cmdExistingVm(ctx, mach, 'powerdown')
+    return 0
+
+def resumeCmd(ctx, args):
+    mach = argsToMach(ctx,args) 
+    if mach == None:
+        return 0
+    cmdExistingVm(ctx, mach, 'resume')
+    return 0
+
+def statsCmd(ctx, args):
+    mach = argsToMach(ctx,args) 
+    if mach == None:
+        return 0
+    cmdExistingVm(ctx, mach, 'stats')
+    return 0
+
+def quitCmd(ctx, args):
+    return 1
+
+def aliasesCmd(ctx, args):
+    for (k,v) in aliases.items(): 
+        print "'%s' is an alias for '%s'" %(k,v)
+    return 0
+
+def verboseCmd(ctx, args):
+    global g_verbose
+    g_verbose = not g_verbose
+    return 0
+
+def hostCmd(ctx, args):
+   host = ctx['vb'].host
+   cnt = host.processorCount
+   print "Processor count:",cnt
+   for i in range(0,cnt):
+      print "Processor #%d speed: %dMHz" %(i,host.getProcessorSpeed(i))
+                
+   collector = ctx['vb'].performanceCollector
+  
+   (vals, names, objs, idxs, lens) = collector.queryMetricsData(["*"], [host])
+   for i in range(0,len(vals)):
+      print "for name:",names[i]," val:",vals[i]
+
+   return 0
+
+aliases = {'s':'start',  
+           'i':'info',
+           'l':'list',
+           'h':'help',
+           'a':'aliases',
+           'q':'quit', 'exit':'quit',
+           'v':'verbose'}
+
+commands = {'help':['Prints help information', helpCmd],
+            'start':['Start virtual machine by name or uuid', startCmd],
+            'pause':['Pause virtual machine', pauseCmd],
+            'resume':['Resume virtual machine', resumeCmd],
+            'stats':['Stats for virtual machine', statsCmd],
+            'powerdown':['Power down virtual machine', powerdownCmd],
+            'list':['Shows known virtual machines', listCmd],
+            'info':['Shows info on machine', infoCmd],
+            'aliases':['Shows aliases', aliasesCmd],
+            'verbose':['Toggle verbosity', verboseCmd],
+            'quit':['Exits', quitCmd],
+            'host':['Show host information', hostCmd]}
+
+def runCommand(ctx, cmd):
+    if len(cmd) == 0: return 0 
+    args = split_no_quotes(cmd)
+    c = args[0]
+    if aliases.get(c, None) != None:
+        c = aliases[c]
+    ci = commands.get(c,None)
+    if ci == None:
+        print "Unknown command: '%s', type 'help' for list of known commands" %(c)
+        return 0
+    return ci[1](ctx, args)
+
+def interpret():
+    vbox = None
+    try:
+        vbox = xpcom.components.classes["@virtualbox.org/VirtualBox;1"].createInstance()
+    except xpcom.Exception, e:
+        print "XPCOM exception: ",e
+        traceback.print_exc()
+        return
+    print "Running VirtualBox version %s" %(vbox.version)
+    mgr = LocalManager()
+    ctx = {'mgr':mgr, 'vb':vbox }
+
+    autoCompletion(commands, ctx)
+
+    while True:
+        try:
+            cmd = raw_input("vbox> ")
+            done = runCommand(ctx, cmd)
+            if done != 0: break
+        except KeyboardInterrupt:            
+            print '====== You can type quit or q to leave'
+            break
+        except EOFError:
+            break;
+        except Exception,e:
+            print e
+            if g_verbose:
+                traceback.print_exc()
+
+
+interpret()
Index: trunk/src/libs/xpcom18a4/python/server/.cvsignore
===================================================================
--- trunk/src/libs/xpcom18a4/python/server/.cvsignore	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/server/.cvsignore	(revision 11746)
@@ -0,0 +1,2 @@
+*.pyc
+*.pyo
Index: trunk/src/libs/xpcom18a4/python/server/__init__.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/server/__init__.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/server/__init__.py	(revision 11746)
@@ -0,0 +1,88 @@
+# ***** 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>
+#
+# 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 *****
+
+# The xpcom.server package.
+
+from policy import DefaultPolicy
+from xpcom import _xpcom
+
+# We define the concept of a single "tracer" object - similar to the single
+# Python "trace hook" for debugging.  Someone can set
+# xpcom.server.tracer to some class/function, and it will be used in place
+# of the real xpcom object.  Presumably this "trace" object will delegate
+# to the real object, but presumably also taking some other action, such
+# as calling a profiler or debugger.
+# tracer_unwrap is a function used to "unwrap" the tracer object.
+# If is expected that tracer_unwrap will be called with an object
+# previously returned by "tracer()".
+tracer = tracer_unwrap = None
+
+# Wrap an instance in an interface (via a policy)
+def WrapObject(ob, iid, policy = None, bWrapClient = 1):
+    """Called by the framework to attempt to wrap
+    an object in a policy.
+    If iid is None, it will use the first interface the object indicates it supports.
+    """
+    if policy is None:
+        policy = DefaultPolicy
+    if tracer is not None:
+        ob = tracer(ob)
+    return _xpcom.WrapObject(policy( ob, iid ), iid, bWrapClient)
+
+# Unwrap a Python object back into the Python object
+def UnwrapObject(ob):
+    if ob is None:
+        return None
+    ret = _xpcom.UnwrapObject(ob)._obj_
+    if tracer_unwrap is not None:
+        ret = tracer_unwrap(ret)
+    return ret
+
+# Create the main module for the Python loader.
+# This is a once only init process, and the returned object
+# if used to load all other Python components.
+
+# This means that we keep all factories, modules etc implemented in
+# Python!
+def NS_GetModule( serviceManager, nsIFile ):
+    import loader
+    iid = _xpcom.IID_nsIModule
+    return WrapObject(loader.MakePythonComponentLoaderModule(serviceManager, nsIFile), iid, bWrapClient = 0)
+
+def _shutdown():
+    from policy import _shutdown
+    _shutdown()
Index: trunk/src/libs/xpcom18a4/python/server/enumerator.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/server/enumerator.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/server/enumerator.py	(revision 11746)
@@ -0,0 +1,58 @@
+# ***** 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, 2001
+# 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 *****
+
+from xpcom import components
+
+# This class is created by Python components when it
+# needs to return an enumerator.
+# For example, a component may implement a function:
+#  nsISimpleEnumerator enumSomething();
+# This could could simply say:
+# return SimpleEnumerator([something1, something2, something3])
+class SimpleEnumerator:
+    _com_interfaces_ = [components.interfaces.nsISimpleEnumerator]
+
+    def __init__(self, data):
+        self._data = data
+        self._index = 0
+
+    def hasMoreElements(self):
+        return self._index < len(self._data)
+    
+    def getNext(self):
+        self._index = self._index + 1
+        return self._data[self._index-1]
Index: trunk/src/libs/xpcom18a4/python/server/factory.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/server/factory.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/server/factory.py	(revision 11746)
@@ -0,0 +1,68 @@
+# ***** 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, 2001
+# 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 *****
+
+# Class factory
+#
+# Hardly worth its own source file!
+import xpcom
+from xpcom import components, nsError, _xpcom, logger
+
+class Factory:
+    _com_interfaces_ = components.interfaces.nsIFactory
+    # This will only ever be constructed via other Python code,
+    # so we can have ctor args.
+    def __init__(self, klass):
+        self.klass = klass
+
+    def createInstance(self, outer, iid):
+        if outer is not None:
+            raise xpcom.ServerException(nsError.NS_ERROR_NO_AGGREGATION)
+
+        logger.debug("Python Factory creating %s", self.klass.__name__)
+        try:
+            return self.klass()
+        except:
+            # An exception here may not be obvious to the user - none
+            # of their code has been called yet.  It can be handy on
+            # failure to tell the user what class failed!
+            logger.error("Creation of class '%r' failed!\nException details follow\n",
+                           self.klass)
+            # The framework itself will also report the error.
+            raise
+
+    def lockServer(self, lock):
+        logger.debug("Python Factory LockServer called '%s'", lock)
Index: trunk/src/libs/xpcom18a4/python/server/loader.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/server/loader.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/server/loader.py	(revision 11746)
@@ -0,0 +1,225 @@
+# ***** 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>
+#
+# 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 *****
+
+import xpcom
+from xpcom import components, logger
+
+import module
+
+import glob, os, types
+
+from xpcom.client import Component
+
+# Until we get interface constants.
+When_Startup = 0
+When_Component = 1
+When_Timer = 2
+
+def _has_good_attr(object, attr):
+    # Actually allows "None" to be specified to disable inherited attributes.
+    return getattr(object, attr, None) is not None
+
+def FindCOMComponents(py_module):
+    # For now, just run over all classes looking for likely candidates.
+    comps = []
+    for name, object in py_module.__dict__.items():
+        if type(object)==types.ClassType and \
+           _has_good_attr(object, "_com_interfaces_") and \
+           _has_good_attr(object, "_reg_clsid_") and \
+           _has_good_attr(object, "_reg_contractid_"):
+            comps.append(object)
+    return comps
+
+def register_self(klass, compMgr, location, registryLocation, componentType):
+    pcl = PythonComponentLoader
+    from xpcom import _xpcom
+    svc = _xpcom.GetServiceManager().getServiceByContractID("@mozilla.org/categorymanager;1", components.interfaces.nsICategoryManager)
+    svc.addCategoryEntry("component-loader", pcl._reg_component_type_, pcl._reg_contractid_, 1, 1)
+
+class PythonComponentLoader:
+    _com_interfaces_ = components.interfaces.nsIComponentLoader
+    _reg_clsid_ = "{63B68B1E-3E62-45f0-98E3-5E0B5797970C}" # Never copy these!
+    _reg_contractid_ = "moz.pyloader.1"
+    _reg_desc_ = "Python component loader"
+    # Optional function which performs additional special registration
+    # Appears that no special unregistration is needed for ComponentLoaders, hence no unregister function.
+    _reg_registrar_ = (register_self,None)
+    # Custom attributes for ComponentLoader registration.
+    _reg_component_type_ = "script/python"
+
+    def __init__(self):
+        self.com_modules = {} # Keyed by module's FQN as obtained from nsIFile.path
+        self.moduleFactory = module.Module
+        self.num_modules_this_register = 0
+
+    def _getCOMModuleForLocation(self, componentFile):
+        fqn = componentFile.path
+        mod = self.com_modules.get(fqn)
+        if mod is not None:
+            return mod
+        import ihooks, sys
+        base_name = os.path.splitext(os.path.basename(fqn))[0]
+        loader = ihooks.ModuleLoader()
+
+        module_name_in_sys = "component:%s" % (base_name,)
+        stuff = loader.find_module(base_name, [componentFile.parent.path])
+        assert stuff is not None, "Couldnt find the module '%s'" % (base_name,)
+        py_mod = loader.load_module( module_name_in_sys, stuff )
+
+        # Make and remember the COM module.
+        comps = FindCOMComponents(py_mod)
+        mod = self.moduleFactory(comps)
+        
+        self.com_modules[fqn] = mod
+        return mod
+        
+    def getFactory(self, clsid, location, type):
+        # return the factory
+        assert type == self._reg_component_type_, "Being asked to create an object not of my type:%s" % (type,)
+        # FIXME: how to do this without obsolete component manager?
+        cmo = components.manager.queryInterface(components.interfaces.nsIComponentManagerObsolete)	
+        file_interface = cmo.specForRegistryLocation(location)
+        # delegate to the module.
+        m = self._getCOMModuleForLocation(file_interface)
+        return m.getClassObject(components.manager, clsid, components.interfaces.nsIFactory)
+
+    def init(self, comp_mgr, registry):
+        # void
+        self.comp_mgr = comp_mgr
+        logger.debug("Python component loader init() called")
+
+     # Called when a component of the appropriate type is registered,
+     # to give the component loader an opportunity to do things like
+     # annotate the registry and such.
+    def onRegister (self, clsid, type, className, proId, location, replace, persist):
+        logger.debug("Python component loader - onRegister() called")
+
+    def autoRegisterComponents (self, when, directory):
+        directory_path = directory.path
+        self.num_modules_this_register = 0
+        logger.debug("Auto-registering all Python components in '%s'", directory_path)
+
+        # ToDo - work out the right thing here
+        # eg - do we recurse?
+        # - do we support packages?
+        entries = directory.directoryEntries
+        while entries.HasMoreElements():
+            entry = entries.GetNext(components.interfaces.nsIFile)
+            if os.path.splitext(entry.path)[1]==".py":
+                try:
+                    self.autoRegisterComponent(when, entry)
+                # Handle some common user errors
+                except xpcom.COMException, details:
+                    from xpcom import nsError
+                    # If the interface name does not exist, suppress the traceback
+                    if details.errno==nsError.NS_ERROR_NO_INTERFACE:
+                        logger.error("Registration of '%s' failed\n %s",
+                                     entry.leafName, details.message)
+                    else:
+                        logger.exception("Registration of '%s' failed!", entry.leafName)
+                except SyntaxError, details:
+                    # Syntax error in source file - no useful traceback here either.
+                    logger.error("Registration of '%s' failed\n %s",
+                                 entry.leafName, details)
+                except:
+                    # All other exceptions get the full traceback.
+                    logger.exception("Registration of '%s' failed.", entry.leafName)
+
+    def autoRegisterComponent (self, when, componentFile):
+        # bool return
+        
+        # Check if we actually need to do anything
+        modtime = componentFile.lastModifiedTime
+        loader_mgr = components.manager.queryInterface(components.interfaces.nsIComponentLoaderManager)
+        if not loader_mgr.hasFileChanged(componentFile, None, modtime):
+            return 1
+
+        if self.num_modules_this_register == 0:
+            # New components may have just installed new Python
+            # modules into the main python directory (including new .pth files)
+            # So we ask Python to re-process our site directory.
+            # Note that the pyloader does the equivalent when loading.
+            try:
+                from xpcom import _xpcom
+                import site
+                NS_XPCOM_CURRENT_PROCESS_DIR="XCurProcD"
+                dirname = _xpcom.GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR)
+                dirname.append("python")
+                site.addsitedir(dirname.path)
+            except:
+                logger.exception("PyXPCOM loader failed to process site directory before component registration")
+
+        self.num_modules_this_register += 1
+
+        # auto-register via the module.
+        m = self._getCOMModuleForLocation(componentFile)
+        m.registerSelf(components.manager, componentFile, None, self._reg_component_type_)
+        loader_mgr = components.manager.queryInterface(components.interfaces.nsIComponentLoaderManager)
+        loader_mgr.saveFileInfo(componentFile, None, modtime)
+        return 1
+
+    def autoUnregisterComponent (self, when, componentFile):
+        # bool return
+        # auto-unregister via the module.
+        m = self._getCOMModuleForLocation(componentFile)
+        loader_mgr = components.manager.queryInterface(components.interfaces.nsIComponentLoaderManager)
+        try:
+            m.unregisterSelf(components.manager, componentFile)
+        finally:
+            loader_mgr.removeFileInfo(componentFile, None)
+        return 1
+
+    def registerDeferredComponents (self, when):
+        # bool return
+        logger.debug("Python component loader - registerDeferred() called")
+        return 0 # no more to register
+
+    def unloadAll (self, when):
+        # This is called at shutdown time - don't get too upset if an error
+        # results from logging due to the logfile being closed
+        try:
+            logger.debug("Python component loader being asked to unload all components!")
+        except:
+            # Evil blank except, but restricting to just catching IOError
+            # failure means custom logs could still screw us
+            pass
+        self.comp_mgr = None
+        self.com_modules = {}
+
+def MakePythonComponentLoaderModule(serviceManager, nsIFile):
+    import module
+    return module.Module( [PythonComponentLoader] )
Index: trunk/src/libs/xpcom18a4/python/server/module.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/server/module.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/server/module.py	(revision 11746)
@@ -0,0 +1,108 @@
+# ***** 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) 2000, 2001
+# ActiveState Tool Corp.  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 *****
+
+from xpcom import components
+from xpcom import ServerException, Exception
+from xpcom import nsError
+
+import factory
+
+import types
+import os
+
+class Module:
+    _com_interfaces_ = components.interfaces.nsIModule
+    def __init__(self, comps):
+        # Build a map of classes we can provide factories for.
+        c = self.components = {}
+        for klass in comps:
+            c[components.ID(klass._reg_clsid_)] = klass
+        self.klassFactory = factory.Factory
+
+    def getClassObject(self, compMgr, clsid, iid):
+        # Single retval result.
+        try:
+            klass = self.components[clsid]
+        except KeyError:
+            raise ServerException(nsError.NS_ERROR_FACTORY_NOT_REGISTERED)
+        
+        # We can ignore the IID - the auto-wrap process will automatically QI us.
+        return self.klassFactory(klass)
+
+    def registerSelf(self, compMgr, location, loaderStr, componentType):
+        # void function.
+        fname = os.path.basename(location.path)
+        for klass in self.components.values():
+            reg_contractid = klass._reg_contractid_
+            print "Registering '%s' (%s)" % (reg_contractid, fname)
+            reg_desc = getattr(klass, "_reg_desc_", reg_contractid)
+            compMgr = compMgr.queryInterface(components.interfaces.nsIComponentRegistrar)
+            compMgr.registerFactoryLocation(klass._reg_clsid_,
+                                              reg_desc,
+                                              reg_contractid,
+                                              location,
+                                              loaderStr,
+                                              componentType)
+
+            # See if this class nominates custom register_self
+            extra_func = getattr(klass, "_reg_registrar_", (None,None))[0]
+            if extra_func is not None:
+                extra_func(klass, compMgr, location, loaderStr, componentType)
+
+    def unregisterSelf(self, compMgr, location, loaderStr):
+        # void function.
+        for klass in self.components.values():
+            ok = 1
+            try:
+                compMgr.unregisterComponentSpec(klass._reg_clsid_, location)
+            except Exception:
+                ok = 0
+            # Give the class a bash even if we failed!
+            extra_func = getattr(klass, "_reg_registrar_", (None,None))[1]
+            if extra_func is not None:
+                try:
+                    extra_func(klass, compMgr, location, loaderStr)
+                except Exception:
+                    ok = 0
+            if ok:
+                print "Successfully unregistered", klass.__name__
+            else:
+                print "Unregistration of", klass.__name__, "failed. (probably just not already registered)"
+        
+    def canUnload(self, compMgr):
+        # single bool result
+        return 0 # we can never unload!
+
Index: trunk/src/libs/xpcom18a4/python/server/policy.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/server/policy.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/server/policy.py	(revision 11746)
@@ -0,0 +1,368 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# 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 *****
+
+from xpcom import xpcom_consts, _xpcom, client, nsError, logger
+from xpcom import ServerException, COMException
+import xpcom
+import xpcom.server
+import operator
+import types
+import logging
+
+
+IID_nsISupports = _xpcom.IID_nsISupports
+IID_nsIVariant = _xpcom.IID_nsIVariant
+XPT_MD_IS_GETTER = xpcom_consts.XPT_MD_IS_GETTER
+XPT_MD_IS_SETTER = xpcom_consts.XPT_MD_IS_SETTER
+
+VARIANT_INT_TYPES = xpcom_consts.VTYPE_INT8, xpcom_consts.VTYPE_INT16, xpcom_consts.VTYPE_INT32, \
+                    xpcom_consts.VTYPE_UINT8, xpcom_consts.VTYPE_UINT16, xpcom_consts.VTYPE_INT32
+VARIANT_LONG_TYPES = xpcom_consts.VTYPE_INT64, xpcom_consts.VTYPE_UINT64
+VARIANT_FLOAT_TYPES = xpcom_consts.VTYPE_FLOAT, xpcom_consts.VTYPE_DOUBLE
+VARIANT_STRING_TYPES = xpcom_consts.VTYPE_CHAR, xpcom_consts.VTYPE_CHAR_STR, xpcom_consts.VTYPE_STRING_SIZE_IS, \
+                       xpcom_consts.VTYPE_CSTRING
+VARIANT_UNICODE_TYPES = xpcom_consts.VTYPE_WCHAR, xpcom_consts.VTYPE_DOMSTRING, xpcom_consts.VTYPE_WSTRING_SIZE_IS, \
+                        xpcom_consts.VTYPE_ASTRING 
+
+_supports_primitives_map_ = {} # Filled on first use.
+
+_interface_sequence_types_ = types.TupleType, types.ListType
+_string_types_ = types.StringType, types.UnicodeType
+XPTI_GetInterfaceInfoManager = _xpcom.XPTI_GetInterfaceInfoManager
+
+def _GetNominatedInterfaces(obj):
+    ret = getattr(obj, "_com_interfaces_", None)
+    if ret is None: return None
+    # See if the user only gave one.
+    if type(ret) not in _interface_sequence_types_:
+        ret = [ret]
+    real_ret = []
+    # For each interface, walk to the root of the interface tree.
+    iim = XPTI_GetInterfaceInfoManager()
+    for interface in ret:
+        # Allow interface name or IID.
+        interface_info = None
+        if type(interface) in _string_types_:
+            try:
+                interface_info = iim.GetInfoForName(interface)
+            except COMException:
+                pass
+        if interface_info is None:
+            # Allow a real IID
+            interface_info = iim.GetInfoForIID(interface)
+        real_ret.append(interface_info.GetIID())
+        parent = interface_info.GetParent()
+        while parent is not None:
+            parent_iid = parent.GetIID()
+            if parent_iid == IID_nsISupports:
+                break
+            real_ret.append(parent_iid)
+            parent = parent.GetParent()
+    return real_ret
+
+##
+## ClassInfo support
+##
+## We cache class infos by class
+class_info_cache = {}
+
+def GetClassInfoForObject(ob):
+    if xpcom.server.tracer_unwrap is not None:
+        ob = xpcom.server.tracer_unwrap(ob)
+    klass = ob.__class__
+    ci = class_info_cache.get(klass)
+    if ci is None:
+        ci = DefaultClassInfo(klass)
+        ci = xpcom.server.WrapObject(ci, _xpcom.IID_nsIClassInfo, bWrapClient = 0)
+        class_info_cache[klass] = ci
+    return ci
+
+class DefaultClassInfo:
+    _com_interfaces_ = _xpcom.IID_nsIClassInfo
+    def __init__(self, klass):
+        self.klass = klass
+        self.contractID = getattr(klass, "_reg_contractid_", None)
+        self.classDescription = getattr(klass, "_reg_desc_", None)
+        self.classID = getattr(klass, "_reg_clsid_", None)
+        self.implementationLanguage = 3 # Python - avoid lookups just for this
+        self.flags = 0 # what to do here??
+        self.interfaces = None
+
+    def get_classID(self):
+        if self.classID is None:
+            raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED, "Class '%r' has no class ID" % (self.klass,))
+        return self.classID
+
+    def getInterfaces(self):
+        if self.interfaces is None:
+            self.interfaces = _GetNominatedInterfaces(self.klass)
+        return self.interfaces
+
+    def getHelperForLanguage(self, language):
+        return None # Not sure what to do here.
+
+class DefaultPolicy:
+    def __init__(self, instance, iid):
+        self._obj_ = instance
+        self._nominated_interfaces_ = ni = _GetNominatedInterfaces(instance)
+        self._iid_ = iid
+        if ni is None:
+            raise ValueError, "The object '%r' can not be used as a COM object" % (instance,)
+        # This is really only a check for the user
+        if __debug__:
+            if iid != IID_nsISupports and iid not in ni:
+                # The object may delegate QI.
+                delegate_qi = getattr(instance, "_query_interface_", None)
+                # Perform the actual QI and throw away the result - the _real_
+                # QI performed by the framework will set things right!
+                if delegate_qi is None or not delegate_qi(iid):
+                    raise ServerException(nsError.NS_ERROR_NO_INTERFACE)
+        # Stuff for the magic interface conversion.
+        self._interface_info_ = None
+        self._interface_iid_map_ = {} # Cache - Indexed by (method_index, param_index)
+
+    def _QueryInterface_(self, com_object, iid):
+        # Framework allows us to return a single boolean integer,
+        # or a COM object.
+        if iid in self._nominated_interfaces_:
+            # We return the underlying object re-wrapped
+            # in a new gateway - which is desirable, as one gateway should only support
+            # one interface (this wont affect the users of this policy - we can have as many
+            # gateways as we like pointing to the same Python objects - the users never
+            # see what object the call came in from.
+            # NOTE: We could have simply returned the instance and let the framework
+            # do the auto-wrap for us - but this way we prevent a round-trip back into Python
+            # code just for the autowrap.
+            return xpcom.server.WrapObject(self._obj_, iid, bWrapClient = 0)
+
+        # Always support nsIClassInfo 
+        if iid == _xpcom.IID_nsIClassInfo:
+            return GetClassInfoForObject(self._obj_)
+
+        # See if the instance has a QI
+        # use lower-case "_query_interface_" as win32com does, and it doesnt really matter.
+        delegate = getattr(self._obj_, "_query_interface_", None)
+        if delegate is not None:
+            # The COM object itself doesnt get passed to the child
+            # (again, as win32com doesnt).  It is rarely needed
+            # (in win32com, we dont even pass it to the policy, although we have identified
+            # one place where we should - for marshalling - so I figured I may as well pass it
+            # to the policy layer here, but no all the way down to the object.
+            return delegate(iid)
+        # Finally see if we are being queried for one of the "nsISupports primitives"
+        if not _supports_primitives_map_:
+            iim = _xpcom.XPTI_GetInterfaceInfoManager()
+            for (iid_name, attr, cvt) in _supports_primitives_data_:
+                special_iid = iim.GetInfoForName(iid_name).GetIID()
+                _supports_primitives_map_[special_iid] = (attr, cvt)
+        attr, cvt = _supports_primitives_map_.get(iid, (None,None))
+        if attr is not None and hasattr(self._obj_, attr):
+            return xpcom.server.WrapObject(SupportsPrimitive(iid, self._obj_, attr, cvt), iid, bWrapClient = 0)
+        # Out of clever things to try!
+        return None # We dont support this IID.
+
+    def _MakeInterfaceParam_(self, interface, iid, method_index, mi, param_index):
+        # Wrap a "raw" interface object in a nice object.  The result of this
+        # function will be passed to one of the gateway methods.
+        if iid is None:
+            # look up the interface info - this will be true for all xpcom called interfaces.
+            if self._interface_info_ is None:
+                import xpcom.xpt
+                self._interface_info_ = xpcom.xpt.Interface( self._iid_ )
+            iid = self._interface_iid_map_.get( (method_index, param_index))
+            if iid is None:
+                iid = self._interface_info_.GetIIDForParam(method_index, param_index)
+                self._interface_iid_map_[(method_index, param_index)] = iid
+        # handle nsIVariant
+        if iid == IID_nsIVariant:
+            interface = interface.QueryInterface(iid)
+            dt = interface.dataType
+            if dt in VARIANT_INT_TYPES:
+                return interface.getAsInt32()
+            if dt in VARIANT_LONG_TYPES:
+                return interface.getAsInt64()
+            if dt in VARIANT_FLOAT_TYPES:
+                return interface.getAsFloat()
+            if dt in VARIANT_STRING_TYPES:
+                return interface.getAsStringWithSize()
+            if dt in VARIANT_UNICODE_TYPES:
+                return interface.getAsWStringWithSize()
+            if dt == xpcom_consts.VTYPE_BOOL:
+                return interface.getAsBool()
+            if dt == xpcom_consts.VTYPE_INTERFACE:
+                return interface.getAsISupports()
+            if dt == xpcom_consts.VTYPE_INTERFACE_IS:
+                return interface.getAsInterface()
+            if dt == xpcom_consts.VTYPE_EMPTY or dt == xpcom_consts.VTYPE_VOID:
+                return None
+            if dt == xpcom_consts.VTYPE_ARRAY:
+                return interface.getAsArray()
+            if dt == xpcom_consts.VTYPE_EMPTY_ARRAY:
+                return []
+            if dt == xpcom_consts.VTYPE_ID:
+                return interface.getAsID()
+            # all else fails...
+            logger.warning("Warning: nsIVariant type %d not supported - returning a string", dt)
+            try:
+                return interface.getAsString()
+            except COMException:
+                logger.exception("Error: failed to get Variant as a string - returning variant object")
+                return interface
+            
+        return client.Component(interface, iid)
+    
+    def _CallMethod_(self, com_object, index, info, params):
+        #print "_CallMethod_", index, info, params
+        flags, name, param_descs, ret = info
+        assert ret[1][0] == xpcom_consts.TD_UINT32, "Expected an nsresult (%s)" % (ret,)
+        if XPT_MD_IS_GETTER(flags):
+            # Look for a function of that name
+            func = getattr(self._obj_, "get_" + name, None)
+            if func is None:
+                assert len(param_descs)==1 and len(params)==0, "Can only handle a single [out] arg for a default getter"
+                ret = getattr(self._obj_, name) # Let attribute error go here!
+            else:
+                ret = func(*params)
+            return 0, ret
+        elif XPT_MD_IS_SETTER(flags):
+            # Look for a function of that name
+            func = getattr(self._obj_, "set_" + name, None)
+            if func is None:
+                assert len(param_descs)==1 and len(params)==1, "Can only handle a single [in] arg for a default setter"
+                setattr(self._obj_, name, params[0]) # Let attribute error go here!
+            else:
+                func(*params)
+            return 0
+        else:
+            # A regular method.
+            func = getattr(self._obj_, name)
+            return 0, func(*params)
+
+    def _doHandleException(self, func_name, exc_info):
+        exc_val = exc_info[1]
+        is_server_exception = isinstance(exc_val, ServerException)
+        if is_server_exception:
+            # When a component raised an explicit COM exception, it is
+            # considered 'normal' - however, we still write a debug log
+            # record to help track these otherwise silent exceptions.
+
+            # Note that Python 2.3 does not allow an explicit exc_info tuple
+            # and passing 'True' will not work as there is no exception pending.
+            # Trick things!
+            if logger.isEnabledFor(logging.DEBUG):
+                try:
+                    raise exc_info[0], exc_info[1], exc_info[2]
+                except:
+                    logger.debug("'%s' raised COM Exception %s",
+                             func_name, exc_val, exc_info = 1)
+            return exc_val.errno
+        # Unhandled exception - always print a warning and the traceback.
+        # As above, trick the logging module to handle Python 2.3
+        try:
+            raise exc_info[0], exc_info[1], exc_info[2]
+        except:
+            logger.exception("Unhandled exception calling '%s'", func_name)
+        return nsError.NS_ERROR_FAILURE
+
+    # Called whenever an unhandled Python exception is detected as a result
+    # of _CallMethod_ - this exception may have been raised during the _CallMethod_
+    # invocation, or after its return, but when unpacking the results
+    # eg, type errors, such as a Python integer being used as a string "out" param.
+    def _CallMethodException_(self, com_object, index, info, params, exc_info):
+        # Later we may want to have some smart "am I debugging" flags?
+        # Or maybe just delegate to the actual object - it's probably got the best
+        # idea what to do with them!
+        flags, name, param_descs, ret = info
+        exc_typ, exc_val, exc_tb = exc_info
+        # use the xpt module to get a better repr for the method.
+        # But if we fail, ignore it!
+        try:
+            import xpcom.xpt
+            m = xpcom.xpt.Method(info, index, None)
+            func_repr = m.Describe().lstrip()
+        except COMException:
+            func_repr = "%s(%r)" % (name, param_descs)
+        except:
+            # any other errors are evil!?  Log it
+            self._doHandleException("<building method repr>", sys.exc_info())
+            # And fall through to logging the original error.
+        return self._doHandleException(func_repr, exc_info)
+
+    # Called whenever a gateway fails due to anything other than _CallMethod_.
+    # Really only used for the component loader etc objects, so most
+    # users should never see exceptions triggered here.
+    def _GatewayException_(self, name, exc_info):
+        return self._doHandleException(name, exc_info)
+
+_supports_primitives_data_ = [
+    ("nsISupportsCString", "__str__", str),
+    ("nsISupportsString", "__unicode__", unicode),
+    ("nsISupportsPRUint64", "__long__", long),
+    ("nsISupportsPRInt64", "__long__", long),
+    ("nsISupportsPRUint32", "__int__", int),
+    ("nsISupportsPRInt32", "__int__", int),
+    ("nsISupportsPRUint16", "__int__", int),
+    ("nsISupportsPRInt16", "__int__", int),
+    ("nsISupportsPRUint8", "__int__", int),
+    ("nsISupportsPRBool", "__nonzero__", operator.truth),
+    ("nsISupportsDouble", "__float__", float),
+    ("nsISupportsFloat", "__float__", float),
+]
+
+# Support for the nsISupports primitives:
+class SupportsPrimitive:
+    _com_interfaces_ = ["nsISupports"]
+    def __init__(self, iid, base_ob, attr_name, converter):
+        self.iid = iid
+        self.base_ob = base_ob
+        self.attr_name = attr_name
+        self.converter = converter
+    def _query_interface_(self, iid):
+        if iid == self.iid:
+            return 1
+        return None
+    def get_data(self):
+        method = getattr(self.base_ob, self.attr_name)
+        val = method()
+        return self.converter(val)
+    def set_data(self, val):
+        raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
+    def toString(self):
+        return str(self.get_data())
+
+def _shutdown():
+    class_info_cache.clear()
Index: trunk/src/libs/xpcom18a4/python/src/ErrorUtils.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/ErrorUtils.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/ErrorUtils.cpp	(revision 11746)
@@ -0,0 +1,373 @@
+/* ***** 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>
+#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!
+	PyObject *obMessage = PyString_FromString(pszMessageText);
+	if (obMessage) {
+		PyObject *repr = PyObject_Repr(obMessage);
+		if (repr) {
+			c += PyString_AsString(repr);
+			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];
+	// Use safer NS_ functions.
+	PR_vsnprintf(buff, sizeof(buff), fmt, argptr);
+
+	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) {
+		streamout += PyString_AsString(temp);
+		Py_DECREF(temp);
+	} else
+		streamout += "Can't 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'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);
+	}
+}
+
+void PyXPCOM_LogWarning(const char *fmt, ...)
+{
+	va_list marker;
+	va_start(marker, fmt);
+	VLogF(LOGGER_WARNING, fmt, 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);
+}
+#endif
+
+
+PyObject *PyXPCOM_BuildPyException(nsresult r)
+{
+	// Need the message etc.
+	PyObject *evalue = Py_BuildValue("i", r);
+	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;
+
+	/* 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\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!
+	}
+}
Index: trunk/src/libs/xpcom18a4/python/src/PyGBase.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyGBase.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyGBase.cpp	(revision 11746)
@@ -0,0 +1,840 @@
+/* ***** 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 = "_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
+		szRepr = PyString_AsString(r);
+	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 ? m_pPyObject->ob_type->tp_name : "<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 && PyInstance_Check(ob), "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 {
+		iid_check = NS_GET_IID(nsISupports);
+		pis->QueryInterface(iid_check, getter_AddRefs(piswrap));
+	}
+
+	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, 
+	                               "_MakeInterfaceParam_",
+				       "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, "_QueryInterface_",
+		                                                    "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", result->ob_type->tp_name);
+				// 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, 
+	                                       "_GatewayException_",
+					       "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", err_result->ob_type->tp_name);
+		}
+		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);
+}
Index: trunk/src/libs/xpcom18a4/python/src/PyGInputStream.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyGInputStream.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyGInputStream.cpp	(revision 11746)
@@ -0,0 +1,156 @@
+/* ***** 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)) {
+#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 /* VBOX */
+		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", ret->ob_type->tp_name);
+			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;
+		}
+	}
+	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;
+}
Index: trunk/src/libs/xpcom18a4/python/src/PyGModule.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyGModule.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyGModule.cpp	(revision 11746)
@@ -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);
+}
Index: trunk/src/libs/xpcom18a4/python/src/PyGStub.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyGStub.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyGStub.cpp	(revision 11746)
@@ -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, 
+	                                       "_CallMethod_",
+					       "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, 
+	                                       "_CallMethodException_",
+					       "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", err_result->ob_type->tp_name);
+		}
+		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;
+}
Index: trunk/src/libs/xpcom18a4/python/src/PyGWeakReference.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyGWeakReference.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyGWeakReference.cpp	(revision 11746)
@@ -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;
+}
Index: trunk/src/libs/xpcom18a4/python/src/PyIClassInfo.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyIClassInfo.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyIClassInfo.cpp	(revision 11746)
@@ -0,0 +1,177 @@
+/* ***** 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)
+		return PyString_FromString(v);
+	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}
+};
Index: trunk/src/libs/xpcom18a4/python/src/PyIComponentManager.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyIComponentManager.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyIComponentManager.cpp	(revision 11746)
@@ -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}
+};
Index: trunk/src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp	(revision 11746)
@@ -0,0 +1,198 @@
+/* ***** 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);
+
+	PyObject *ob_pid = PyString_FromString(ret_pid);
+	PyObject *ob_class = PyString_FromString(ret_class);
+	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}
+};
Index: trunk/src/libs/xpcom18a4/python/src/PyIEnumerator.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyIEnumerator.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyIEnumerator.cpp	(revision 11746)
@@ -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}
+};
Index: trunk/src/libs/xpcom18a4/python/src/PyIID.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyIID.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyIID.cpp	(revision 11746)
@@ -0,0 +1,238 @@
+/* ***** 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 (PyBuffer_Check(obBuf)) {
+			PyBufferProcs *pb = NULL;
+			pb = obBuf->ob_type->tp_as_buffer;
+			void *buf = NULL;
+			int size = (*pb->bf_getreadbuffer)(obBuf, 0, &buf);
+			if (size != sizeof(nsIID) || buf==NULL) {
+				PyErr_Format(PyExc_ValueError, "A buffer object to be converted to an IID must be exactly %d bytes long", sizeof(nsIID));
+				return NULL;
+			}
+			nsIID iid;
+			unsigned char *ptr = (unsigned char *)buf;
+			iid.m0 = XPT_SWAB32(*((PRUint32 *)ptr));
+			ptr = ((unsigned char *)buf) + offsetof(nsIID, m1);
+			iid.m1 = XPT_SWAB16(*((PRUint16 *)ptr));
+			ptr = ((unsigned char *)buf) + offsetof(nsIID, m2);
+			iid.m2 = XPT_SWAB16(*((PRUint16 *)ptr));
+			ptr = ((unsigned char *)buf) + offsetof(nsIID, m3);
+			for (int i=0;i<8;i++) {
+				iid.m3[i] = *((PRUint8 *)ptr);
+				ptr += sizeof(PRUint8);
+			}
+			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 (PyString_Check(ob)) {
+		ok = iid.Parse(PyString_AsString(ob));
+		if (!ok) {
+			PyXPCOM_BuildPyException(NS_ERROR_ILLEGAL_VALUE);
+			return PR_FALSE;
+		}
+	} else if (ob->ob_type == &type) {
+		iid = ((Py_nsIID *)ob)->m_iid;
+	} else if (PyInstance_Check(ob)) {
+		// 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;
+		}
+		if (use_ob->ob_type != &type) {
+			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", ob->ob_type->tp_name);
+		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.
+PyTypeObject Py_nsIID::type =
+{
+	PyObject_HEAD_INIT(&PyType_Type)
+	0,
+	"IID",
+	sizeof(Py_nsIID),
+	0,
+	PyTypeMethod_dealloc,                           /* tp_dealloc */
+	0,                                              /* tp_print */
+	PyTypeMethod_getattr,                           /* tp_getattr */
+	0,                                              /* tp_setattr */
+	PyTypeMethod_compare,                           /* tp_compare */
+	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 */
+};
+
+Py_nsIID::Py_nsIID(const nsIID &riid)
+{
+	ob_type = &type;
+	_Py_NewReference(this);
+	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) {
+			ret = PyString_FromString(iid_repr);
+			nsMemory::Free(iid_repr);
+		} else
+			ret = PyString_FromString("<cant get IID info!>");
+		return ret;
+	}
+	return PyErr_Format(PyExc_AttributeError, "IID objects have no attribute '%s'", name);
+}
+
+/* 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);
+}
+
+/* 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();
+	sprintf(buf, "_xpcom.IID('%s')", sziid);
+	nsMemory::Free(sziid);
+	return PyString_FromString(buf);
+}
+
+/* static */ PyObject *
+Py_nsIID::PyTypeMethod_str(PyObject *self)
+{
+	Py_nsIID *s_iid = (Py_nsIID *)self;
+	char *sziid = s_iid->m_iid.ToString();
+	PyObject *ret = PyString_FromString(sziid);
+	nsMemory::Free(sziid);
+	return ret;
+}
+
+/* static */long
+Py_nsIID::PyTypeMethod_hash(PyObject *self)
+{
+	const nsIID &iid = ((Py_nsIID *)self)->m_iid;
+
+	long ret = iid.m0 + iid.m1 + iid.m2;
+	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;
+}
Index: trunk/src/libs/xpcom18a4/python/src/PyIInputStream.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyIInputStream.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyIInputStream.cpp	(revision 11746)
@@ -0,0 +1,182 @@
+/* ***** 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.
+		return PyBuffer_New(0);
+	}
+	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) ) {
+		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
+		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}
+};
Index: trunk/src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp	(revision 11746)
@@ -0,0 +1,427 @@
+/* ***** 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);
+	PyObject *ret = PyString_FromString(name);
+	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;
+
+*/
Index: trunk/src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp	(revision 11746)
@@ -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 <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);
+
+	PyObject *ret = PyString_FromString(ret_name);
+	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}
+};
Index: trunk/src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp	(revision 11746)
@@ -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}
+};
Index: trunk/src/libs/xpcom18a4/python/src/PyISupports.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyISupports.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyISupports.cpp	(revision 11746)
@@ -0,0 +1,464 @@
+/* ***** 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!!!
+
+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;
+}
+
+Py_nsISupports::Py_nsISupports(nsISupports *punk, const nsIID &iid, PyTypeObject *this_type)
+{
+	ob_type = this_type;
+	m_obj = punk;
+	m_iid = iid;
+	// refcnt of object managed by caller.
+	PR_AtomicIncrement(&cInterfaces);
+	PyXPCOM_DLLAddRef();
+	_Py_NewReference(this);
+}
+
+Py_nsISupports::~Py_nsISupports()
+{
+	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;
+	}
+	PyXPCOM_TypeObject *this_type = (PyXPCOM_TypeObject *)ob_type;
+	return Py_FindMethodInChain(&this_type->chain, this, (char *)name);
+}
+
+/* virtual */ int
+Py_nsISupports::setattr(const char *name, PyObject *v)
+{
+	char buf[128];
+	sprintf(buf, "%s has read-only attributes", ob_type->tp_name );
+	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", ob->ob_type->tp_name);
+		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 (PyInstance_Check(ob)) {
+			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 (PyInstance_Check(ob)) {
+		// 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
+Py_nsISupports::RegisterInterface( const nsIID &iid, PyTypeObject *t)
+{
+	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;
+		pis->QueryInterface(riid, (void **)&queryResult);
+		NS_ASSERTION(queryResult == pis, "QueryInterface needed");
+		NS_IF_RELEASE(queryResult);
+#endif
+	}
+
+	PyTypeObject *createType = NULL;
+	// 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)
+			createType = (PyTypeObject *)PyDict_GetItem(mapIIDToType, obiid);
+		Py_DECREF(obiid);
+	}
+	if (createType==NULL)
+		createType = Py_nsISupports::type;
+	// 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;
+	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);
+}
+
+
+// @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."},
+	{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;
Index: trunk/src/libs/xpcom18a4/python/src/PyIVariant.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyIVariant.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyIVariant.cpp	(revision 11746)
@@ -0,0 +1,219 @@
+/* ***** 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) {
+	return PyString_FromStringAndSize(&c, 1);
+}
+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)
+
+GET_ALLOCATED(char *, GetAsString, PyString_FromString, nsMemory::Free)
+GET_ALLOCATED(PRUnichar *, GetAsWString, MyUnicode, nsMemory::Free)
+GET_ALLOCATED_SIZE(char *, GetAsStringWithSize, PyString_FromStringAndSize, nsMemory::Free)
+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);
+}
Index: trunk/src/libs/xpcom18a4/python/src/PyXPCOM.h
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyXPCOM.h	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyXPCOM.h	(revision 11746)
@@ -0,0 +1,833 @@
+/* ***** 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 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
+
+#include <Python.h>
+
+#ifdef SOLARIS_WAS_DEFINED
+#define SOLARIS
+#undef SOLARIS_WAS_DEFINED
+#endif
+
+#ifdef VBOX_PYXPCOM
+#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
+
+#else
+
+#include <Python.h>
+
+#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
+
+#endif
+
+#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;
+
+/*************************************************************************
+**************************************************************************
+
+ 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);
+
+// 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.
+
+class PYXPCOM_EXPORT PyXPCOM_TypeObject : public PyTypeObject {
+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 long Py_hash(PyObject *self);
+};
+
+//////////////////////////////////////////////////////////////////////////
+// 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;
+
+	// 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);
+	static void RegisterInterface( const nsIID &iid, PyTypeObject *t);
+	static void InitType();
+
+	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, 
+			    PyTypeObject *type);
+
+	// Make a default wrapper for an ISupports (which is an
+	// xpcom.client.Component instance)
+	static PyObject *MakeDefaultWrapper(PyObject *pyis, const nsIID &iid);
+
+};
+
+// 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 && 
+		       ob->ob_type== &type && 
+		       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);
+	static int PyTypeMethod_compare(PyObject *self, PyObject *ob);
+	static PyObject *PyTypeMethod_repr(PyObject *self);
+	static long PyTypeMethod_hash(PyObject *self);
+	static PyObject *PyTypeMethod_str(PyObject *self);
+	static void PyTypeMethod_dealloc(PyObject *self);
+	static NS_EXPORT_STATIC_MEMBER_(PyTypeObject) type;
+	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);
+
+
+// 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.
+		if (PyThreadState_Get()->gilstate_counter==1) {
+			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__
Index: trunk/src/libs/xpcom18a4/python/src/PyXPCOM_std.h
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/PyXPCOM_std.h	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/PyXPCOM_std.h	(revision 11746)
@@ -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"
Index: trunk/src/libs/xpcom18a4/python/src/Pyxpt_info.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/Pyxpt_info.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/Pyxpt_info.cpp	(revision 11746)
@@ -0,0 +1,185 @@
+/* ***** 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:
+			v = PyString_FromStringAndSize(&c->value.ch, 1);
+			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:
+			v = PyString_FromString(c->value.str);
+			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:
+			v = PyString_FromString("Unknown type code!!");
+			break;
+
+	}
+	PyObject *ret = Py_BuildValue("sbO", c->name, ob_type, v);
+	Py_DECREF(ob_type);
+	Py_DECREF(v);
+	return ret;
+}
Index: trunk/src/libs/xpcom18a4/python/src/TypeObject.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/TypeObject.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/TypeObject.cpp	(revision 11746)
@@ -0,0 +1,239 @@
+/* ***** 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>
+
+
+static PyTypeObject PyInterfaceType_Type = {
+	PyObject_HEAD_INIT(&PyType_Type)
+	0,			/* Number of items for varobject */
+	"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.",
+};
+
+/*static*/ PRBool
+PyXPCOM_TypeObject::IsType(PyTypeObject *t)
+{
+	return t->ob_type == &PyInterfaceType_Type;
+}
+
+////////////////////////////////////////////////////////////////////
+//
+// 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;
+}
+
+// @pymethod int|Py_nsISupports|__hash__|Implement a hash-code for the XPCOM object using XPCOM identity rules.
+/*static*/long PyXPCOM_TypeObject::Py_hash(PyObject *self)
+{
+	// We always return the value of the nsISupports *.
+	nsISupports *pUnkThis;
+	if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE))
+		return -1;
+	long ret = _Py_HashPointer(pUnkThis);
+	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;
+	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];
+	sprintf(buf, "<XPCOM object (%s) at 0x%p/0x%p>",
+	        iid_repr, (void *)self, (void *)pis->m_obj.get());
+	nsMemory::Free(iid_repr);
+	return PyString_FromString(buf);
+}
+
+/*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
+		ret = PyString_FromString(val);
+	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)
+{
+	static const PyTypeObject type_template = {
+		PyObject_HEAD_INIT(&PyInterfaceType_Type)
+		0,                                           /*ob_size*/
+		"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 */
+		Py_cmp,                                      /* tp_compare */
+		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 */
+		0,                                           /* 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;
+
+	chain.methods = methodList;
+	chain.link = pBase ? &pBase->chain : NULL;
+
+	baseType = pBase;
+	ctor = thector;
+
+	// cast away const, as Python doesnt use it.
+	tp_name = (char *)name;
+	tp_basicsize = typeSize;
+}
+
+PyXPCOM_TypeObject::~PyXPCOM_TypeObject()
+{
+}
Index: trunk/src/libs/xpcom18a4/python/src/VariantUtils.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/VariantUtils.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/VariantUtils.cpp	(revision 11746)
@@ -0,0 +1,2786 @@
+/* ***** 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;
+	PRUnichar *dest;
+
+	s = PyUnicode_AsUTF16String(obj);
+	if (!s)
+		return -1;
+	size = (PyString_GET_SIZE(s) - 2) / sizeof(PRUnichar);
+	dest = (PRUnichar *)nsMemory::Alloc(sizeof(PRUnichar) * (size + 1));
+	if (!dest) {
+		PyErr_NoMemory();
+		Py_DECREF(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.
+	memcpy(dest, PyString_AS_STRING(s) + 2, 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 {
+			ret = PyString_FromStringAndSize(NULL, s.Length());
+			if (!ret)
+				return NULL;
+			// Need "CopyAsciiTo"!?
+			nsACString::const_iterator fromBegin, fromEnd;
+			char* dest = PyString_AS_STRING(ret);
+			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 (!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;
+	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 ( array_type == nsXPTType::T_U8 && 
+		(PyString_Check(sequence_ob) || PyUnicode_Check(sequence_ob))) {
+
+		PRBool release_seq;
+		if (PyUnicode_Check(sequence_ob)) {
+			release_seq = PR_TRUE;
+			sequence_ob = PyObject_Str(sequence_ob);
+		} else
+			release_seq = PR_FALSE;
+		if (!sequence_ob) // presumably a memory error, or Unicode encoding error.
+			return PR_FALSE;
+		memcpy(pthis, PyString_AS_STRING(sequence_ob), sequence_size);
+		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 (!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) );
+				break;
+
+			  case nsXPTType::T_WCHAR:
+				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!");
+				// Lossy!
+				FILL_SIMPLE_POINTER( PRUnichar, *PyUnicode_AS_UNICODE(val_use) );
+				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 (!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);
+
+				*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 (!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!");
+				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)
+		return PyString_FromStringAndSize( (char *)array_ptr, sequence_size );
+
+	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
+					val = PyString_FromString(*pp);
+				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);
+				val = PyString_FromString(buf);
+				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 (PyString_Check(ob))
+		return nsIDataType::VTYPE_STRING_SIZE_IS;
+	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:
+			nr = v->SetAsStringWithSize(PyString_Size(ob), PyString_AsString(ob));
+			break;
+		case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+			if (PyUnicode_GetSize(ob) == 0) {
+				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", ob->ob_type->tp_name);
+					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", ob->ob_type->tp_name);
+			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", ob->ob_type->tp_name);
+			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_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) {
+		PyErr_Format(PyExc_ValueError, "The type descriptions indicate %d args are needed, but %d were provided",
+			total_params_needed, PySequence_Length(m_pyparams));
+		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]));
+
+	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 (!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);
+			break;
+			}
+
+		  case nsXPTType::T_WCHAR: {
+			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), "PyUnicode_FromObject didnt return a unicode object!");
+			if (PyUnicode_GetSize(val_use) != 1) {
+				PyErr_SetString(PyExc_ValueError, "Must specify a one character string for a character");
+				BREAK_FALSE;
+			}
+			// Lossy!
+			ns_v.val.wc = *PyUnicode_AS_UNICODE(val_use);
+			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 {
+				// strings are assumed to already be UTF8 encoded.
+				if (PyString_Check(val)) {
+					val_use = val;
+					Py_INCREF(val);
+				// Unicode objects are encoded by us.
+				} else if (PyUnicode_Check(val)) {
+					if (bIsUTF8)
+						val_use = PyUnicode_AsUTF8String(val);
+					else
+						val_use = PyObject_Str(val);
+				} else {
+					PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be string or Unicode objects");
+					BREAK_FALSE;
+				}
+				if (!val_use)
+					BREAK_FALSE;
+				ns_v.val.p = new nsCString(PyString_AS_STRING(val_use), 
+				                           PyString_GET_SIZE(val_use));
+			}
+
+			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 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 = 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);
+			ns_v.val.p = this_buffer_pointer;
+			break;
+			}
+
+		  case nsXPTType::T_WCHAR_STR: {
+			if (val==Py_None) {
+				ns_v.val.p = nsnull;
+				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 = PyUnicode_FromObject(val))==NULL)
+				BREAK_FALSE;
+			NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+			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 (!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);
+			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 (!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!");
+			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:
+		ret = PyString_FromStringAndSize( ((char *)ns_v.ptr), 1 );
+		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
+			ret = PyString_FromString( *((char **)ns_v.ptr) );
+		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);
+			ret = PyString_FromStringAndSize( *((char **)ns_v.ptr), string_size );
+		}
+		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);
+		ret = PyString_FromStringAndSize(&temp, 1);
+		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
+			ret = PyString_FromString(t);
+		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
+			ret = PyString_FromStringAndSize(t, string_size);
+		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);
+		ret = PyString_FromString(buf);
+		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 (!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) );
+		break;
+
+	  case nsXPTType::T_WCHAR:
+		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!");
+		// Lossy!
+		FILL_SIMPLE_POINTER( PRUnichar, *PyUnicode_AS_UNICODE(val_use) );
+		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 (!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_Size(val_use));
+		}
+		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 (PyString_Check(val)) {
+				val_use = val;
+				Py_INCREF(val);
+			} else if (PyUnicode_Check(val)) {
+				val_use = PyUnicode_AsUTF8String(val);
+			} else {
+				PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be string or Unicode objects");
+				BREAK_FALSE;
+			}
+			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_Size(val_use));
+		}
+		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 (!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);
+
+		*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 (!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!");
+		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;
+		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 (!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);
+		}
+		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 (!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!");
+			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'", val->ob_type->tp_name);
+				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) ||
+		     PyString_Check(user_result) ||
+		     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;
+}
Index: trunk/src/libs/xpcom18a4/python/src/dllmain.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/dllmain.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/dllmain.cpp	(revision 11746)
@@ -0,0 +1,348 @@
+/* ***** 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("argv")==NULL) {
+				PyObject *path = PyList_New(0);
+				PyObject *str = PyString_FromString("");
+				PyList_Append(path, str);
+				PySys_SetObject("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;
+}
+
Index: trunk/src/libs/xpcom18a4/python/src/loader/pyloader.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/loader/pyloader.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/loader/pyloader.cpp	(revision 11746)
@@ -0,0 +1,433 @@
+/* ***** 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);
+}
+/*** - 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);
+}
+#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;
+}
Index: trunk/src/libs/xpcom18a4/python/src/module/.deps/_xpcom.pp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/module/.deps/_xpcom.pp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/module/.deps/_xpcom.pp	(revision 11746)
@@ -0,0 +1,266 @@
+_xpcom.o: _xpcom.cpp ../../../../../config/gcc_hidden.h \
+  ../../../../../mozilla-config.h \
+  ../../../../../dist/include/pyxpcom/PyXPCOM.h \
+  ../../../../../dist/include/xpcom/nsIAllocator.h \
+  ../../../../../dist/include/xpcom/nsMemory.h \
+  ../../../../../dist/include/xpcom/nsXPCOM.h \
+  ../../../../../dist/include/xpcom/nscore.h \
+  ../../../../../dist/include/xpcom/xpcom-config.h \
+  ../../../../../dist/include/nspr/prtypes.h \
+  ../../../../../dist/include/nspr/prcpucfg.h \
+  ../../../../../dist/include/system_wrappers/stddef.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stddef.h \
+  ../../../../../dist/include/nspr/obsolete/protypes.h \
+  ../../../../../dist/include/system_wrappers/sys/types.h \
+  /usr/include/sys/types.h \
+  ../../../../../dist/include/system_wrappers/features.h \
+  /usr/include/features.h \
+  ../../../../../dist/include/system_wrappers/sys/cdefs.h \
+  /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+  /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+  /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+  ../../../../../dist/include/system_wrappers/time.h /usr/include/time.h \
+  ../../../../../dist/include/system_wrappers/endian.h \
+  /usr/include/endian.h /usr/include/bits/endian.h \
+  ../../../../../dist/include/system_wrappers/sys/select.h \
+  /usr/include/sys/select.h /usr/include/bits/select.h \
+  /usr/include/bits/sigset.h /usr/include/bits/time.h \
+  /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+  ../../../../../dist/include/xpcom/nsError.h \
+  ../../../../../dist/include/xpcom/nsXPCOMCID.h \
+  ../../../../../dist/include/xpcom/nsIMemory.h \
+  ../../../../../dist/include/xpcom/nsISupports.h \
+  ../../../../../dist/include/xpcom/nsrootidl.h \
+  ../../../../../dist/include/nspr/prtime.h \
+  ../../../../../dist/include/nspr/prlong.h \
+  ../../../../../dist/include/nspr/prtypes.h \
+  ../../../../../dist/include/xpcom/nsISupportsBase.h \
+  ../../../../../dist/include/xpcom/nsID.h \
+  ../../../../../dist/include/system_wrappers/string.h \
+  /usr/include/string.h /usr/include/xlocale.h \
+  ../../../../../dist/include/xpcom/nsISupportsUtils.h \
+  ../../../../../dist/include/xpcom/nsDebug.h \
+  ../../../../../dist/include/xpcom/nsISupportsImpl.h \
+  ../../../../../dist/include/nspr/prthread.h \
+  ../../../../../dist/include/nspr/prinrval.h \
+  ../../../../../dist/include/nspr/pratom.h \
+  ../../../../../dist/include/nspr/prlock.h \
+  ../../../../../dist/include/xpcom/nsTraceRefcnt.h \
+  ../../../../../dist/include/xpcom/nsIClassInfo.h \
+  ../../../../../dist/include/xpcom/nsIProgrammingLanguage.h \
+  ../../../../../dist/include/xpcom/nsIWeakReference.h \
+  ../../../../../dist/include/xpcom/nsIWeakReferenceUtils.h \
+  ../../../../../dist/include/xpcom/nsCOMPtr.h \
+  ../../../../../dist/include/xpcom/nsIInterfaceInfoManager.h \
+  ../../../../../dist/include/xpcom/nsIInterfaceInfo.h \
+  ../../../../../dist/include/xpcom/nsIEnumerator.h \
+  ../../../../../dist/include/xpcom/nsISimpleEnumerator.h \
+  ../../../../../dist/include/xpcom/nsIClassInfo.h \
+  ../../../../../dist/include/xpcom/nsIComponentManager.h \
+  ../../../../../dist/include/xpcom/nsComponentManagerUtils.h \
+  ../../../../../dist/include/xpcom/nsIFactory.h \
+  ../../../../../dist/include/xpcom/nsIComponentManagerObsolete.h \
+  ../../../../../dist/include/xpcom/nsIServiceManager.h \
+  ../../../../../dist/include/xpcom/nsServiceManagerUtils.h \
+  ../../../../../dist/include/xpcom/nsIServiceManager.h \
+  ../../../../../dist/include/xpcom/nsIServiceManagerObsolete.h \
+  ../../../../../dist/include/xpcom/nsIComponentManager.h \
+  ../../../../../dist/include/xpcom/nsIInputStream.h \
+  ../../../../../dist/include/xpcom/nsIVariant.h \
+  ../../../../../dist/include/xpcom/nsIModule.h \
+  ../../../../../dist/include/string/nsXPIDLString.h \
+  ../../../../../dist/include/string/nsString.h \
+  ../../../../../dist/include/string/nsSubstring.h \
+  ../../../../../dist/include/string/nsAString.h \
+  ../../../../../dist/include/string/nsStringFwd.h \
+  ../../../../../dist/include/string/nsStringIterator.h \
+  ../../../../../dist/include/string/nsCharTraits.h \
+  ../../../../../dist/include/system_wrappers/ctype.h \
+  /usr/include/ctype.h ../../../../../dist/include/xpcom/nsDebug.h \
+  ../../../../../dist/include/string/nsAlgorithm.h \
+  ../../../../../dist/include/string/nsObsoleteAString.h \
+  ../../../../../dist/include/string/string-template-def-unichar.h \
+  ../../../../../dist/include/string/nsTObsoleteAString.h \
+  ../../../../../dist/include/string/string-template-undef.h \
+  ../../../../../dist/include/string/string-template-def-char.h \
+  ../../../../../dist/include/string/nsTAString.h \
+  ../../../../../dist/include/string/nsSubstringTuple.h \
+  ../../../../../dist/include/string/nsTSubstringTuple.h \
+  ../../../../../dist/include/string/nsTSubstring.h \
+  ../../../../../dist/include/string/nsDependentSubstring.h \
+  ../../../../../dist/include/string/nsTDependentSubstring.h \
+  ../../../../../dist/include/string/nsReadableUtils.h \
+  ../../../../../dist/include/system_wrappers/new \
+  /usr/include/c++/4.2/new /usr/include/c++/4.2/cstddef \
+  /usr/include/c++/4.2/x86_64-linux-gnu/bits/c++config.h \
+  /usr/include/c++/4.2/x86_64-linux-gnu/bits/os_defines.h \
+  /usr/include/c++/4.2/x86_64-linux-gnu/bits/cpu_defines.h \
+  /usr/include/c++/4.2/exception \
+  ../../../../../dist/include/string/nsTString.h \
+  ../../../../../dist/include/string/nsDependentString.h \
+  ../../../../../dist/include/string/nsTDependentString.h \
+  ../../../../../dist/include/string/nsLiteralString.h \
+  ../../../../../dist/include/string/nsPromiseFlatString.h \
+  ../../../../../dist/include/string/nsTPromiseFlatString.h \
+  ../../../../../dist/include/xpcom/nsMemory.h \
+  ../../../../../dist/include/system_wrappers/stdio.h \
+  /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
+  ../../../../../dist/include/system_wrappers/wchar.h \
+  /usr/include/wchar.h \
+  ../../../../../dist/include/system_wrappers/stdarg.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stdarg.h \
+  /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+  ../../../../../dist/include/nspr/plhash.h \
+  ../../../../../dist/include/xpcom/nsCRT.h \
+  ../../../../../dist/include/system_wrappers/stdlib.h \
+  /usr/include/stdlib.h /usr/include/bits/waitflags.h \
+  /usr/include/bits/waitstatus.h \
+  ../../../../../dist/include/system_wrappers/alloca.h \
+  /usr/include/alloca.h ../../../../../dist/include/nspr/plstr.h \
+  ../../../../../dist/include/xpcom/nsCppSharedAllocator.h \
+  ../../../../../dist/include/system_wrappers/limits.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/limits.h \
+  /usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/syslimits.h \
+  /usr/include/limits.h /usr/include/bits/posix1_lim.h \
+  /usr/include/bits/local_lim.h \
+  ../../../../../dist/include/system_wrappers/linux/limits.h \
+  /usr/include/linux/limits.h /usr/include/bits/posix2_lim.h \
+  /usr/include/bits/xopen_lim.h \
+  ../../../../../dist/include/xpcom/xptcall.h \
+  ../../../../../dist/include/xpcom/xpt_struct.h \
+  ../../../../../dist/include/xpcom/xpt_arena.h \
+  ../../../../../dist/include/xpcom/xptinfo.h \
+  ../../../../../dist/include/xpcom/xptcstubsdecl.inc \
+  ../../../../../dist/include/system_wrappers/xpt_xdr.h \
+  ../../../../../dist/include/xpcom/xpt_xdr.h \
+  ../../../../../dist/include/system_wrappers/Python.h \
+  /usr/include/python2.5/Python.h /usr/include/python2.5/patchlevel.h \
+  /usr/include/python2.5/pyconfig.h \
+  ../../../../../dist/include/system_wrappers/errno.h \
+  /usr/include/errno.h /usr/include/bits/errno.h \
+  /usr/include/linux/errno.h /usr/include/asm/errno.h \
+  /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
+  ../../../../../dist/include/system_wrappers/unistd.h \
+  /usr/include/unistd.h /usr/include/bits/posix_opt.h \
+  /usr/include/bits/environments.h /usr/include/bits/confname.h \
+  ../../../../../dist/include/system_wrappers/getopt.h \
+  /usr/include/getopt.h \
+  ../../../../../dist/include/system_wrappers/assert.h \
+  /usr/include/assert.h /usr/include/python2.5/pyport.h \
+  ../../../../../dist/include/system_wrappers/stdint.h \
+  /usr/include/stdint.h /usr/include/bits/wchar.h \
+  ../../../../../dist/include/system_wrappers/math.h /usr/include/math.h \
+  /usr/include/bits/huge_val.h /usr/include/bits/huge_valf.h \
+  /usr/include/bits/huge_vall.h /usr/include/bits/inf.h \
+  /usr/include/bits/nan.h /usr/include/bits/mathdef.h \
+  /usr/include/bits/mathcalls.h \
+  ../../../../../dist/include/system_wrappers/sys/time.h \
+  /usr/include/sys/time.h \
+  ../../../../../dist/include/system_wrappers/sys/stat.h \
+  /usr/include/sys/stat.h /usr/include/bits/stat.h \
+  /usr/include/python2.5/pymem.h /usr/include/python2.5/object.h \
+  /usr/include/python2.5/objimpl.h /usr/include/python2.5/pydebug.h \
+  /usr/include/python2.5/unicodeobject.h \
+  /usr/include/python2.5/intobject.h /usr/include/python2.5/boolobject.h \
+  /usr/include/python2.5/longobject.h \
+  /usr/include/python2.5/floatobject.h \
+  /usr/include/python2.5/complexobject.h \
+  /usr/include/python2.5/rangeobject.h \
+  /usr/include/python2.5/stringobject.h \
+  /usr/include/python2.5/bufferobject.h \
+  /usr/include/python2.5/tupleobject.h \
+  /usr/include/python2.5/listobject.h /usr/include/python2.5/dictobject.h \
+  /usr/include/python2.5/enumobject.h /usr/include/python2.5/setobject.h \
+  /usr/include/python2.5/methodobject.h \
+  /usr/include/python2.5/moduleobject.h \
+  /usr/include/python2.5/funcobject.h \
+  /usr/include/python2.5/classobject.h \
+  /usr/include/python2.5/fileobject.h /usr/include/python2.5/cobject.h \
+  /usr/include/python2.5/traceback.h /usr/include/python2.5/sliceobject.h \
+  /usr/include/python2.5/cellobject.h /usr/include/python2.5/iterobject.h \
+  /usr/include/python2.5/genobject.h /usr/include/python2.5/descrobject.h \
+  /usr/include/python2.5/weakrefobject.h /usr/include/python2.5/codecs.h \
+  /usr/include/python2.5/pyerrors.h /usr/include/python2.5/pystate.h \
+  /usr/include/python2.5/pyarena.h /usr/include/python2.5/modsupport.h \
+  /usr/include/python2.5/pythonrun.h /usr/include/python2.5/ceval.h \
+  /usr/include/python2.5/sysmodule.h /usr/include/python2.5/intrcheck.h \
+  /usr/include/python2.5/import.h /usr/include/python2.5/abstract.h \
+  /usr/include/python2.5/compile.h /usr/include/python2.5/code.h \
+  /usr/include/python2.5/eval.h /usr/include/python2.5/pystrtod.h \
+  /usr/include/python2.5/pyfpe.h \
+  ../../../../../dist/include/system_wrappers/signal.h \
+  /usr/include/signal.h /usr/include/bits/signum.h \
+  /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h \
+  /usr/include/bits/sigcontext.h /usr/include/bits/sigstack.h \
+  ../../../../../dist/include/system_wrappers/sys/ucontext.h \
+  /usr/include/sys/ucontext.h /usr/include/bits/sigthread.h \
+  ../../../../../dist/include/system_wrappers/setjmp.h \
+  /usr/include/setjmp.h /usr/include/bits/setjmp.h \
+  ../../../../../dist/include/xpcom/nsXPCOM.h \
+  ../../../../../dist/include/xpcom/nsISupportsPrimitives.h \
+  ../../../../../dist/include/xpcom/nsIFile.h \
+  ../../../../../dist/include/xpcom/nsDirectoryServiceUtils.h \
+  ../../../../../dist/include/xpcom/nsIProperties.h \
+  ../../../../../dist/include/xpcom/nsIComponentRegistrar.h \
+  ../../../../../dist/include/xpcom/nsIComponentManagerObsolete.h \
+  ../../../../../dist/include/xpcom/nsIConsoleService.h \
+  ../../../../../dist/include/xpcom/nsIConsoleListener.h \
+  ../../../../../dist/include/xpcom/nsIConsoleMessage.h \
+  ../../../../../dist/include/nspr/nspr.h \
+  ../../../../../dist/include/nspr/pratom.h \
+  ../../../../../dist/include/nspr/prbit.h \
+  ../../../../../dist/include/nspr/prclist.h \
+  ../../../../../dist/include/nspr/prcmon.h \
+  ../../../../../dist/include/nspr/prmon.h \
+  ../../../../../dist/include/nspr/prcvar.h \
+  ../../../../../dist/include/nspr/prdtoa.h \
+  ../../../../../dist/include/nspr/prenv.h \
+  ../../../../../dist/include/nspr/prerror.h \
+  ../../../../../dist/include/nspr/prerr.h \
+  ../../../../../dist/include/nspr/prinet.h \
+  ../../../../../dist/include/system_wrappers/sys/socket.h \
+  /usr/include/sys/socket.h \
+  ../../../../../dist/include/system_wrappers/sys/uio.h \
+  /usr/include/sys/uio.h /usr/include/bits/uio.h \
+  /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+  /usr/include/asm/socket.h /usr/include/asm/sockios.h \
+  ../../../../../dist/include/system_wrappers/netinet/in.h \
+  /usr/include/netinet/in.h /usr/include/bits/in.h \
+  /usr/include/bits/byteswap.h \
+  ../../../../../dist/include/system_wrappers/arpa/inet.h \
+  /usr/include/arpa/inet.h \
+  ../../../../../dist/include/system_wrappers/netdb.h \
+  /usr/include/netdb.h /usr/include/rpc/netdb.h /usr/include/bits/netdb.h \
+  ../../../../../dist/include/nspr/prinit.h \
+  ../../../../../dist/include/nspr/prthread.h \
+  ../../../../../dist/include/nspr/prwin16.h \
+  ../../../../../dist/include/nspr/prio.h \
+  ../../../../../dist/include/nspr/prtime.h \
+  ../../../../../dist/include/nspr/pripcsem.h \
+  ../../../../../dist/include/nspr/prlink.h \
+  ../../../../../dist/include/nspr/prlog.h \
+  ../../../../../dist/include/nspr/prmem.h \
+  ../../../../../dist/include/nspr/prmwait.h \
+  ../../../../../dist/include/nspr/prnetdb.h \
+  ../../../../../dist/include/nspr/prprf.h \
+  ../../../../../dist/include/nspr/prproces.h \
+  ../../../../../dist/include/nspr/prrng.h \
+  ../../../../../dist/include/nspr/prrwlock.h \
+  ../../../../../dist/include/nspr/prshm.h \
+  ../../../../../dist/include/nspr/prshma.h \
+  ../../../../../dist/include/nspr/prsystem.h \
+  ../../../../../dist/include/nspr/prtpool.h \
+  ../../../../../dist/include/nspr/prtrace.h \
+  ../../../../../dist/include/xpcom/nsIEventQueue.h \
+  ../../../../../dist/include/xpcom/nsIEventTarget.h \
+  ../../../../../dist/include/xpcom/plevent.h \
+  ../../../../../dist/include/nspr/prclist.h \
+  ../../../../../dist/include/nspr/prlock.h \
+  ../../../../../dist/include/nspr/prcvar.h \
+  ../../../../../dist/include/nspr/prmon.h \
+  ../../../../../dist/include/xpcom/nsIProxyObjectManager.h \
+  ../../../../../dist/include/xpcom/nsProxyEvent.h \
+  ../../../../../dist/include/xpcom/nsAutoPtr.h \
+  ../../../../../dist/include/xpcom/nsIEventQueueService.h \
+  ../../../../../dist/include/xpcom/nsIEventQueue.h \
+  ../../../../../dist/include/xpcom/xptcall.h
Index: trunk/src/libs/xpcom18a4/python/src/module/_xpcom.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/module/_xpcom.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/module/_xpcom.cpp	(revision 11746)
@@ -0,0 +1,602 @@
+/* ***** 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 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
+#define MODULE_NAME "VBoxPython"
+#else
+#define MODULE_NAME "_xpcom"
+#endif
+
+// "boot-strap" methods - interfaces we need to get the base
+// interface support!
+
+/* 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);
+}
+
+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));
+}
+
+/* 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);
+}
+		
+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)",
+		                    obIS->ob_type->tp_name);
+	}
+	// 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);
+	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).
+}
+
+// @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;
+
+	// 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)",
+				    ob->ob_type->tp_name);
+
+	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;
+	return PyBuffer_New(bufSize);
+}
+
+// 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;
+}
+
+extern PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args);
+
+static struct PyMethodDef xpcom_methods[]=
+{
+	{"GetComponentManager", PyXPCOMMethod_GetComponentManager, 1},
+	{"GetComponentRegistrar", PyXPCOMMethod_GetComponentRegistrar, 1},
+	{"NS_GetGlobalComponentManager", PyXPCOMMethod_NS_GetGlobalComponentManager, 1}, // deprecated
+	{"XPTI_GetInterfaceInfoManager", PyXPCOMMethod_XPTI_GetInterfaceInfoManager, 1},
+	{"XPTC_InvokeByIndex", PyXPCOMMethod_XPTC_InvokeByIndex, 1},
+	{"GetServiceManager", PyXPCOMMethod_GetServiceManager, 1},
+	{"GetGlobalServiceManager", PyXPCOMMethod_GetGlobalServiceManager, 1}, // deprecated
+	{"IID", PyXPCOMMethod_IID, 1}, // IID is wrong - deprecated - not just IID, but CID, etc. 
+	{"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},
+	// These should no longer be used - just use the logging.getLogger('pyxpcom')...
+	{ NULL }
+};
+
+#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.
+//
+extern "C" NS_EXPORT
+void 
+init_xpcom() {
+	PyObject *oModule;
+
+	// ensure the framework has valid state to work with.
+	if (!PyXPCOM_Globals_Ensure())
+		return;
+
+	// Must force Python to start using thread locks
+	PyEval_InitThreads();
+
+	// Create the module and add the functions
+	oModule = Py_InitModule(MODULE_NAME, xpcom_methods);
+
+	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");
+		return;
+	}
+	PyDict_SetItemString(dict, "IIDType", (PyObject *)&Py_nsIID::type);
+
+	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);
+}
+
+#ifdef VBOX_PYXPCOM
+#include <VBox/com/com.h>
+using namespace com;
+
+#include <iprt/runtime.h>
+#include <iprt/stream.h>
+extern "C" NS_EXPORT
+void 
+initVBoxPython() {
+  static bool vboxInited = false;
+  if (!vboxInited) {
+    int rc = 0;
+
+    rc = RTR3Init(false, 0);
+    rc = com::Initialize();
+
+    init_xpcom();
+  }
+}
+#endif
Index: trunk/src/libs/xpcom18a4/python/src/readme.html
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/readme.html	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/readme.html	(revision 11746)
@@ -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>
Index: trunk/src/libs/xpcom18a4/python/src/xpcom.cpp
===================================================================
--- trunk/src/libs/xpcom18a4/python/src/xpcom.cpp	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/src/xpcom.cpp	(revision 11746)
@@ -0,0 +1,638 @@
+/* ***** 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 "nsIThread.h"
+#include "nsXPCOM.h"
+#include "nsISupportsPrimitives.h"
+#include "nsIModule.h"
+#include "nsIFile.h"
+#include "nsILocalFile.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIComponentManagerObsolete.h"
+
+#ifdef XP_WIN
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include "windows.h"
+#endif
+
+#include "nsIEventQueue.h"
+#include "nsIProxyObjectManager.h"
+
+PYXPCOM_EXPORT PyObject *PyXPCOM_Error = NULL;
+extern PRInt32 _PyXPCOM_GetGatewayCount(void);
+extern PRInt32 _PyXPCOM_GetInterfaceCount(void);
+
+extern void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
+
+#define LOADER_LINKS_WITH_PYTHON
+
+#ifndef PYXPCOM_USE_PYGILSTATE
+extern void PyXPCOM_InterpreterState_Ensure();
+#endif
+
+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)
+
+////////////////////////////////////////////////////////////
+// This is the main entry point called by the Python component
+// loader.
+extern "C" NS_EXPORT 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), PR_TRUE);
+	if (obServMgr==NULL) goto done;
+	obLocation = Py_nsISupports::PyObjectFromInterface(location, NS_GET_IID(nsIFile), PR_TRUE);
+	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;
+}
+
+// "boot-strap" methods - interfaces we need to get the base
+// interface support!
+
+/* 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;
+	nsIComponentManager* cm;
+	nsresult rv;
+	Py_BEGIN_ALLOW_THREADS;
+	rv = NS_GetComponentManager(&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(cm, NS_GET_IID(nsIComponentManagerObsolete), PR_FALSE, PR_FALSE);
+}
+
+static PyObject *
+PyXPCOMMethod_GetComponentManager(PyObject *self, PyObject *args)
+{
+	if (!PyArg_ParseTuple(args, ""))
+		return NULL;
+	nsIComponentManager* cm;
+	nsresult rv;
+	Py_BEGIN_ALLOW_THREADS;
+	rv = NS_GetComponentManager(&cm);
+	Py_END_ALLOW_THREADS;
+	if ( NS_FAILED(rv) )
+		return PyXPCOM_BuildPyException(rv);
+
+	return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsIComponentManager), PR_FALSE, PR_FALSE);
+}
+
+static PyObject *
+PyXPCOMMethod_GetServiceManager(PyObject *self, PyObject *args)
+{
+	if (!PyArg_ParseTuple(args, ""))
+		return NULL;
+	nsIServiceManager* sm;
+	nsresult rv;
+	Py_BEGIN_ALLOW_THREADS;
+	rv = NS_GetServiceManager(&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), PR_FALSE);
+}
+
+/* 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);
+}
+		
+static PyObject *
+PyXPCOMMethod_XPTI_GetInterfaceInfoManager(PyObject *self, PyObject *args)
+{
+	if (!PyArg_ParseTuple(args, ""))
+		return NULL;
+	nsCOMPtr<nsIInterfaceInfoManager> im(do_GetService(
+	                NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+	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.
+	return Py_nsISupports::PyObjectFromInterface(im, NS_GET_IID(nsIInterfaceInfoManager), PR_FALSE, PR_FALSE);
+}
+
+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;
+
+	// 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;
+	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);
+	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;
+
+	nsISupports *ret = NULL;
+	nsresult r = PyXPCOM_XPTStub::CreateNew(ob, iid, (void **)&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, PR_FALSE, 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).
+}
+
+// @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;
+
+	// 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;
+	nsISupports *presult = nsnull;
+	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,
+				(void **)&presult);
+	}
+	if (pQueueRelease)
+		pQueueRelease->Release();
+	Py_END_ALLOW_THREADS;
+
+	PyObject *result;
+	if (NS_SUCCEEDED(rv_proxy) ) {
+		result = Py_nsISupports::PyObjectFromInterface(presult, iid, PR_FALSE);
+	} else {
+		result = PyXPCOM_BuildPyException(rv_proxy);
+	}
+	return result;
+}
+
+PyObject *PyGetSpecialDirectory(PyObject *self, PyObject *args)
+{
+	char *dirname;
+	if (!PyArg_ParseTuple(args, "s:GetSpecialDirectory", &dirname))
+		return NULL;
+	nsIFile *file = NULL;
+	nsresult r = NS_GetSpecialDirectory(dirname, &file);
+	if ( NS_FAILED(r) )
+		return PyXPCOM_BuildPyException(r);
+	// returned object swallows our reference.
+	return Py_nsISupports::PyObjectFromInterface(file, NS_GET_IID(nsIFile), PR_FALSE);
+}
+
+PyObject *AllocateBuffer(PyObject *self, PyObject *args)
+{
+	int bufSize;
+	if (!PyArg_ParseTuple(args, "i", &bufSize))
+		return NULL;
+	return PyBuffer_New(bufSize);
+}
+
+PyObject *LogWarning(PyObject *self, PyObject *args)
+{
+	char *msg;
+	if (!PyArg_ParseTuple(args, "s", &msg))
+		return NULL;
+	PyXPCOM_LogWarning("%s", msg);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+PyObject *LogError(PyObject *self, PyObject *args)
+{
+	char *msg;
+	if (!PyArg_ParseTuple(args, "s", &msg))
+		return NULL;
+	PyXPCOM_LogError("%s", msg);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+extern PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args);
+
+static struct PyMethodDef xpcom_methods[]=
+{
+	{"GetComponentManager", PyXPCOMMethod_GetComponentManager, 1},
+	{"NS_GetGlobalComponentManager", PyXPCOMMethod_NS_GetGlobalComponentManager, 1}, // deprecated
+	{"XPTI_GetInterfaceInfoManager", PyXPCOMMethod_XPTI_GetInterfaceInfoManager, 1},
+	{"XPTC_InvokeByIndex", PyXPCOMMethod_XPTC_InvokeByIndex, 1},
+	{"GetServiceManager", PyXPCOMMethod_GetServiceManager, 1},
+	{"GetGlobalServiceManager", PyXPCOMMethod_GetGlobalServiceManager, 1}, // deprecated
+	{"IID", PyXPCOMMethod_IID, 1}, // IID is wrong - deprecated - not just IID, but CID, etc. 
+	{"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},
+	{"LogWarning", LogWarning, 1},
+	{"LogError", LogError, 1},
+	{ NULL }
+};
+
+////////////////////////////////////////////////////////////
+// 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;
+	}
+	return rc;
+}
+
+
+#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.
+//
+extern "C" NS_EXPORT
+void 
+init_xpcom() {
+	PyObject *oModule;
+
+	// ensure the framework has valid state to work with.
+	if (!PyXPCOM_Globals_Ensure())
+		return;
+
+	// Must force Python to start using thread locks
+	PyEval_InitThreads();
+
+	// Create the module and add the functions
+	oModule = Py_InitModule("_xpcom", xpcom_methods);
+
+	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");
+		return;
+	}
+	PyDict_SetItemString(dict, "IIDType", (PyObject *)&Py_nsIID::type);
+
+	// register our entry point.
+	PyObject *obFuncPtr = PyLong_FromVoidPtr((void *)&PyXPCOM_NSGetModule);
+	if (obFuncPtr)
+		PyDict_SetItemString(dict, 
+		                             "_NSGetModule_FuncPtr", 
+		                             obFuncPtr);
+	Py_XDECREF(obFuncPtr);
+
+	REGISTER_IID(nsISupports);
+	REGISTER_IID(nsISupportsCString);
+	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.
+
+	Py_nsISupports::InitType();
+	Py_nsIComponentManager::InitType(dict);
+	Py_nsIInterfaceInfoManager::InitType(dict);
+	Py_nsIEnumerator::InitType(dict);
+	Py_nsISimpleEnumerator::InitType(dict);
+	Py_nsIInterfaceInfo::InitType(dict);
+	Py_nsIInputStream::InitType(dict);
+	Py_nsIClassInfo::InitType(dict);
+	Py_nsIVariant::InitType(dict);
+	// for backward compatibility:
+	Py_nsIComponentManagerObsolete::InitType(dict);
+
+    // We have special support for proxies - may as well add their constants!
+    REGISTER_INT(PROXY_SYNC);
+    REGISTER_INT(PROXY_ASYNC);
+    REGISTER_INT(PROXY_ALWAYS);
+}
Index: trunk/src/libs/xpcom18a4/python/test/.cvsignore
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/.cvsignore	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/.cvsignore	(revision 11746)
@@ -0,0 +1,2 @@
+*.pyc
+*.pyo
Index: trunk/src/libs/xpcom18a4/python/test/output/test_com_exceptions
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/output/test_com_exceptions	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/output/test_com_exceptions	(revision 11746)
@@ -0,0 +1,8 @@
+test_com_exceptions
+** Unhandled exception calling 'int8 do_short(in int16, inout int16, out int16, out retval int16);'
+** Returning nsresult of NS_ERROR_FAILURE
+** Unhandled exception calling 'int8 do_unsigned_short(in uint16, inout uint16, out uint16, out retval uint16);'
+** Returning nsresult of NS_ERROR_FAILURE
+** Unhandled exception calling 'int8 do_unsigned_long_long(in uint64, inout uint64, out uint64, out retval uint64);'
+** Returning nsresult of NS_ERROR_FAILURE
+The xpcom exception tests passed
Index: trunk/src/libs/xpcom18a4/python/test/output/test_comfile
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/output/test_comfile	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/output/test_comfile	(revision 11746)
@@ -0,0 +1,7 @@
+test_comfile
+Open as string test worked.
+Open as URL test worked.
+File test using buffers worked.
+Local file read test worked.
+Read the correct data.
+Chunks read the correct data.
Index: trunk/src/libs/xpcom18a4/python/test/output/test_components
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/output/test_components	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/output/test_components	(revision 11746)
@@ -0,0 +1,4 @@
+test_components
+The interfaces object appeared to work!
+The classes object appeared to work!
+The ID function appeared to work!
Index: trunk/src/libs/xpcom18a4/python/test/output/test_isupports_primitives
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/output/test_isupports_primitives	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/output/test_isupports_primitives	(revision 11746)
@@ -0,0 +1,2 @@
+test_isupports_primitives
+The nsISupports primitive interface tests appeared to work
Index: trunk/src/libs/xpcom18a4/python/test/output/test_streams
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/output/test_streams	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/output/test_streams	(revision 11746)
@@ -0,0 +1,1 @@
+test_streams
Index: trunk/src/libs/xpcom18a4/python/test/output/test_test_component
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/output/test_test_component	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/output/test_test_component	(revision 11746)
@@ -0,0 +1,4 @@
+test_test_component
+Testing the Python.TestComponent component
+The Python test component worked!
+Javascript could successfully use the Python test component.
Index: trunk/src/libs/xpcom18a4/python/test/output/test_weakreferences
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/output/test_weakreferences	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/output/test_weakreferences	(revision 11746)
@@ -0,0 +1,2 @@
+test_weakreferences
+Weak-reference tests appear to have worked!
Index: trunk/src/libs/xpcom18a4/python/test/pyxpcom_test_tools.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/pyxpcom_test_tools.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/pyxpcom_test_tools.py	(revision 11746)
@@ -0,0 +1,126 @@
+# test tools for the pyxpcom bindings
+from xpcom import _xpcom
+import unittest
+
+# export a "getmemusage()" function that returns a useful "bytes used" count
+# for the current process.  Growth in this when doing the same thing over and
+# over implies a leak.
+
+try:
+    import win32api
+    import win32pdh
+    import win32pdhutil
+    have_pdh = 1
+except ImportError:
+    have_pdh = 0
+
+# XXX - win32pdh is slow, particularly finding our current process.
+# A better way would be good.
+
+# Our win32pdh specific functions - they can be at the top-level on all 
+# platforms, but will only actually be called if the modules are available.
+def FindMyCounter():
+    pid_me = win32api.GetCurrentProcessId()
+
+    object = "Process"
+    items, instances = win32pdh.EnumObjectItems(None,None,object, -1)
+    for instance in instances:
+        # We use 2 counters - "ID Process" and "Working Set"
+        counter = "ID Process"
+        format = win32pdh.PDH_FMT_LONG
+
+        hq = win32pdh.OpenQuery()
+        path = win32pdh.MakeCounterPath( (None,object,instance, None, -1,"ID Process") )
+        hc1 = win32pdh.AddCounter(hq, path)
+        path = win32pdh.MakeCounterPath( (None,object,instance, None, -1,"Working Set") )
+        hc2 = win32pdh.AddCounter(hq, path)
+        win32pdh.CollectQueryData(hq)
+        type, pid = win32pdh.GetFormattedCounterValue(hc1, format)
+        if pid==pid_me:
+            win32pdh.RemoveCounter(hc1) # not needed any more
+            return hq, hc2
+        # Not mine - close the query and try again
+        win32pdh.RemoveCounter(hc1)
+        win32pdh.RemoveCounter(hc2)
+        win32pdh.CloseQuery(hq)
+    else:
+        raise RuntimeError, "Can't find myself!?"
+
+def CloseCounter(hq, hc):
+    win32pdh.RemoveCounter(hc)
+    win32pdh.CloseQuery(hq)
+
+def GetCounterValue(hq, hc):
+    win32pdh.CollectQueryData(hq)
+    format = win32pdh.PDH_FMT_LONG
+    type, val = win32pdh.GetFormattedCounterValue(hc, format)
+    return val
+
+g_pdh_data = None
+# The pdh function that does the work
+def pdh_getmemusage():
+    global g_pdh_data
+    if g_pdh_data is None:
+        hq, hc = FindMyCounter()
+        g_pdh_data = hq, hc
+    hq, hc = g_pdh_data
+    return GetCounterValue(hq, hc)
+
+# The public bit
+if have_pdh:
+    getmemusage = pdh_getmemusage
+else:
+    def getmemusage():
+        return 0
+
+# Test runner utilities, including some support for builtin leak tests.
+class TestLoader(unittest.TestLoader):
+    def loadTestsFromTestCase(self, testCaseClass):
+        """Return a suite of all tests cases contained in testCaseClass"""
+        leak_tests = []
+        for name in self.getTestCaseNames(testCaseClass):
+            real_test = testCaseClass(name)
+            leak_test = self._getTestWrapper(real_test)
+            leak_tests.append(leak_test)
+        return self.suiteClass(leak_tests)
+    def _getTestWrapper(self, test):
+        # later! see pywin32's win32/test/util.py
+        return test
+    def loadTestsFromModule(self, mod):
+        if hasattr(mod, "suite"):
+            ret = mod.suite()
+        else:
+            ret = unittest.TestLoader.loadTestsFromModule(self, mod)
+        assert ret.countTestCases() > 0, "No tests in %r" % (mod,)
+        return ret
+    def loadTestsFromName(self, name, module=None):
+        test = unittest.TestLoader.loadTestsFromName(self, name, module)
+        if isinstance(test, unittest.TestSuite):
+            pass # hmmm? print "Don't wrap suites yet!", test._tests
+        elif isinstance(test, unittest.TestCase):
+            test = self._getTestWrapper(test)
+        else:
+            print "XXX - what is", test
+        return test
+
+# A base class our tests should derive from (well, one day it will be)
+TestCase = unittest.TestCase
+
+def suite_from_functions(*funcs):
+    suite = unittest.TestSuite()
+    for func in funcs:
+        suite.addTest(unittest.FunctionTestCase(func))
+    return suite
+
+def testmain(*args, **kw):
+    new_kw = kw.copy()
+    if not new_kw.has_key('testLoader'):
+        new_kw['testLoader'] = TestLoader()
+    try:
+        unittest.main(*args, **new_kw)
+    finally:
+        _xpcom.NS_ShutdownXPCOM()
+        ni = _xpcom._GetInterfaceCount()
+        ng = _xpcom._GetGatewayCount()
+        if ni or ng:
+            print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
Index: trunk/src/libs/xpcom18a4/python/test/regrtest.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/regrtest.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/regrtest.py	(revision 11746)
@@ -0,0 +1,91 @@
+# ***** 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 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 *****
+
+# regrtest.py
+#
+# The Regression Tests for the xpcom package.
+import os
+import sys
+
+import unittest
+
+# A little magic to create a single "test suite" from all test_ files
+# in this dir.  A single suite makes for prettier output test :)
+def suite():
+    # Loop over all test_*.py files here
+    try:
+        me = __file__
+    except NameError:
+        me = sys.argv[0]
+    me = os.path.abspath(me)
+    files = os.listdir(os.path.dirname(me))
+    suite = unittest.TestSuite()
+    # XXX - add the others here!
+    #suite.addTest(unittest.FunctionTestCase(import_all))
+    for file in files:
+        base, ext = os.path.splitext(file)
+        if ext=='.py' and os.path.basename(base).startswith("test_"):
+            mod = __import__(base)
+            if hasattr(mod, "suite"):
+                test = mod.suite()
+            else:
+                test = unittest.defaultTestLoader.loadTestsFromModule(mod)
+            suite.addTest(test)
+    return suite
+
+class CustomLoader(unittest.TestLoader):
+    def loadTestsFromModule(self, module):
+        return suite()
+
+try:
+    unittest.TestProgram(testLoader=CustomLoader())(argv=sys.argv)
+finally:
+    from xpcom import _xpcom
+    _xpcom.NS_ShutdownXPCOM() # To get leak stats and otherwise ensure life is good.
+    ni = _xpcom._GetInterfaceCount()
+    ng = _xpcom._GetGatewayCount()
+    if ni or ng:
+        # The old 'regrtest' that was not based purely on unittest did not
+        # do this check at the end - it relied on each module doing it itself.
+        # Thus, these leaks are not new, just newly noticed :)  Likely to be
+        # something silly like module globals.
+        if ni == 6 and ng == 1:
+            print "Sadly, there are 6/1 leaks, but these appear normal and benign"
+        else:
+            print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
+    else:
+        print "yay! Our leaks have all vanished!"
Index: trunk/src/libs/xpcom18a4/python/test/test_com_exceptions.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_com_exceptions.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_com_exceptions.py	(revision 11746)
@@ -0,0 +1,124 @@
+# ***** 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) 2000, 2001
+# ActiveState Tool Corp.  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 *****
+
+# Test pyxpcom exception.
+
+from xpcom import components, nsError, ServerException, COMException, logger
+from xpcom.server import WrapObject
+from pyxpcom_test_tools import testmain
+
+import unittest
+import logging
+
+class PythonFailingComponent:
+    # Re-use the test interface for this test.
+    _com_interfaces_ = components.interfaces.nsIPythonTestInterfaceExtra
+
+    def do_boolean(self, p1, p2):
+        # This should cause the caller to see a "silent" NS_ERROR_FAILURE exception.
+        raise ServerException()
+
+    def do_octet(self, p1, p2):
+        # This should cause the caller to see a "silent" NS_ERROR_NOT_IMPLEMENTED exception.
+        raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
+
+    def do_short(self, p1, p2):
+        # This should cause the caller to see a "debug" NS_ERROR_FAILURE exception.
+        raise COMException(nsError.NS_ERROR_NOT_IMPLEMENTED)
+
+    def do_unsigned_short(self, p1, p2):
+        # This should cause the caller to see a "debug" NS_ERROR_FAILURE exception.
+        raise "Foo"
+
+    def do_long(self, p1, p2):
+        # This should cause the caller to see a "silent" NS_ERROR_FAILURE exception.
+        raise ServerException
+
+    def do_unsigned_long(self, p1, p2):
+        # This should cause the caller to see a "silent" NS_ERROR_NOT_IMPLEMENTED exception.
+        raise ServerException, nsError.NS_ERROR_NOT_IMPLEMENTED
+
+    def do_long_long(self, p1, p2):
+        # This should cause the caller to see a "silent" NS_ERROR_NOT_IMPLEMENTED exception.
+        raise ServerException, (nsError.NS_ERROR_NOT_IMPLEMENTED, "testing")
+
+    def do_unsigned_long_long(self, p1, p2):
+        # Report of a crash in this case - test it!
+        raise ServerException, "A bad exception param"
+
+class TestHandler(logging.Handler):
+    def __init__(self, level=logging.ERROR): # only counting error records
+        logging.Handler.__init__(self, level)
+        self.records = []
+    
+    def reset(self):
+        self.records = []
+
+    def handle(self, record):
+        self.records.append(record)
+
+class ExceptionTests(unittest.TestCase):
+
+    def _testit(self, expected_errno, num_tracebacks, func, *args):
+
+        # Screw with the logger
+        old_handlers = logger.handlers
+        test_handler = TestHandler()
+        logger.handlers = [test_handler]
+
+        try:
+            try:
+                apply(func, args)
+            except COMException, what:
+                if what.errno != expected_errno:
+                    raise
+        finally:
+            logger.handlers = old_handlers
+        self.failUnlessEqual(num_tracebacks, len(test_handler.records))
+
+    def testEmAll(self):
+        ob = WrapObject( PythonFailingComponent(), components.interfaces.nsIPythonTestInterfaceExtra)
+        self._testit(nsError.NS_ERROR_FAILURE, 0, ob.do_boolean, 0, 0)
+        self._testit(nsError.NS_ERROR_NOT_IMPLEMENTED, 0, ob.do_octet, 0, 0)
+        self._testit(nsError.NS_ERROR_FAILURE, 1, ob.do_short, 0, 0)
+        self._testit(nsError.NS_ERROR_FAILURE, 1, ob.do_unsigned_short, 0, 0)
+        self._testit(nsError.NS_ERROR_FAILURE, 0, ob.do_long, 0, 0)
+        self._testit(nsError.NS_ERROR_NOT_IMPLEMENTED, 0, ob.do_unsigned_long, 0, 0)
+        self._testit(nsError.NS_ERROR_NOT_IMPLEMENTED, 0, ob.do_long_long, 0, 0)
+        self._testit(nsError.NS_ERROR_FAILURE, 1, ob.do_unsigned_long_long, 0, 0)
+
+if __name__=='__main__':
+    testmain()
Index: trunk/src/libs/xpcom18a4/python/test/test_comfile.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_comfile.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_comfile.py	(revision 11746)
@@ -0,0 +1,49 @@
+# ***** 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, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Mark Hammond (markh@activestate.com)
+#
+# 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 *****
+
+"""Test the xpcom.file module."""
+from pyxpcom_test_tools import suite_from_functions, testmain
+
+import xpcom.file
+
+# Make this test run under our std test suite
+def suite():
+    return suite_from_functions(xpcom.file._TestAll)
+
+if __name__=='__main__':
+    testmain()
+
Index: trunk/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/py_test_component.h
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/py_test_component.h	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/py_test_component.h	(revision 11746)
@@ -0,0 +1,1411 @@
+/*
+ * DO NOT EDIT.  THIS FILE IS GENERATED FROM py_test_component.idl
+ */
+
+#ifndef __gen_py_test_component_h__
+#define __gen_py_test_component_h__
+
+
+#ifndef __gen_nsISupports_h__
+#include "nsISupports.h"
+#endif
+
+#ifndef __gen_nsIVariant_h__
+#include "nsIVariant.h"
+#endif
+
+/* For IDL files that don't want to include root IDL files. */
+#ifndef NS_NO_VTABLE
+#define NS_NO_VTABLE
+#endif
+
+/* starting interface:    nsIPythonTestInterface */
+#define NS_IPYTHONTESTINTERFACE_IID_STR "1ecaed4f-e4d5-4ee7-abf0-7d72ae1441d7"
+
+#define NS_IPYTHONTESTINTERFACE_IID \
+  {0x1ecaed4f, 0xe4d5, 0x4ee7, \
+    { 0xab, 0xf0, 0x7d, 0x72, 0xae, 0x14, 0x41, 0xd7 }}
+
+class NS_NO_VTABLE nsIPythonTestInterface : public nsISupports {
+ public: 
+
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPYTHONTESTINTERFACE_IID)
+
+  enum { One = 1 };
+
+  enum { Two = 2 };
+
+  enum { MinusOne = -1 };
+
+  enum { BigLong = 2147483647 };
+
+  enum { BiggerLong = 4294967295 };
+
+  enum { BigULong = 4294967295U };
+
+  /* attribute boolean boolean_value; */
+  NS_IMETHOD GetBoolean_value(PRBool *aBoolean_value) = 0;
+  NS_IMETHOD SetBoolean_value(PRBool aBoolean_value) = 0;
+
+  /* attribute octet octet_value; */
+  NS_IMETHOD GetOctet_value(PRUint8 *aOctet_value) = 0;
+  NS_IMETHOD SetOctet_value(PRUint8 aOctet_value) = 0;
+
+  /* attribute short short_value; */
+  NS_IMETHOD GetShort_value(PRInt16 *aShort_value) = 0;
+  NS_IMETHOD SetShort_value(PRInt16 aShort_value) = 0;
+
+  /* attribute unsigned short ushort_value; */
+  NS_IMETHOD GetUshort_value(PRUint16 *aUshort_value) = 0;
+  NS_IMETHOD SetUshort_value(PRUint16 aUshort_value) = 0;
+
+  /* attribute long long_value; */
+  NS_IMETHOD GetLong_value(PRInt32 *aLong_value) = 0;
+  NS_IMETHOD SetLong_value(PRInt32 aLong_value) = 0;
+
+  /* attribute unsigned long ulong_value; */
+  NS_IMETHOD GetUlong_value(PRUint32 *aUlong_value) = 0;
+  NS_IMETHOD SetUlong_value(PRUint32 aUlong_value) = 0;
+
+  /* attribute long long long_long_value; */
+  NS_IMETHOD GetLong_long_value(PRInt64 *aLong_long_value) = 0;
+  NS_IMETHOD SetLong_long_value(PRInt64 aLong_long_value) = 0;
+
+  /* attribute unsigned long long ulong_long_value; */
+  NS_IMETHOD GetUlong_long_value(PRUint64 *aUlong_long_value) = 0;
+  NS_IMETHOD SetUlong_long_value(PRUint64 aUlong_long_value) = 0;
+
+  /* attribute float float_value; */
+  NS_IMETHOD GetFloat_value(float *aFloat_value) = 0;
+  NS_IMETHOD SetFloat_value(float aFloat_value) = 0;
+
+  /* attribute double double_value; */
+  NS_IMETHOD GetDouble_value(double *aDouble_value) = 0;
+  NS_IMETHOD SetDouble_value(double aDouble_value) = 0;
+
+  /* attribute char char_value; */
+  NS_IMETHOD GetChar_value(char *aChar_value) = 0;
+  NS_IMETHOD SetChar_value(char aChar_value) = 0;
+
+  /* attribute wchar wchar_value; */
+  NS_IMETHOD GetWchar_value(PRUnichar *aWchar_value) = 0;
+  NS_IMETHOD SetWchar_value(PRUnichar aWchar_value) = 0;
+
+  /* attribute string string_value; */
+  NS_IMETHOD GetString_value(char * *aString_value) = 0;
+  NS_IMETHOD SetString_value(const char * aString_value) = 0;
+
+  /* attribute wstring wstring_value; */
+  NS_IMETHOD GetWstring_value(PRUnichar * *aWstring_value) = 0;
+  NS_IMETHOD SetWstring_value(const PRUnichar * aWstring_value) = 0;
+
+  /* attribute AString astring_value; */
+  NS_IMETHOD GetAstring_value(nsAString & aAstring_value) = 0;
+  NS_IMETHOD SetAstring_value(const nsAString & aAstring_value) = 0;
+
+  /* attribute ACString acstring_value; */
+  NS_IMETHOD GetAcstring_value(nsACString & aAcstring_value) = 0;
+  NS_IMETHOD SetAcstring_value(const nsACString & aAcstring_value) = 0;
+
+  /* attribute AUTF8String utf8string_value; */
+  NS_IMETHOD GetUtf8string_value(nsACString & aUtf8string_value) = 0;
+  NS_IMETHOD SetUtf8string_value(const nsACString & aUtf8string_value) = 0;
+
+  /* attribute nsIIDRef iid_value; */
+  NS_IMETHOD GetIid_value(nsIID & *aIid_value) = 0;
+  NS_IMETHOD SetIid_value(const nsIID & aIid_value) = 0;
+
+  /* attribute nsIPythonTestInterface interface_value; */
+  NS_IMETHOD GetInterface_value(nsIPythonTestInterface * *aInterface_value) = 0;
+  NS_IMETHOD SetInterface_value(nsIPythonTestInterface * aInterface_value) = 0;
+
+  /* attribute nsISupports isupports_value; */
+  NS_IMETHOD GetIsupports_value(nsISupports * *aIsupports_value) = 0;
+  NS_IMETHOD SetIsupports_value(nsISupports * aIsupports_value) = 0;
+
+  /* boolean do_boolean (in boolean p1, inout boolean p2, out boolean p3); */
+  NS_IMETHOD Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval) = 0;
+
+  /* octet do_octet (in octet p1, inout octet p2, out octet p3); */
+  NS_IMETHOD Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval) = 0;
+
+  /* short do_short (in short p1, inout short p2, out short p3); */
+  NS_IMETHOD Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval) = 0;
+
+  /* unsigned short do_unsigned_short (in unsigned short p1, inout unsigned short p2, out unsigned short p3); */
+  NS_IMETHOD Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval) = 0;
+
+  /* long do_long (in long p1, inout long p2, out long p3); */
+  NS_IMETHOD Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval) = 0;
+
+  /* unsigned long do_unsigned_long (in unsigned long p1, inout unsigned long p2, out unsigned long p3); */
+  NS_IMETHOD Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval) = 0;
+
+  /* long long do_long_long (in long long p1, inout long long p2, out long long p3); */
+  NS_IMETHOD Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval) = 0;
+
+  /* unsigned long long do_unsigned_long_long (in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3); */
+  NS_IMETHOD Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval) = 0;
+
+  /* float do_float (in float p1, inout float p2, out float p3); */
+  NS_IMETHOD Do_float(float p1, float *p2, float *p3, float *_retval) = 0;
+
+  /* double do_double (in double p1, inout double p2, out double p3); */
+  NS_IMETHOD Do_double(double p1, double *p2, double *p3, double *_retval) = 0;
+
+  /* char do_char (in char p1, inout char p2, out char p3); */
+  NS_IMETHOD Do_char(char p1, char *p2, char *p3, char *_retval) = 0;
+
+  /* wchar do_wchar (in wchar p1, inout wchar p2, out wchar p3); */
+  NS_IMETHOD Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval) = 0;
+
+  /* string do_string (in string p1, inout string p2, out string p3); */
+  NS_IMETHOD Do_string(const char *p1, char **p2, char **p3, char **_retval) = 0;
+
+  /* wstring do_wstring (in wstring p1, inout wstring p2, out wstring p3); */
+  NS_IMETHOD Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval) = 0;
+
+  /* nsIIDRef do_nsIIDRef (in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3); */
+  NS_IMETHOD Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval) = 0;
+
+  /* nsIPythonTestInterface do_nsIPythonTestInterface (in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3); */
+  NS_IMETHOD Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval) = 0;
+
+  /* nsISupports do_nsISupports (in nsISupports p1, inout nsISupports p2, out nsISupports p3); */
+  NS_IMETHOD Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval) = 0;
+
+  /* void do_nsISupportsIs (in nsIIDRef iid, [iid_is (iid), retval] out nsQIResult result); */
+  NS_IMETHOD Do_nsISupportsIs(const nsIID & iid, void * *result) = 0;
+
+};
+
+/* Use this macro when declaring classes that implement this interface. */
+#define NS_DECL_NSIPYTHONTESTINTERFACE \
+  NS_IMETHOD GetBoolean_value(PRBool *aBoolean_value); \
+  NS_IMETHOD SetBoolean_value(PRBool aBoolean_value); \
+  NS_IMETHOD GetOctet_value(PRUint8 *aOctet_value); \
+  NS_IMETHOD SetOctet_value(PRUint8 aOctet_value); \
+  NS_IMETHOD GetShort_value(PRInt16 *aShort_value); \
+  NS_IMETHOD SetShort_value(PRInt16 aShort_value); \
+  NS_IMETHOD GetUshort_value(PRUint16 *aUshort_value); \
+  NS_IMETHOD SetUshort_value(PRUint16 aUshort_value); \
+  NS_IMETHOD GetLong_value(PRInt32 *aLong_value); \
+  NS_IMETHOD SetLong_value(PRInt32 aLong_value); \
+  NS_IMETHOD GetUlong_value(PRUint32 *aUlong_value); \
+  NS_IMETHOD SetUlong_value(PRUint32 aUlong_value); \
+  NS_IMETHOD GetLong_long_value(PRInt64 *aLong_long_value); \
+  NS_IMETHOD SetLong_long_value(PRInt64 aLong_long_value); \
+  NS_IMETHOD GetUlong_long_value(PRUint64 *aUlong_long_value); \
+  NS_IMETHOD SetUlong_long_value(PRUint64 aUlong_long_value); \
+  NS_IMETHOD GetFloat_value(float *aFloat_value); \
+  NS_IMETHOD SetFloat_value(float aFloat_value); \
+  NS_IMETHOD GetDouble_value(double *aDouble_value); \
+  NS_IMETHOD SetDouble_value(double aDouble_value); \
+  NS_IMETHOD GetChar_value(char *aChar_value); \
+  NS_IMETHOD SetChar_value(char aChar_value); \
+  NS_IMETHOD GetWchar_value(PRUnichar *aWchar_value); \
+  NS_IMETHOD SetWchar_value(PRUnichar aWchar_value); \
+  NS_IMETHOD GetString_value(char * *aString_value); \
+  NS_IMETHOD SetString_value(const char * aString_value); \
+  NS_IMETHOD GetWstring_value(PRUnichar * *aWstring_value); \
+  NS_IMETHOD SetWstring_value(const PRUnichar * aWstring_value); \
+  NS_IMETHOD GetAstring_value(nsAString & aAstring_value); \
+  NS_IMETHOD SetAstring_value(const nsAString & aAstring_value); \
+  NS_IMETHOD GetAcstring_value(nsACString & aAcstring_value); \
+  NS_IMETHOD SetAcstring_value(const nsACString & aAcstring_value); \
+  NS_IMETHOD GetUtf8string_value(nsACString & aUtf8string_value); \
+  NS_IMETHOD SetUtf8string_value(const nsACString & aUtf8string_value); \
+  NS_IMETHOD GetIid_value(nsIID & *aIid_value); \
+  NS_IMETHOD SetIid_value(const nsIID & aIid_value); \
+  NS_IMETHOD GetInterface_value(nsIPythonTestInterface * *aInterface_value); \
+  NS_IMETHOD SetInterface_value(nsIPythonTestInterface * aInterface_value); \
+  NS_IMETHOD GetIsupports_value(nsISupports * *aIsupports_value); \
+  NS_IMETHOD SetIsupports_value(nsISupports * aIsupports_value); \
+  NS_IMETHOD Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval); \
+  NS_IMETHOD Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval); \
+  NS_IMETHOD Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval); \
+  NS_IMETHOD Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval); \
+  NS_IMETHOD Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval); \
+  NS_IMETHOD Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval); \
+  NS_IMETHOD Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval); \
+  NS_IMETHOD Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval); \
+  NS_IMETHOD Do_float(float p1, float *p2, float *p3, float *_retval); \
+  NS_IMETHOD Do_double(double p1, double *p2, double *p3, double *_retval); \
+  NS_IMETHOD Do_char(char p1, char *p2, char *p3, char *_retval); \
+  NS_IMETHOD Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval); \
+  NS_IMETHOD Do_string(const char *p1, char **p2, char **p3, char **_retval); \
+  NS_IMETHOD Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval); \
+  NS_IMETHOD Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval); \
+  NS_IMETHOD Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval); \
+  NS_IMETHOD Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval); \
+  NS_IMETHOD Do_nsISupportsIs(const nsIID & iid, void * *result); 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */
+#define NS_FORWARD_NSIPYTHONTESTINTERFACE(_to) \
+  NS_IMETHOD GetBoolean_value(PRBool *aBoolean_value) { return _to GetBoolean_value(aBoolean_value); } \
+  NS_IMETHOD SetBoolean_value(PRBool aBoolean_value) { return _to SetBoolean_value(aBoolean_value); } \
+  NS_IMETHOD GetOctet_value(PRUint8 *aOctet_value) { return _to GetOctet_value(aOctet_value); } \
+  NS_IMETHOD SetOctet_value(PRUint8 aOctet_value) { return _to SetOctet_value(aOctet_value); } \
+  NS_IMETHOD GetShort_value(PRInt16 *aShort_value) { return _to GetShort_value(aShort_value); } \
+  NS_IMETHOD SetShort_value(PRInt16 aShort_value) { return _to SetShort_value(aShort_value); } \
+  NS_IMETHOD GetUshort_value(PRUint16 *aUshort_value) { return _to GetUshort_value(aUshort_value); } \
+  NS_IMETHOD SetUshort_value(PRUint16 aUshort_value) { return _to SetUshort_value(aUshort_value); } \
+  NS_IMETHOD GetLong_value(PRInt32 *aLong_value) { return _to GetLong_value(aLong_value); } \
+  NS_IMETHOD SetLong_value(PRInt32 aLong_value) { return _to SetLong_value(aLong_value); } \
+  NS_IMETHOD GetUlong_value(PRUint32 *aUlong_value) { return _to GetUlong_value(aUlong_value); } \
+  NS_IMETHOD SetUlong_value(PRUint32 aUlong_value) { return _to SetUlong_value(aUlong_value); } \
+  NS_IMETHOD GetLong_long_value(PRInt64 *aLong_long_value) { return _to GetLong_long_value(aLong_long_value); } \
+  NS_IMETHOD SetLong_long_value(PRInt64 aLong_long_value) { return _to SetLong_long_value(aLong_long_value); } \
+  NS_IMETHOD GetUlong_long_value(PRUint64 *aUlong_long_value) { return _to GetUlong_long_value(aUlong_long_value); } \
+  NS_IMETHOD SetUlong_long_value(PRUint64 aUlong_long_value) { return _to SetUlong_long_value(aUlong_long_value); } \
+  NS_IMETHOD GetFloat_value(float *aFloat_value) { return _to GetFloat_value(aFloat_value); } \
+  NS_IMETHOD SetFloat_value(float aFloat_value) { return _to SetFloat_value(aFloat_value); } \
+  NS_IMETHOD GetDouble_value(double *aDouble_value) { return _to GetDouble_value(aDouble_value); } \
+  NS_IMETHOD SetDouble_value(double aDouble_value) { return _to SetDouble_value(aDouble_value); } \
+  NS_IMETHOD GetChar_value(char *aChar_value) { return _to GetChar_value(aChar_value); } \
+  NS_IMETHOD SetChar_value(char aChar_value) { return _to SetChar_value(aChar_value); } \
+  NS_IMETHOD GetWchar_value(PRUnichar *aWchar_value) { return _to GetWchar_value(aWchar_value); } \
+  NS_IMETHOD SetWchar_value(PRUnichar aWchar_value) { return _to SetWchar_value(aWchar_value); } \
+  NS_IMETHOD GetString_value(char * *aString_value) { return _to GetString_value(aString_value); } \
+  NS_IMETHOD SetString_value(const char * aString_value) { return _to SetString_value(aString_value); } \
+  NS_IMETHOD GetWstring_value(PRUnichar * *aWstring_value) { return _to GetWstring_value(aWstring_value); } \
+  NS_IMETHOD SetWstring_value(const PRUnichar * aWstring_value) { return _to SetWstring_value(aWstring_value); } \
+  NS_IMETHOD GetAstring_value(nsAString & aAstring_value) { return _to GetAstring_value(aAstring_value); } \
+  NS_IMETHOD SetAstring_value(const nsAString & aAstring_value) { return _to SetAstring_value(aAstring_value); } \
+  NS_IMETHOD GetAcstring_value(nsACString & aAcstring_value) { return _to GetAcstring_value(aAcstring_value); } \
+  NS_IMETHOD SetAcstring_value(const nsACString & aAcstring_value) { return _to SetAcstring_value(aAcstring_value); } \
+  NS_IMETHOD GetUtf8string_value(nsACString & aUtf8string_value) { return _to GetUtf8string_value(aUtf8string_value); } \
+  NS_IMETHOD SetUtf8string_value(const nsACString & aUtf8string_value) { return _to SetUtf8string_value(aUtf8string_value); } \
+  NS_IMETHOD GetIid_value(nsIID & *aIid_value) { return _to GetIid_value(aIid_value); } \
+  NS_IMETHOD SetIid_value(const nsIID & aIid_value) { return _to SetIid_value(aIid_value); } \
+  NS_IMETHOD GetInterface_value(nsIPythonTestInterface * *aInterface_value) { return _to GetInterface_value(aInterface_value); } \
+  NS_IMETHOD SetInterface_value(nsIPythonTestInterface * aInterface_value) { return _to SetInterface_value(aInterface_value); } \
+  NS_IMETHOD GetIsupports_value(nsISupports * *aIsupports_value) { return _to GetIsupports_value(aIsupports_value); } \
+  NS_IMETHOD SetIsupports_value(nsISupports * aIsupports_value) { return _to SetIsupports_value(aIsupports_value); } \
+  NS_IMETHOD Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval) { return _to Do_boolean(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval) { return _to Do_octet(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval) { return _to Do_short(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval) { return _to Do_unsigned_short(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval) { return _to Do_long(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval) { return _to Do_unsigned_long(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval) { return _to Do_long_long(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval) { return _to Do_unsigned_long_long(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_float(float p1, float *p2, float *p3, float *_retval) { return _to Do_float(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_double(double p1, double *p2, double *p3, double *_retval) { return _to Do_double(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_char(char p1, char *p2, char *p3, char *_retval) { return _to Do_char(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval) { return _to Do_wchar(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_string(const char *p1, char **p2, char **p3, char **_retval) { return _to Do_string(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval) { return _to Do_wstring(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval) { return _to Do_nsIIDRef(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval) { return _to Do_nsIPythonTestInterface(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval) { return _to Do_nsISupports(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_nsISupportsIs(const nsIID & iid, void * *result) { return _to Do_nsISupportsIs(iid, result); } 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
+#define NS_FORWARD_SAFE_NSIPYTHONTESTINTERFACE(_to) \
+  NS_IMETHOD GetBoolean_value(PRBool *aBoolean_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetBoolean_value(aBoolean_value); } \
+  NS_IMETHOD SetBoolean_value(PRBool aBoolean_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetBoolean_value(aBoolean_value); } \
+  NS_IMETHOD GetOctet_value(PRUint8 *aOctet_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetOctet_value(aOctet_value); } \
+  NS_IMETHOD SetOctet_value(PRUint8 aOctet_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetOctet_value(aOctet_value); } \
+  NS_IMETHOD GetShort_value(PRInt16 *aShort_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetShort_value(aShort_value); } \
+  NS_IMETHOD SetShort_value(PRInt16 aShort_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetShort_value(aShort_value); } \
+  NS_IMETHOD GetUshort_value(PRUint16 *aUshort_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUshort_value(aUshort_value); } \
+  NS_IMETHOD SetUshort_value(PRUint16 aUshort_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetUshort_value(aUshort_value); } \
+  NS_IMETHOD GetLong_value(PRInt32 *aLong_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetLong_value(aLong_value); } \
+  NS_IMETHOD SetLong_value(PRInt32 aLong_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetLong_value(aLong_value); } \
+  NS_IMETHOD GetUlong_value(PRUint32 *aUlong_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUlong_value(aUlong_value); } \
+  NS_IMETHOD SetUlong_value(PRUint32 aUlong_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetUlong_value(aUlong_value); } \
+  NS_IMETHOD GetLong_long_value(PRInt64 *aLong_long_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetLong_long_value(aLong_long_value); } \
+  NS_IMETHOD SetLong_long_value(PRInt64 aLong_long_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetLong_long_value(aLong_long_value); } \
+  NS_IMETHOD GetUlong_long_value(PRUint64 *aUlong_long_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUlong_long_value(aUlong_long_value); } \
+  NS_IMETHOD SetUlong_long_value(PRUint64 aUlong_long_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetUlong_long_value(aUlong_long_value); } \
+  NS_IMETHOD GetFloat_value(float *aFloat_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetFloat_value(aFloat_value); } \
+  NS_IMETHOD SetFloat_value(float aFloat_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetFloat_value(aFloat_value); } \
+  NS_IMETHOD GetDouble_value(double *aDouble_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDouble_value(aDouble_value); } \
+  NS_IMETHOD SetDouble_value(double aDouble_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetDouble_value(aDouble_value); } \
+  NS_IMETHOD GetChar_value(char *aChar_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetChar_value(aChar_value); } \
+  NS_IMETHOD SetChar_value(char aChar_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetChar_value(aChar_value); } \
+  NS_IMETHOD GetWchar_value(PRUnichar *aWchar_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetWchar_value(aWchar_value); } \
+  NS_IMETHOD SetWchar_value(PRUnichar aWchar_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetWchar_value(aWchar_value); } \
+  NS_IMETHOD GetString_value(char * *aString_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetString_value(aString_value); } \
+  NS_IMETHOD SetString_value(const char * aString_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetString_value(aString_value); } \
+  NS_IMETHOD GetWstring_value(PRUnichar * *aWstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetWstring_value(aWstring_value); } \
+  NS_IMETHOD SetWstring_value(const PRUnichar * aWstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetWstring_value(aWstring_value); } \
+  NS_IMETHOD GetAstring_value(nsAString & aAstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetAstring_value(aAstring_value); } \
+  NS_IMETHOD SetAstring_value(const nsAString & aAstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetAstring_value(aAstring_value); } \
+  NS_IMETHOD GetAcstring_value(nsACString & aAcstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetAcstring_value(aAcstring_value); } \
+  NS_IMETHOD SetAcstring_value(const nsACString & aAcstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetAcstring_value(aAcstring_value); } \
+  NS_IMETHOD GetUtf8string_value(nsACString & aUtf8string_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUtf8string_value(aUtf8string_value); } \
+  NS_IMETHOD SetUtf8string_value(const nsACString & aUtf8string_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetUtf8string_value(aUtf8string_value); } \
+  NS_IMETHOD GetIid_value(nsIID & *aIid_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetIid_value(aIid_value); } \
+  NS_IMETHOD SetIid_value(const nsIID & aIid_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetIid_value(aIid_value); } \
+  NS_IMETHOD GetInterface_value(nsIPythonTestInterface * *aInterface_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetInterface_value(aInterface_value); } \
+  NS_IMETHOD SetInterface_value(nsIPythonTestInterface * aInterface_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetInterface_value(aInterface_value); } \
+  NS_IMETHOD GetIsupports_value(nsISupports * *aIsupports_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetIsupports_value(aIsupports_value); } \
+  NS_IMETHOD SetIsupports_value(nsISupports * aIsupports_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetIsupports_value(aIsupports_value); } \
+  NS_IMETHOD Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_boolean(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_octet(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_short(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_unsigned_short(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_long(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_unsigned_long(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_long_long(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_unsigned_long_long(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_float(float p1, float *p2, float *p3, float *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_float(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_double(double p1, double *p2, double *p3, double *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_double(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_char(char p1, char *p2, char *p3, char *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_char(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_wchar(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_string(const char *p1, char **p2, char **p3, char **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_string(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_wstring(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_nsIIDRef(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_nsIPythonTestInterface(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_nsISupports(p1, p2, p3, _retval); } \
+  NS_IMETHOD Do_nsISupportsIs(const nsIID & iid, void * *result) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_nsISupportsIs(iid, result); } 
+
+#if 0
+/* Use the code below as a template for the implementation class for this interface. */
+
+/* Header file */
+class nsPythonTestInterface : public nsIPythonTestInterface
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPYTHONTESTINTERFACE
+
+  nsPythonTestInterface();
+
+private:
+  ~nsPythonTestInterface();
+
+protected:
+  /* additional members */
+};
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(nsPythonTestInterface, nsIPythonTestInterface)
+
+nsPythonTestInterface::nsPythonTestInterface()
+{
+  /* member initializers and constructor code */
+}
+
+nsPythonTestInterface::~nsPythonTestInterface()
+{
+  /* destructor code */
+}
+
+/* attribute boolean boolean_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetBoolean_value(PRBool *aBoolean_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetBoolean_value(PRBool aBoolean_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute octet octet_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetOctet_value(PRUint8 *aOctet_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetOctet_value(PRUint8 aOctet_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute short short_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetShort_value(PRInt16 *aShort_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetShort_value(PRInt16 aShort_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute unsigned short ushort_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetUshort_value(PRUint16 *aUshort_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetUshort_value(PRUint16 aUshort_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute long long_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetLong_value(PRInt32 *aLong_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetLong_value(PRInt32 aLong_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute unsigned long ulong_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetUlong_value(PRUint32 *aUlong_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetUlong_value(PRUint32 aUlong_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute long long long_long_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetLong_long_value(PRInt64 *aLong_long_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetLong_long_value(PRInt64 aLong_long_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute unsigned long long ulong_long_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetUlong_long_value(PRUint64 *aUlong_long_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetUlong_long_value(PRUint64 aUlong_long_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute float float_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetFloat_value(float *aFloat_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetFloat_value(float aFloat_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute double double_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetDouble_value(double *aDouble_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetDouble_value(double aDouble_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute char char_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetChar_value(char *aChar_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetChar_value(char aChar_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute wchar wchar_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetWchar_value(PRUnichar *aWchar_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetWchar_value(PRUnichar aWchar_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute string string_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetString_value(char * *aString_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetString_value(const char * aString_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute wstring wstring_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetWstring_value(PRUnichar * *aWstring_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetWstring_value(const PRUnichar * aWstring_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute AString astring_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetAstring_value(nsAString & aAstring_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetAstring_value(const nsAString & aAstring_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute ACString acstring_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetAcstring_value(nsACString & aAcstring_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetAcstring_value(const nsACString & aAcstring_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute AUTF8String utf8string_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetUtf8string_value(nsACString & aUtf8string_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetUtf8string_value(const nsACString & aUtf8string_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute nsIIDRef iid_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetIid_value(nsIID & *aIid_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetIid_value(const nsIID & aIid_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute nsIPythonTestInterface interface_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetInterface_value(nsIPythonTestInterface * *aInterface_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetInterface_value(nsIPythonTestInterface * aInterface_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute nsISupports isupports_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetIsupports_value(nsISupports * *aIsupports_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetIsupports_value(nsISupports * aIsupports_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* boolean do_boolean (in boolean p1, inout boolean p2, out boolean p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* octet do_octet (in octet p1, inout octet p2, out octet p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* short do_short (in short p1, inout short p2, out short p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* unsigned short do_unsigned_short (in unsigned short p1, inout unsigned short p2, out unsigned short p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* long do_long (in long p1, inout long p2, out long p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* unsigned long do_unsigned_long (in unsigned long p1, inout unsigned long p2, out unsigned long p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* long long do_long_long (in long long p1, inout long long p2, out long long p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* unsigned long long do_unsigned_long_long (in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* float do_float (in float p1, inout float p2, out float p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_float(float p1, float *p2, float *p3, float *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* double do_double (in double p1, inout double p2, out double p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_double(double p1, double *p2, double *p3, double *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* char do_char (in char p1, inout char p2, out char p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_char(char p1, char *p2, char *p3, char *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* wchar do_wchar (in wchar p1, inout wchar p2, out wchar p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* string do_string (in string p1, inout string p2, out string p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_string(const char *p1, char **p2, char **p3, char **_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* wstring do_wstring (in wstring p1, inout wstring p2, out wstring p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIIDRef do_nsIIDRef (in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIPythonTestInterface do_nsIPythonTestInterface (in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsISupports do_nsISupports (in nsISupports p1, inout nsISupports p2, out nsISupports p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void do_nsISupportsIs (in nsIIDRef iid, [iid_is (iid), retval] out nsQIResult result); */
+NS_IMETHODIMP nsPythonTestInterface::Do_nsISupportsIs(const nsIID & iid, void * *result)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* End of implementation class template. */
+#endif
+
+
+/* starting interface:    nsIPythonTestInterfaceExtra */
+#define NS_IPYTHONTESTINTERFACEEXTRA_IID_STR "b38d1538-fe92-42c3-831f-285242edeea4"
+
+#define NS_IPYTHONTESTINTERFACEEXTRA_IID \
+  {0xb38d1538, 0xfe92, 0x42c3, \
+    { 0x83, 0x1f, 0x28, 0x52, 0x42, 0xed, 0xee, 0xa4 }}
+
+class NS_NO_VTABLE nsIPythonTestInterfaceExtra : public nsIPythonTestInterface {
+ public: 
+
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPYTHONTESTINTERFACEEXTRA_IID)
+
+  /* void MultiplyEachItemInIntegerArray (in PRInt32 val, in PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */
+  NS_IMETHOD MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray) = 0;
+
+  /* void MultiplyEachItemInIntegerArrayAndAppend (in PRInt32 val, inout PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */
+  NS_IMETHOD MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray) = 0;
+
+  /* void CompareStringArrays ([array, size_is (count)] in string arr1, [array, size_is (count)] in string arr2, in unsigned long count, [retval] out short result); */
+  NS_IMETHOD CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result) = 0;
+
+  /* void DoubleStringArray (inout PRUint32 count, [array, size_is (count)] inout string valueArray); */
+  NS_IMETHOD DoubleStringArray(PRUint32 *count, char ***valueArray) = 0;
+
+  /* void ReverseStringArray (in PRUint32 count, [array, size_is (count)] inout string valueArray); */
+  NS_IMETHOD ReverseStringArray(PRUint32 count, char ***valueArray) = 0;
+
+  /* void DoubleString (inout PRUint32 count, [size_is (count)] inout string str); */
+  NS_IMETHOD DoubleString(PRUint32 *count, char **str) = 0;
+
+  /* void DoubleString2 (in PRUint32 in_count, [size_is (in_count)] in string in_str, out PRUint32 out_count, [size_is (out_count)] out string out_str); */
+  NS_IMETHOD DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) = 0;
+
+  /* void DoubleString3 (in PRUint32 in_count, [size_is (in_count)] in string in_str, out PRUint32 out_count, [size_is (out_count), retval] out string out_str); */
+  NS_IMETHOD DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) = 0;
+
+  /* void DoubleString4 ([size_is (count)] in string in_str, inout PRUint32 count, [size_is (count)] out string out_str); */
+  NS_IMETHOD DoubleString4(const char *in_str, PRUint32 *count, char **out_str) = 0;
+
+  /* void UpString (in PRUint32 count, [size_is (count)] inout string str); */
+  NS_IMETHOD UpString(PRUint32 count, char **str) = 0;
+
+  /* void UpString2 (in PRUint32 count, [size_is (count)] in string in_str, [size_is (count)] out string out_str); */
+  NS_IMETHOD UpString2(PRUint32 count, const char *in_str, char **out_str) = 0;
+
+  /* void CopyUTF8String (in AUTF8String in_str, out AUTF8String out_str); */
+  NS_IMETHOD CopyUTF8String(const nsACString & in_str, nsACString & out_str) = 0;
+
+  /* void CopyUTF8String2 (in AUTF8String in_str, out AUTF8String out_str); */
+  NS_IMETHOD CopyUTF8String2(const nsACString & in_str, nsACString & out_str) = 0;
+
+  /* void GetFixedString (in PRUint32 count, [size_is (count)] out string out_str); */
+  NS_IMETHOD GetFixedString(PRUint32 count, char **out_str) = 0;
+
+  /* void DoubleWideString (inout PRUint32 count, [size_is (count)] inout wstring str); */
+  NS_IMETHOD DoubleWideString(PRUint32 *count, PRUnichar **str) = 0;
+
+  /* void DoubleWideString2 (in PRUint32 in_count, [size_is (in_count)] in wstring in_str, out PRUint32 out_count, [size_is (out_count)] out wstring out_str); */
+  NS_IMETHOD DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) = 0;
+
+  /* void DoubleWideString3 (in PRUint32 in_count, [size_is (in_count)] in wstring in_str, out PRUint32 out_count, [size_is (out_count), retval] out wstring out_str); */
+  NS_IMETHOD DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) = 0;
+
+  /* void DoubleWideString4 ([size_is (count)] in wstring in_str, inout PRUint32 count, [size_is (count)] out wstring out_str); */
+  NS_IMETHOD DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str) = 0;
+
+  /* void UpWideString (in PRUint32 count, [size_is (count)] inout wstring str); */
+  NS_IMETHOD UpWideString(PRUint32 count, PRUnichar **str) = 0;
+
+  /* void UpWideString2 (in PRUint32 count, [size_is (count)] in wstring in_str, [size_is (count)] out wstring out_str); */
+  NS_IMETHOD UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str) = 0;
+
+  /* void GetFixedWideString (in PRUint32 count, [size_is (count)] out string out_str); */
+  NS_IMETHOD GetFixedWideString(PRUint32 count, char **out_str) = 0;
+
+  /* void GetStrings (out PRUint32 count, [array, size_is (count), retval] out string str); */
+  NS_IMETHOD GetStrings(PRUint32 *count, char ***str) = 0;
+
+  /* void UpOctetArray (inout PRUint32 count, [array, size_is (count)] inout PRUint8 data); */
+  NS_IMETHOD UpOctetArray(PRUint32 *count, PRUint8 **data) = 0;
+
+  /* void UpOctetArray2 (inout PRUint32 count, [array, size_is (count)] inout PRUint8 data); */
+  NS_IMETHOD UpOctetArray2(PRUint32 *count, PRUint8 **data) = 0;
+
+  /* void CheckInterfaceArray (in PRUint32 count, [array, size_is (count)] in nsISupports data, [retval] out PRBool all_non_null); */
+  NS_IMETHOD CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null) = 0;
+
+  /* void CopyInterfaceArray (in PRUint32 count, [array, size_is (count)] in nsISupports data, [array, size_is (out_count)] out nsISupports out_data, out PRUint32 out_count); */
+  NS_IMETHOD CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count) = 0;
+
+  /* void GetInterfaceArray (out PRUint32 count, [array, size_is (count)] out nsISupports data); */
+  NS_IMETHOD GetInterfaceArray(PRUint32 *count, nsISupports ***data) = 0;
+
+  /* void ExtendInterfaceArray (inout PRUint32 count, [array, size_is (count)] inout nsISupports data); */
+  NS_IMETHOD ExtendInterfaceArray(PRUint32 *count, nsISupports ***data) = 0;
+
+  /* void CheckIIDArray (in PRUint32 count, [array, size_is (count)] in nsIIDRef data, [retval] out PRBool all_mine); */
+  NS_IMETHOD CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine) = 0;
+
+  /* void GetIIDArray (out PRUint32 count, [array, size_is (count)] out nsIIDRef data); */
+  NS_IMETHOD GetIIDArray(PRUint32 *count, nsIID & **data) = 0;
+
+  /* void ExtendIIDArray (inout PRUint32 count, [array, size_is (count)] inout nsIIDRef data); */
+  NS_IMETHOD ExtendIIDArray(PRUint32 *count, nsIID & **data) = 0;
+
+  /* void SumArrays (in PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] in PRInt32 array2, [retval] out PRInt32 result); */
+  NS_IMETHOD SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result) = 0;
+
+  /* void GetArrays (out PRUint32 count, [array, size_is (count)] out PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */
+  NS_IMETHOD GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2) = 0;
+
+  /* void GetFixedArray (in PRUint32 count, [array, size_is (count)] out PRInt32 array1); */
+  NS_IMETHOD GetFixedArray(PRUint32 count, PRInt32 **array1) = 0;
+
+  /* void CopyArray (in PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */
+  NS_IMETHOD CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2) = 0;
+
+  /* void CopyAndDoubleArray (inout PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */
+  NS_IMETHOD CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) = 0;
+
+  /* void AppendArray (inout PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] inout PRInt32 array2); */
+  NS_IMETHOD AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) = 0;
+
+  /* void AppendVariant (in nsIVariant variant, inout nsIVariant result); */
+  NS_IMETHOD AppendVariant(nsIVariant *variant, nsIVariant **result) = 0;
+
+  /* nsIVariant CopyVariant (in nsIVariant variant); */
+  NS_IMETHOD CopyVariant(nsIVariant *variant, nsIVariant **_retval) = 0;
+
+  /* nsIVariant SumVariants (in PRUint32 incount, [array, size_is (incount)] in nsIVariant variants); */
+  NS_IMETHOD SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval) = 0;
+
+};
+
+/* Use this macro when declaring classes that implement this interface. */
+#define NS_DECL_NSIPYTHONTESTINTERFACEEXTRA \
+  NS_IMETHOD MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray); \
+  NS_IMETHOD MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray); \
+  NS_IMETHOD CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result); \
+  NS_IMETHOD DoubleStringArray(PRUint32 *count, char ***valueArray); \
+  NS_IMETHOD ReverseStringArray(PRUint32 count, char ***valueArray); \
+  NS_IMETHOD DoubleString(PRUint32 *count, char **str); \
+  NS_IMETHOD DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str); \
+  NS_IMETHOD DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str); \
+  NS_IMETHOD DoubleString4(const char *in_str, PRUint32 *count, char **out_str); \
+  NS_IMETHOD UpString(PRUint32 count, char **str); \
+  NS_IMETHOD UpString2(PRUint32 count, const char *in_str, char **out_str); \
+  NS_IMETHOD CopyUTF8String(const nsACString & in_str, nsACString & out_str); \
+  NS_IMETHOD CopyUTF8String2(const nsACString & in_str, nsACString & out_str); \
+  NS_IMETHOD GetFixedString(PRUint32 count, char **out_str); \
+  NS_IMETHOD DoubleWideString(PRUint32 *count, PRUnichar **str); \
+  NS_IMETHOD DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str); \
+  NS_IMETHOD DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str); \
+  NS_IMETHOD DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str); \
+  NS_IMETHOD UpWideString(PRUint32 count, PRUnichar **str); \
+  NS_IMETHOD UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str); \
+  NS_IMETHOD GetFixedWideString(PRUint32 count, char **out_str); \
+  NS_IMETHOD GetStrings(PRUint32 *count, char ***str); \
+  NS_IMETHOD UpOctetArray(PRUint32 *count, PRUint8 **data); \
+  NS_IMETHOD UpOctetArray2(PRUint32 *count, PRUint8 **data); \
+  NS_IMETHOD CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null); \
+  NS_IMETHOD CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count); \
+  NS_IMETHOD GetInterfaceArray(PRUint32 *count, nsISupports ***data); \
+  NS_IMETHOD ExtendInterfaceArray(PRUint32 *count, nsISupports ***data); \
+  NS_IMETHOD CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine); \
+  NS_IMETHOD GetIIDArray(PRUint32 *count, nsIID & **data); \
+  NS_IMETHOD ExtendIIDArray(PRUint32 *count, nsIID & **data); \
+  NS_IMETHOD SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result); \
+  NS_IMETHOD GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2); \
+  NS_IMETHOD GetFixedArray(PRUint32 count, PRInt32 **array1); \
+  NS_IMETHOD CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2); \
+  NS_IMETHOD CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2); \
+  NS_IMETHOD AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2); \
+  NS_IMETHOD AppendVariant(nsIVariant *variant, nsIVariant **result); \
+  NS_IMETHOD CopyVariant(nsIVariant *variant, nsIVariant **_retval); \
+  NS_IMETHOD SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval); 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */
+#define NS_FORWARD_NSIPYTHONTESTINTERFACEEXTRA(_to) \
+  NS_IMETHOD MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray) { return _to MultiplyEachItemInIntegerArray(val, count, valueArray); } \
+  NS_IMETHOD MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray) { return _to MultiplyEachItemInIntegerArrayAndAppend(val, count, valueArray); } \
+  NS_IMETHOD CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result) { return _to CompareStringArrays(arr1, arr2, count, result); } \
+  NS_IMETHOD DoubleStringArray(PRUint32 *count, char ***valueArray) { return _to DoubleStringArray(count, valueArray); } \
+  NS_IMETHOD ReverseStringArray(PRUint32 count, char ***valueArray) { return _to ReverseStringArray(count, valueArray); } \
+  NS_IMETHOD DoubleString(PRUint32 *count, char **str) { return _to DoubleString(count, str); } \
+  NS_IMETHOD DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) { return _to DoubleString2(in_count, in_str, out_count, out_str); } \
+  NS_IMETHOD DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) { return _to DoubleString3(in_count, in_str, out_count, out_str); } \
+  NS_IMETHOD DoubleString4(const char *in_str, PRUint32 *count, char **out_str) { return _to DoubleString4(in_str, count, out_str); } \
+  NS_IMETHOD UpString(PRUint32 count, char **str) { return _to UpString(count, str); } \
+  NS_IMETHOD UpString2(PRUint32 count, const char *in_str, char **out_str) { return _to UpString2(count, in_str, out_str); } \
+  NS_IMETHOD CopyUTF8String(const nsACString & in_str, nsACString & out_str) { return _to CopyUTF8String(in_str, out_str); } \
+  NS_IMETHOD CopyUTF8String2(const nsACString & in_str, nsACString & out_str) { return _to CopyUTF8String2(in_str, out_str); } \
+  NS_IMETHOD GetFixedString(PRUint32 count, char **out_str) { return _to GetFixedString(count, out_str); } \
+  NS_IMETHOD DoubleWideString(PRUint32 *count, PRUnichar **str) { return _to DoubleWideString(count, str); } \
+  NS_IMETHOD DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) { return _to DoubleWideString2(in_count, in_str, out_count, out_str); } \
+  NS_IMETHOD DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) { return _to DoubleWideString3(in_count, in_str, out_count, out_str); } \
+  NS_IMETHOD DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str) { return _to DoubleWideString4(in_str, count, out_str); } \
+  NS_IMETHOD UpWideString(PRUint32 count, PRUnichar **str) { return _to UpWideString(count, str); } \
+  NS_IMETHOD UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str) { return _to UpWideString2(count, in_str, out_str); } \
+  NS_IMETHOD GetFixedWideString(PRUint32 count, char **out_str) { return _to GetFixedWideString(count, out_str); } \
+  NS_IMETHOD GetStrings(PRUint32 *count, char ***str) { return _to GetStrings(count, str); } \
+  NS_IMETHOD UpOctetArray(PRUint32 *count, PRUint8 **data) { return _to UpOctetArray(count, data); } \
+  NS_IMETHOD UpOctetArray2(PRUint32 *count, PRUint8 **data) { return _to UpOctetArray2(count, data); } \
+  NS_IMETHOD CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null) { return _to CheckInterfaceArray(count, data, all_non_null); } \
+  NS_IMETHOD CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count) { return _to CopyInterfaceArray(count, data, out_data, out_count); } \
+  NS_IMETHOD GetInterfaceArray(PRUint32 *count, nsISupports ***data) { return _to GetInterfaceArray(count, data); } \
+  NS_IMETHOD ExtendInterfaceArray(PRUint32 *count, nsISupports ***data) { return _to ExtendInterfaceArray(count, data); } \
+  NS_IMETHOD CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine) { return _to CheckIIDArray(count, data, all_mine); } \
+  NS_IMETHOD GetIIDArray(PRUint32 *count, nsIID & **data) { return _to GetIIDArray(count, data); } \
+  NS_IMETHOD ExtendIIDArray(PRUint32 *count, nsIID & **data) { return _to ExtendIIDArray(count, data); } \
+  NS_IMETHOD SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result) { return _to SumArrays(count, array1, array2, result); } \
+  NS_IMETHOD GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2) { return _to GetArrays(count, array1, array2); } \
+  NS_IMETHOD GetFixedArray(PRUint32 count, PRInt32 **array1) { return _to GetFixedArray(count, array1); } \
+  NS_IMETHOD CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2) { return _to CopyArray(count, array1, array2); } \
+  NS_IMETHOD CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) { return _to CopyAndDoubleArray(count, array1, array2); } \
+  NS_IMETHOD AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) { return _to AppendArray(count, array1, array2); } \
+  NS_IMETHOD AppendVariant(nsIVariant *variant, nsIVariant **result) { return _to AppendVariant(variant, result); } \
+  NS_IMETHOD CopyVariant(nsIVariant *variant, nsIVariant **_retval) { return _to CopyVariant(variant, _retval); } \
+  NS_IMETHOD SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval) { return _to SumVariants(incount, variants, _retval); } 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
+#define NS_FORWARD_SAFE_NSIPYTHONTESTINTERFACEEXTRA(_to) \
+  NS_IMETHOD MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray) { return !_to ? NS_ERROR_NULL_POINTER : _to->MultiplyEachItemInIntegerArray(val, count, valueArray); } \
+  NS_IMETHOD MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray) { return !_to ? NS_ERROR_NULL_POINTER : _to->MultiplyEachItemInIntegerArrayAndAppend(val, count, valueArray); } \
+  NS_IMETHOD CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result) { return !_to ? NS_ERROR_NULL_POINTER : _to->CompareStringArrays(arr1, arr2, count, result); } \
+  NS_IMETHOD DoubleStringArray(PRUint32 *count, char ***valueArray) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleStringArray(count, valueArray); } \
+  NS_IMETHOD ReverseStringArray(PRUint32 count, char ***valueArray) { return !_to ? NS_ERROR_NULL_POINTER : _to->ReverseStringArray(count, valueArray); } \
+  NS_IMETHOD DoubleString(PRUint32 *count, char **str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleString(count, str); } \
+  NS_IMETHOD DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleString2(in_count, in_str, out_count, out_str); } \
+  NS_IMETHOD DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleString3(in_count, in_str, out_count, out_str); } \
+  NS_IMETHOD DoubleString4(const char *in_str, PRUint32 *count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleString4(in_str, count, out_str); } \
+  NS_IMETHOD UpString(PRUint32 count, char **str) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpString(count, str); } \
+  NS_IMETHOD UpString2(PRUint32 count, const char *in_str, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpString2(count, in_str, out_str); } \
+  NS_IMETHOD CopyUTF8String(const nsACString & in_str, nsACString & out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyUTF8String(in_str, out_str); } \
+  NS_IMETHOD CopyUTF8String2(const nsACString & in_str, nsACString & out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyUTF8String2(in_str, out_str); } \
+  NS_IMETHOD GetFixedString(PRUint32 count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetFixedString(count, out_str); } \
+  NS_IMETHOD DoubleWideString(PRUint32 *count, PRUnichar **str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleWideString(count, str); } \
+  NS_IMETHOD DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleWideString2(in_count, in_str, out_count, out_str); } \
+  NS_IMETHOD DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleWideString3(in_count, in_str, out_count, out_str); } \
+  NS_IMETHOD DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleWideString4(in_str, count, out_str); } \
+  NS_IMETHOD UpWideString(PRUint32 count, PRUnichar **str) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpWideString(count, str); } \
+  NS_IMETHOD UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpWideString2(count, in_str, out_str); } \
+  NS_IMETHOD GetFixedWideString(PRUint32 count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetFixedWideString(count, out_str); } \
+  NS_IMETHOD GetStrings(PRUint32 *count, char ***str) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetStrings(count, str); } \
+  NS_IMETHOD UpOctetArray(PRUint32 *count, PRUint8 **data) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpOctetArray(count, data); } \
+  NS_IMETHOD UpOctetArray2(PRUint32 *count, PRUint8 **data) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpOctetArray2(count, data); } \
+  NS_IMETHOD CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null) { return !_to ? NS_ERROR_NULL_POINTER : _to->CheckInterfaceArray(count, data, all_non_null); } \
+  NS_IMETHOD CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyInterfaceArray(count, data, out_data, out_count); } \
+  NS_IMETHOD GetInterfaceArray(PRUint32 *count, nsISupports ***data) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetInterfaceArray(count, data); } \
+  NS_IMETHOD ExtendInterfaceArray(PRUint32 *count, nsISupports ***data) { return !_to ? NS_ERROR_NULL_POINTER : _to->ExtendInterfaceArray(count, data); } \
+  NS_IMETHOD CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine) { return !_to ? NS_ERROR_NULL_POINTER : _to->CheckIIDArray(count, data, all_mine); } \
+  NS_IMETHOD GetIIDArray(PRUint32 *count, nsIID & **data) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetIIDArray(count, data); } \
+  NS_IMETHOD ExtendIIDArray(PRUint32 *count, nsIID & **data) { return !_to ? NS_ERROR_NULL_POINTER : _to->ExtendIIDArray(count, data); } \
+  NS_IMETHOD SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result) { return !_to ? NS_ERROR_NULL_POINTER : _to->SumArrays(count, array1, array2, result); } \
+  NS_IMETHOD GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetArrays(count, array1, array2); } \
+  NS_IMETHOD GetFixedArray(PRUint32 count, PRInt32 **array1) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetFixedArray(count, array1); } \
+  NS_IMETHOD CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyArray(count, array1, array2); } \
+  NS_IMETHOD CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyAndDoubleArray(count, array1, array2); } \
+  NS_IMETHOD AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) { return !_to ? NS_ERROR_NULL_POINTER : _to->AppendArray(count, array1, array2); } \
+  NS_IMETHOD AppendVariant(nsIVariant *variant, nsIVariant **result) { return !_to ? NS_ERROR_NULL_POINTER : _to->AppendVariant(variant, result); } \
+  NS_IMETHOD CopyVariant(nsIVariant *variant, nsIVariant **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyVariant(variant, _retval); } \
+  NS_IMETHOD SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->SumVariants(incount, variants, _retval); } 
+
+#if 0
+/* Use the code below as a template for the implementation class for this interface. */
+
+/* Header file */
+class nsPythonTestInterfaceExtra : public nsIPythonTestInterfaceExtra
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPYTHONTESTINTERFACEEXTRA
+
+  nsPythonTestInterfaceExtra();
+
+private:
+  ~nsPythonTestInterfaceExtra();
+
+protected:
+  /* additional members */
+};
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(nsPythonTestInterfaceExtra, nsIPythonTestInterfaceExtra)
+
+nsPythonTestInterfaceExtra::nsPythonTestInterfaceExtra()
+{
+  /* member initializers and constructor code */
+}
+
+nsPythonTestInterfaceExtra::~nsPythonTestInterfaceExtra()
+{
+  /* destructor code */
+}
+
+/* void MultiplyEachItemInIntegerArray (in PRInt32 val, in PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void MultiplyEachItemInIntegerArrayAndAppend (in PRInt32 val, inout PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CompareStringArrays ([array, size_is (count)] in string arr1, [array, size_is (count)] in string arr2, in unsigned long count, [retval] out short result); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleStringArray (inout PRUint32 count, [array, size_is (count)] inout string valueArray); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleStringArray(PRUint32 *count, char ***valueArray)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void ReverseStringArray (in PRUint32 count, [array, size_is (count)] inout string valueArray); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::ReverseStringArray(PRUint32 count, char ***valueArray)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleString (inout PRUint32 count, [size_is (count)] inout string str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleString(PRUint32 *count, char **str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleString2 (in PRUint32 in_count, [size_is (in_count)] in string in_str, out PRUint32 out_count, [size_is (out_count)] out string out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleString3 (in PRUint32 in_count, [size_is (in_count)] in string in_str, out PRUint32 out_count, [size_is (out_count), retval] out string out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleString4 ([size_is (count)] in string in_str, inout PRUint32 count, [size_is (count)] out string out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleString4(const char *in_str, PRUint32 *count, char **out_str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void UpString (in PRUint32 count, [size_is (count)] inout string str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::UpString(PRUint32 count, char **str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void UpString2 (in PRUint32 count, [size_is (count)] in string in_str, [size_is (count)] out string out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::UpString2(PRUint32 count, const char *in_str, char **out_str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CopyUTF8String (in AUTF8String in_str, out AUTF8String out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyUTF8String(const nsACString & in_str, nsACString & out_str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CopyUTF8String2 (in AUTF8String in_str, out AUTF8String out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyUTF8String2(const nsACString & in_str, nsACString & out_str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetFixedString (in PRUint32 count, [size_is (count)] out string out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetFixedString(PRUint32 count, char **out_str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleWideString (inout PRUint32 count, [size_is (count)] inout wstring str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleWideString(PRUint32 *count, PRUnichar **str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleWideString2 (in PRUint32 in_count, [size_is (in_count)] in wstring in_str, out PRUint32 out_count, [size_is (out_count)] out wstring out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleWideString3 (in PRUint32 in_count, [size_is (in_count)] in wstring in_str, out PRUint32 out_count, [size_is (out_count), retval] out wstring out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleWideString4 ([size_is (count)] in wstring in_str, inout PRUint32 count, [size_is (count)] out wstring out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void UpWideString (in PRUint32 count, [size_is (count)] inout wstring str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::UpWideString(PRUint32 count, PRUnichar **str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void UpWideString2 (in PRUint32 count, [size_is (count)] in wstring in_str, [size_is (count)] out wstring out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetFixedWideString (in PRUint32 count, [size_is (count)] out string out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetFixedWideString(PRUint32 count, char **out_str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetStrings (out PRUint32 count, [array, size_is (count), retval] out string str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetStrings(PRUint32 *count, char ***str)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void UpOctetArray (inout PRUint32 count, [array, size_is (count)] inout PRUint8 data); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::UpOctetArray(PRUint32 *count, PRUint8 **data)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void UpOctetArray2 (inout PRUint32 count, [array, size_is (count)] inout PRUint8 data); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::UpOctetArray2(PRUint32 *count, PRUint8 **data)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CheckInterfaceArray (in PRUint32 count, [array, size_is (count)] in nsISupports data, [retval] out PRBool all_non_null); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CopyInterfaceArray (in PRUint32 count, [array, size_is (count)] in nsISupports data, [array, size_is (out_count)] out nsISupports out_data, out PRUint32 out_count); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetInterfaceArray (out PRUint32 count, [array, size_is (count)] out nsISupports data); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetInterfaceArray(PRUint32 *count, nsISupports ***data)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void ExtendInterfaceArray (inout PRUint32 count, [array, size_is (count)] inout nsISupports data); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::ExtendInterfaceArray(PRUint32 *count, nsISupports ***data)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CheckIIDArray (in PRUint32 count, [array, size_is (count)] in nsIIDRef data, [retval] out PRBool all_mine); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetIIDArray (out PRUint32 count, [array, size_is (count)] out nsIIDRef data); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetIIDArray(PRUint32 *count, nsIID & **data)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void ExtendIIDArray (inout PRUint32 count, [array, size_is (count)] inout nsIIDRef data); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::ExtendIIDArray(PRUint32 *count, nsIID & **data)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void SumArrays (in PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] in PRInt32 array2, [retval] out PRInt32 result); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetArrays (out PRUint32 count, [array, size_is (count)] out PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetFixedArray (in PRUint32 count, [array, size_is (count)] out PRInt32 array1); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetFixedArray(PRUint32 count, PRInt32 **array1)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CopyArray (in PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CopyAndDoubleArray (inout PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void AppendArray (inout PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] inout PRInt32 array2); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void AppendVariant (in nsIVariant variant, inout nsIVariant result); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::AppendVariant(nsIVariant *variant, nsIVariant **result)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIVariant CopyVariant (in nsIVariant variant); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyVariant(nsIVariant *variant, nsIVariant **_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIVariant SumVariants (in PRUint32 incount, [array, size_is (incount)] in nsIVariant variants); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* End of implementation class template. */
+#endif
+
+
+/* starting interface:    nsIPythonTestInterfaceDOMStrings */
+#define NS_IPYTHONTESTINTERFACEDOMSTRINGS_IID_STR "657ae651-a973-4818-8c06-f4b948b3d758"
+
+#define NS_IPYTHONTESTINTERFACEDOMSTRINGS_IID \
+  {0x657ae651, 0xa973, 0x4818, \
+    { 0x8c, 0x06, 0xf4, 0xb9, 0x48, 0xb3, 0xd7, 0x58 }}
+
+class NS_NO_VTABLE nsIPythonTestInterfaceDOMStrings : public nsIPythonTestInterfaceExtra {
+ public: 
+
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPYTHONTESTINTERFACEDOMSTRINGS_IID)
+
+  /* DOMString GetDOMStringResult (in PRInt32 length); */
+  NS_IMETHOD GetDOMStringResult(PRInt32 length, nsAString & _retval) = 0;
+
+  /* void GetDOMStringOut (in PRInt32 length, [retval] out DOMString s); */
+  NS_IMETHOD GetDOMStringOut(PRInt32 length, nsAString & s) = 0;
+
+  /* PRUint32 GetDOMStringLength (in DOMString s); */
+  NS_IMETHOD GetDOMStringLength(const nsAString & s, PRUint32 *_retval) = 0;
+
+  /* PRUint32 GetDOMStringRefLength (in DOMStringRef s); */
+  NS_IMETHOD GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval) = 0;
+
+  /* PRUint32 GetDOMStringPtrLength (in DOMStringPtr s); */
+  NS_IMETHOD GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval) = 0;
+
+  /* void ConcatDOMStrings (in DOMString s1, in DOMString s2, out DOMString ret); */
+  NS_IMETHOD ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret) = 0;
+
+  /* attribute DOMString domstring_value; */
+  NS_IMETHOD GetDomstring_value(nsAString & aDomstring_value) = 0;
+  NS_IMETHOD SetDomstring_value(const nsAString & aDomstring_value) = 0;
+
+  /* readonly attribute DOMString domstring_value_ro; */
+  NS_IMETHOD GetDomstring_value_ro(nsAString & aDomstring_value_ro) = 0;
+
+};
+
+/* Use this macro when declaring classes that implement this interface. */
+#define NS_DECL_NSIPYTHONTESTINTERFACEDOMSTRINGS \
+  NS_IMETHOD GetDOMStringResult(PRInt32 length, nsAString & _retval); \
+  NS_IMETHOD GetDOMStringOut(PRInt32 length, nsAString & s); \
+  NS_IMETHOD GetDOMStringLength(const nsAString & s, PRUint32 *_retval); \
+  NS_IMETHOD GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval); \
+  NS_IMETHOD GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval); \
+  NS_IMETHOD ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret); \
+  NS_IMETHOD GetDomstring_value(nsAString & aDomstring_value); \
+  NS_IMETHOD SetDomstring_value(const nsAString & aDomstring_value); \
+  NS_IMETHOD GetDomstring_value_ro(nsAString & aDomstring_value_ro); 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */
+#define NS_FORWARD_NSIPYTHONTESTINTERFACEDOMSTRINGS(_to) \
+  NS_IMETHOD GetDOMStringResult(PRInt32 length, nsAString & _retval) { return _to GetDOMStringResult(length, _retval); } \
+  NS_IMETHOD GetDOMStringOut(PRInt32 length, nsAString & s) { return _to GetDOMStringOut(length, s); } \
+  NS_IMETHOD GetDOMStringLength(const nsAString & s, PRUint32 *_retval) { return _to GetDOMStringLength(s, _retval); } \
+  NS_IMETHOD GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval) { return _to GetDOMStringRefLength(s, _retval); } \
+  NS_IMETHOD GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval) { return _to GetDOMStringPtrLength(s, _retval); } \
+  NS_IMETHOD ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret) { return _to ConcatDOMStrings(s1, s2, ret); } \
+  NS_IMETHOD GetDomstring_value(nsAString & aDomstring_value) { return _to GetDomstring_value(aDomstring_value); } \
+  NS_IMETHOD SetDomstring_value(const nsAString & aDomstring_value) { return _to SetDomstring_value(aDomstring_value); } \
+  NS_IMETHOD GetDomstring_value_ro(nsAString & aDomstring_value_ro) { return _to GetDomstring_value_ro(aDomstring_value_ro); } 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
+#define NS_FORWARD_SAFE_NSIPYTHONTESTINTERFACEDOMSTRINGS(_to) \
+  NS_IMETHOD GetDOMStringResult(PRInt32 length, nsAString & _retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringResult(length, _retval); } \
+  NS_IMETHOD GetDOMStringOut(PRInt32 length, nsAString & s) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringOut(length, s); } \
+  NS_IMETHOD GetDOMStringLength(const nsAString & s, PRUint32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringLength(s, _retval); } \
+  NS_IMETHOD GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringRefLength(s, _retval); } \
+  NS_IMETHOD GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringPtrLength(s, _retval); } \
+  NS_IMETHOD ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret) { return !_to ? NS_ERROR_NULL_POINTER : _to->ConcatDOMStrings(s1, s2, ret); } \
+  NS_IMETHOD GetDomstring_value(nsAString & aDomstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDomstring_value(aDomstring_value); } \
+  NS_IMETHOD SetDomstring_value(const nsAString & aDomstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetDomstring_value(aDomstring_value); } \
+  NS_IMETHOD GetDomstring_value_ro(nsAString & aDomstring_value_ro) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDomstring_value_ro(aDomstring_value_ro); } 
+
+#if 0
+/* Use the code below as a template for the implementation class for this interface. */
+
+/* Header file */
+class nsPythonTestInterfaceDOMStrings : public nsIPythonTestInterfaceDOMStrings
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPYTHONTESTINTERFACEDOMSTRINGS
+
+  nsPythonTestInterfaceDOMStrings();
+
+private:
+  ~nsPythonTestInterfaceDOMStrings();
+
+protected:
+  /* additional members */
+};
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(nsPythonTestInterfaceDOMStrings, nsIPythonTestInterfaceDOMStrings)
+
+nsPythonTestInterfaceDOMStrings::nsPythonTestInterfaceDOMStrings()
+{
+  /* member initializers and constructor code */
+}
+
+nsPythonTestInterfaceDOMStrings::~nsPythonTestInterfaceDOMStrings()
+{
+  /* destructor code */
+}
+
+/* DOMString GetDOMStringResult (in PRInt32 length); */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringResult(PRInt32 length, nsAString & _retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetDOMStringOut (in PRInt32 length, [retval] out DOMString s); */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringOut(PRInt32 length, nsAString & s)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* PRUint32 GetDOMStringLength (in DOMString s); */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringLength(const nsAString & s, PRUint32 *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* PRUint32 GetDOMStringRefLength (in DOMStringRef s); */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* PRUint32 GetDOMStringPtrLength (in DOMStringPtr s); */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void ConcatDOMStrings (in DOMString s1, in DOMString s2, out DOMString ret); */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute DOMString domstring_value; */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDomstring_value(nsAString & aDomstring_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::SetDomstring_value(const nsAString & aDomstring_value)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* readonly attribute DOMString domstring_value_ro; */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDomstring_value_ro(nsAString & aDomstring_value_ro)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* End of implementation class template. */
+#endif
+
+
+#endif /* __gen_py_test_component_h__ */
Index: trunk/src/libs/xpcom18a4/python/test/test_component/py_test_component.html
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_component/py_test_component.html	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_component/py_test_component.html	(revision 11746)
@@ -0,0 +1,182 @@
+<!-- ***** 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 ***** -->
+
+<center><b><font size=+2>Python Component Sample</font></b>
+
+<p>
+<br>
+Last modified 
+<script>
+document.write(document.lastModified);
+</script>
+</center>
+
+<p>XPConnect allows JavaScript
+to transparantly access and manipulate XPCOM objects;
+
+<p>Big Deal, I hear you say!  But it also works for Python!!!
+
+<p>
+This sample demonstrates accessing a XPCOM object through XPConnect.
+The JavaScript executed when this page loads creates an instance
+of the Python object by
+using the <tt>Components</tt> object, then accesses it through
+the <a href="py_test_component.idl">nsISample</a> interface by calling <tt>QueryInterface</tt>:
+<br>
+<pre>
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var sample = Components.classes["component://mozilla/sample/sample-world"].createInstance();
+sample = sample.QueryInterface(Components.interfaces.nsISample);
+</pre>
+
+<p>
+The buttons on the form are connected to JavaScript event handlers which
+call the methods defined in Python
+
+
+<p><b><a name="Compiling">Compiling the idl</b>
+
+<p>The XPIDL compiler (xpidl on Unix, xpidl.exe on Windows, and a CodeWarrior plugin on Mac)
+is compiled at build time (except on Mac) thus
+you will have to build mozilla in order to test this out. If you
+have already built mozilla then the compiler will be located at <tt>mozilla\dist\WIN32_D.OBJ\bin\xpidl.exe</tt>.
+
+<p>Once you have the XPIDL compiler enter the following command at your
+prompt:
+<br><tt>D:\whereever\xpcom\test\test_component>d:\mozilla\dist\WIN32_D.OBJ\bin\xpidl -I
+d:\mozilla\dist\idl -m typelib py_test_component.idl</tt>.  You must then copy the generated .xpt file
+to the mozilla component directory.
+
+<p>The <tt>-I d:\mozilla\dist\idl</tt> points the compiler to the folder
+containing the other idl files, needed because nsISample.idl inherits from
+nsISupports.idl. The <tt>-m typelib</tt> instruction tells the compiler
+to build the .XPT typelib file.</tt>. 
+
+<p>
+For more information on compilation see the <a href="http://www.mozilla.org/scriptable/xpidl/">xpidl
+compiler page</a>.
+
+<p><b>Running the sample</b>
+<p><b>NOTE: This doesnt work for me - I get an access denied error using XPConnect!</b>
+<p>Using Mozilla, load this file. Pay attention
+to the console when clicking "write".
+
+<!-- XXX keep in sync with stuff in pre tag below -->
+<script>
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var sample = Components.classes["Python.TestComponent"].createInstance();
+sample = sample.QueryInterface(Components.interfaces.nsIPythonTestInterface);
+dump("sample = " + sample + "\n");
+
+function get()
+{
+  var field = document.getElementById('Value');
+  field.value = sample.str_value;
+}
+
+function set()
+{
+  var field = document.getElementById('Value');
+  sample.str_value = field.value;
+}
+
+function poke()
+{
+  var field = document.getElementById('Value');
+  sample.poke(field.value);
+}
+
+function write()
+{
+  sample.writeValue("here is what I'm writing: ");
+}
+</script>
+
+<p>
+<form name="form">
+<input type="button" value="Get" onclick="get();">
+<input type="button" value="Set" onclick="set();">
+<input type="button" value="Poke" onclick="poke();">
+<input type="text" id="Value">
+<input type="button" value="Write" onclick="write();">
+<form>
+
+<hr>
+
+<p>
+JavaScript and form source:
+
+<!-- XXX keep in sync with actual script -->
+<pre>
+&lt;script&gt;
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var sample = Components.classes["component://Python.TestComponent"].createInstance();
+sample = sample.QueryInterface(Components.interfaces.nsIPythonTestInterface);
+dump("sample = " + sample + "\n");
+
+function get()
+{
+  var field = document.getElementById('Value');
+  field.value = sample.str_value;
+}
+
+function set()
+{
+  var field = document.getElementById('Value');
+  sample.str_value = field.value;
+}
+
+function poke()
+{
+  var field = document.getElementById('Value');
+  sample.poke(field.value);
+}
+
+function write()
+{
+  sample.writeValue("here is what I'm writing: ");
+}
+&lt;/script&gt;
+
+&lt;form name=&quot;form&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Get&quot; onclick=&quot;get();&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Set&quot; onclick=&quot;set();&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Poke&quot; onclick=&quot;poke();&quot;&gt;
+&lt;input type=&quot;text&quot; id=&quot;Value&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Write&quot; onclick=&quot;write();&quot;&gt;
+&lt;form>
+
+</pre>
Index: trunk/src/libs/xpcom18a4/python/test/test_component/py_test_component.idl
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_component/py_test_component.idl	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_component/py_test_component.idl	(revision 11746)
@@ -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
+ * 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 ***** */
+
+// NOTE: This is a TEST interface, not a DEMO interface :-)
+// We try to get as many data-types etc exposed, meaning this
+// doesnt really make a good demo of a "simple component"
+#include "nsISupports.idl"
+#include "nsIVariant.idl"
+
+[scriptable, uuid(1ECAED4F-E4D5-4ee7-ABF0-7D72AE1441D7)]
+interface nsIPythonTestInterface : nsISupports
+{
+    // Some constants for us to test - one for every type supported by xpidl
+    const short                 One = 1;
+    const long                  Two = 2;
+    const long                  MinusOne = -1;
+    const long                  BigLong = 0x7FFFFFFF;
+    const long                  BiggerLong = 0xFFFFFFFF;
+    const unsigned long         BigULong = 0xFFFFFFFF;
+
+    // Declare every type supported as an attribute.
+    attribute boolean                   boolean_value; // PRBool
+    attribute octet                     octet_value; // PRUint8
+    attribute short                     short_value; // PRInt16
+    attribute unsigned short            ushort_value; //  PRUint16 
+    attribute long                      long_value; // PRInt32 
+    attribute unsigned long             ulong_value; // PRUint32 
+    attribute long long                 long_long_value; // PRInt64 
+    attribute unsigned long long        ulong_long_value; // PRUint64
+    attribute float                     float_value; // float
+    attribute double                    double_value; // double
+    attribute char                      char_value; // char
+    attribute wchar                     wchar_value; // PRUnichar 
+    attribute string                    string_value; // char *
+    attribute wstring                   wstring_value; // PRUnichar* 
+    attribute AString                   astring_value; // nsAString & 
+    attribute ACString                  acstring_value; // nsACString & 
+    attribute AUTF8String               utf8string_value; // nsAUTF8String & 
+    attribute nsIIDRef                  iid_value; // an IID
+    attribute nsIPythonTestInterface    interface_value; // A specific interface
+    attribute nsISupports               isupports_value; // A generic interface
+
+    // Declare every type supported as a method with an "in", "in/out" and "out" params
+    boolean                  do_boolean(in boolean p1, inout boolean p2, out boolean p3);
+    octet                    do_octet(in octet p1, inout octet p2, out octet p3);
+    short                    do_short(in short p1, inout short p2, out short p3);
+    unsigned short           do_unsigned_short(in unsigned short p1, inout unsigned short p2, out unsigned short p3);
+    long                     do_long(in long p1, inout long p2, out long p3);
+    unsigned long            do_unsigned_long(in unsigned long p1, inout unsigned long p2, out unsigned long p3);
+    long long                do_long_long(in long long p1, inout long long p2, out long long p3);
+    unsigned long long       do_unsigned_long_long(in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3);
+    float                    do_float(in float p1, inout float p2, out float p3);
+    double                   do_double(in double p1, inout double p2, out double p3);
+    char                     do_char(in char p1, inout char p2, out char p3);
+    wchar                    do_wchar(in wchar p1, inout wchar p2, out wchar p3);
+    string                   do_string(in string p1, inout string p2, out string p3);
+    wstring                  do_wstring(in wstring p1, inout wstring p2, out wstring p3);
+    nsIIDRef                 do_nsIIDRef(in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3);
+    nsIPythonTestInterface   do_nsIPythonTestInterface(in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3);
+    nsISupports              do_nsISupports(in nsISupports p1, inout nsISupports p2, out nsISupports p3);
+    void                     do_nsISupportsIs(in nsIIDRef iid, [iid_is(iid),retval] out nsQIResult result);
+// Do I really need these??
+//    void                     do_nsISupportsIs2(inout nsIIDRef iid, [iid_is(iid)] inout nsQIResult result);
+//    void                     do_nsISupportsIs3(out nsIIDRef iid, [iid_is(iid)] inout nsQIResult result);
+//    void                     do_nsISupportsIs4(out nsIIDRef iid, [iid_is(iid)] out nsQIResult result);
+};
+
+// Another interface - we use another interface purely for testing purposes -
+// We ensure that the entire interface hierarcy is available correctly.
+[scriptable, uuid(B38D1538-FE92-42c3-831F-285242EDEEA4)]
+interface nsIPythonTestInterfaceExtra : nsIPythonTestInterface
+{
+    // These were copied from the XPCOM test 'xpctest.idl'
+    // (and a few extras added)
+    void MultiplyEachItemInIntegerArray(
+                           in PRInt32 val, 
+                           in PRUint32 count, 
+                           [array, size_is(count)] inout PRInt32 valueArray);
+    void MultiplyEachItemInIntegerArrayAndAppend(
+                           in PRInt32 val, 
+                           inout PRUint32 count, 
+                           [array, size_is(count)] inout PRInt32 valueArray);
+
+    // Note that this method shares a single "size_is" between 2 params!
+    void CompareStringArrays([array, size_is(count)] in string arr1,
+                 [array, size_is(count)] in string arr2,
+                 in unsigned long count,
+                 [retval] out short result);
+
+    void DoubleStringArray(inout PRUint32 count, 
+                           [array, size_is(count)] inout string valueArray);
+    void ReverseStringArray(in PRUint32 count, 
+                            [array, size_is(count)] inout string valueArray);
+
+    // One count, one inout array.
+    void DoubleString(inout PRUint32 count, 
+                      [size_is(count)] inout string str);
+    // One in count and in array, plus out count and out array
+    void DoubleString2(in PRUint32 in_count, [size_is(in_count)] in string in_str,
+                       out PRUint32 out_count, [size_is(out_count)] out string out_str);
+    // As per DoubleString2, but out string also marked retval
+    void DoubleString3(in PRUint32 in_count, [size_is(in_count)] in string in_str,
+                       out PRUint32 out_count, [size_is(out_count), retval] out string out_str);
+    // One in array, one out array, one share inout count.
+    void DoubleString4([size_is(count)] in string in_str, inout PRUint32 count, [size_is(count)] out string out_str);
+    // UpString defines the count as only "in" - meaning the result must be the same size
+    void UpString(in PRUint32 count, 
+                      [size_is(count)] inout string str);
+    // UpString2 defines count as only "in", and a string as only "out"
+    void UpString2(in PRUint32 count, 
+                      [size_is(count)] in string in_str,
+                      [size_is(count)]out string out_str);
+    void CopyUTF8String(in AUTF8String in_str, out AUTF8String out_str);
+    void CopyUTF8String2(in AUTF8String in_str, out AUTF8String out_str);
+    // Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!)
+    void GetFixedString(in PRUint32 count, [size_is(count)]out string out_str);
+
+    void DoubleWideString(inout PRUint32 count, 
+                      [size_is(count)] inout wstring str);
+    void DoubleWideString2(in PRUint32 in_count, [size_is(in_count)] in wstring in_str,
+                       out PRUint32 out_count, [size_is(out_count)] out wstring out_str);
+    void DoubleWideString3(in PRUint32 in_count, [size_is(in_count)] in wstring in_str,
+                       out PRUint32 out_count, [size_is(out_count), retval] out wstring out_str);
+    void DoubleWideString4([size_is(count)] in wstring in_str, inout PRUint32 count, [size_is(count)] out wstring out_str);
+    // UpWideString defines the count as only "in" - meaning the result must be the same size
+    void UpWideString(in PRUint32 count, 
+                      [size_is(count)] inout wstring str);
+    // UpWideString2 defines count as only "in", and a string as only "out"
+    void UpWideString2(in PRUint32 count, 
+                      [size_is(count)] in wstring in_str,
+                      [size_is(count)]out wstring out_str);
+    // Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!)
+    void GetFixedWideString(in PRUint32 count, [size_is(count)]out string out_str);
+
+    void GetStrings(out PRUint32 count,
+                    [retval, array, size_is(count)] out string str);
+
+    void UpOctetArray(inout PRUint32 count,
+                    [array, size_is(count)] inout PRUint8 data);
+
+    void UpOctetArray2(inout PRUint32 count,
+                    [array, size_is(count)] inout PRUint8 data);
+
+    // Arrays of interfaces
+    void CheckInterfaceArray(in PRUint32 count,
+                             [array, size_is(count)] in nsISupports data,
+                             [retval] out PRBool all_non_null);
+    void CopyInterfaceArray(in PRUint32 count,
+                             [array, size_is(count)] in nsISupports data,
+                             [array, size_is(out_count)] out nsISupports out_data,
+                            out PRUint32 out_count);
+    void GetInterfaceArray(out PRUint32 count,
+                             [array, size_is(count)] out nsISupports data);
+    void ExtendInterfaceArray(inout PRUint32 count,
+                             [array, size_is(count)] inout nsISupports data);
+
+    // Arrays of IIDs
+    void CheckIIDArray(in PRUint32 count,
+                             [array, size_is(count)] in nsIIDRef data,
+                             [retval] out PRBool all_mine);
+    void GetIIDArray(out PRUint32 count,
+                             [array, size_is(count)] out nsIIDRef data);
+    void ExtendIIDArray(inout PRUint32 count,
+                             [array, size_is(count)] inout nsIIDRef data);
+
+    // More specific tests.
+    // Test our count param can be shared as an "in" param.
+    void SumArrays(in PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]in PRInt32 array2, [retval]out PRInt32 result);
+    // Test our count param can be shared as an "out" param.
+    void GetArrays(out PRUint32 count, [array, size_is(count)]out PRInt32 array1, [array, size_is(count)]out PRInt32 array2);
+    // Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!)
+    void GetFixedArray(in PRUint32 count, [array, size_is(count)]out PRInt32 array1);
+    // Test our "in" count param can be shared as one "in", plus one  "out" param.
+    void CopyArray(in PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]out PRInt32 array2);
+    // Test our "in-out" count param can be shared as one "in", plus one  "out" param.
+    void CopyAndDoubleArray(inout PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]out PRInt32 array2);
+    // Test our "in-out" count param can be shared as one "in", plus one  "in-out" param.
+    void AppendArray(inout PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]inout PRInt32 array2);
+    void AppendVariant(in nsIVariant variant, inout nsIVariant result);
+    nsIVariant CopyVariant(in nsIVariant variant);
+    nsIVariant SumVariants(in PRUint32 incount, [array, size_is(incount)]in nsIVariant variants);
+};
+
+// DOM String support is a "recent" (01/2001) addition to XPCOM.  These test 
+// have their own interface for no real good reason ;-)
+[scriptable, uuid(657ae651-a973-4818-8c06-f4b948b3d758)]
+interface nsIPythonTestInterfaceDOMStrings : nsIPythonTestInterfaceExtra
+{
+    DOMString GetDOMStringResult(in PRInt32 length);
+    void GetDOMStringOut(in PRInt32 length, [retval] out DOMString s);
+    PRUint32 GetDOMStringLength(in DOMString s);
+    PRUint32 GetDOMStringRefLength(in DOMStringRef s);
+    PRUint32 GetDOMStringPtrLength(in DOMStringPtr s);
+    void ConcatDOMStrings(in DOMString s1, in DOMString s2, out DOMString ret);
+    attribute DOMString domstring_value;
+    readonly attribute DOMString domstring_value_ro;
+};
Index: trunk/src/libs/xpcom18a4/python/test/test_component/py_test_component.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_component/py_test_component.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_component/py_test_component.py	(revision 11746)
@@ -0,0 +1,421 @@
+# ***** 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, 2001
+# 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 *****
+
+# NOTE: This is a TEST interface, not a DEMO interface :-)
+# We try to get as many data-types etc exposed, meaning this
+# doesnt really make a good demo of a "simple component"
+
+
+from xpcom import components, verbose
+
+class PythonTestComponent:
+    # Note we only list the "child" interface, not our intermediate interfaces
+    # (which we must, by definition, also support)
+    _com_interfaces_ = components.interfaces.nsIPythonTestInterfaceDOMStrings
+    _reg_clsid_ = "{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}"
+    _reg_contractid_ = "Python.TestComponent"
+    def __init__(self):
+        self.boolean_value = 1
+        self.octet_value = 2
+        self.short_value = 3
+        self.ushort_value = 4
+        self.long_value = 5
+        self.ulong_value = 6
+        self.long_long_value = 7
+        self.ulong_long_value = 8
+        self.float_value = 9.0
+        self.double_value = 10.0
+        self.char_value = "a"
+        self.wchar_value = "b"
+        self.string_value = "cee"
+        self.wstring_value = "dee"
+        self.astring_value = "astring"
+        self.acstring_value = "acstring"
+        self.utf8string_value = "utf8string"
+        self.iid_value = self._reg_clsid_
+        self.interface_value = None
+        self.isupports_value = None
+        self.domstring_value = "dom"
+
+    def __del__(self):
+        if verbose:
+            print "Python.TestComponent: __del__ method called - object is destructing"
+
+    def do_boolean(self, p1, p2):
+        # boolean                  do_boolean(in boolean p1, inout boolean p2, out boolean p3);
+        ret = p1 ^ p2
+        return ret, not ret, ret
+
+    def do_octet(self, p1, p2):
+        # octet                    do_octet(in octet p1, inout octet p2, out octet p3);
+        return p1+p2, p1-p2, p1*p2
+
+    def do_short(self, p1, p2):
+        # short                    do_short(in short p1, inout short p2, out short p3);
+        return p1+p2, p1-p2, p1*p2
+
+    def do_unsigned_short(self, p1, p2):
+        # unsigned short           do_unsigned_short(in unsigned short p1, inout unsigned short p2, out unsigned short p3);
+        return p1+p2, p1-p2, p1*p2
+    def do_long(self, p1, p2):
+        # long                     do_long(in long p1, inout long p2, out long p3);
+        return p1+p2, p1-p2, p1*p2
+
+    def do_unsigned_long(self, p1, p2):
+        # unsigned long            do_unsigned_long(in unsigned long p1, inout unsigned long p2, out unsigned long p3);
+        return p1+p2, p1-p2, p1*p2
+    def do_long_long(self, p1, p2):
+        #  long long                do_long_long(in long long p1, inout long long p2, out long long p3);
+        return p1+p2, p1-p2, p1*p2
+    def do_unsigned_long_long(self, p1, p2):
+        # unsigned long long       do_unsigned_long_long(in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3);
+        return p1+p2, p1-p2, p1*p2
+    def do_float(self, p1, p2):
+        # float                    do_float(in float p1, inout float p2, out float p3);
+        return p1+p2, p1-p2, p1*p2
+    def do_double(self, p1, p2):
+        # double                   do_double(in double p1, inout double p2, out double p3);
+        return p1+p2, p1-p2, p1*p2
+    def do_char(self, p1, p2):
+        # char                     do_char(in char p1, inout char p2, out char p3);
+        return chr(ord(p1)+ord(p2)), p2, p1
+    def do_wchar(self, p1, p2):
+        # wchar                    do_wchar(in wchar p1, inout wchar p2, out wchar p3);
+        return chr(ord(p1)+ord(p2)), p2, p1
+    def do_string(self, p1, p2):
+        # string                   do_string(in string p1, inout string p2, out string p3);
+        ret = ""
+        if p1 is not None: ret = ret + p1
+        if p2 is not None: ret = ret + p2
+        return ret, p1, p2
+    def do_wstring(self, p1, p2):
+        # wstring                  do_wstring(in wstring p1, inout wstring p2, out wstring p3);
+        ret = u""
+        if p1 is not None: ret = ret + p1
+        if p2 is not None: ret = ret + p2
+        return ret, p1, p2
+    def do_nsIIDRef(self, p1, p2):
+        # nsIIDRef                 do_nsIIDRef(in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3);
+        return p1, self._reg_clsid_, p2
+    def do_nsIPythonTestInterface(self, p1, p2):
+        # nsIPythonTestInterface   do_nsIPythonTestInterface(in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3);
+        return p2, p1, self
+    def do_nsISupports(self, p1, p2):
+        # nsISupports              do_nsISupports(in nsISupports p1, inout nsISupports p2, out nsISupports p3);
+        return self, p1, p2
+    def do_nsISupportsIs(self, iid):
+        # void                     do_nsISupportsIs(in nsIIDRef iid, [iid_is(iid),retval] out nsQIResult result)
+        # Note the framework does the QI etc on us, so there is no real point me doing it.
+        # (However, user code _should_ do the QI - otherwise any errors are deemed "internal" (as they
+        # are raised by the C++ framework), and therefore logged to the console, etc.
+        # A user QI allows the user to fail gracefully, whatever gracefully means for them!
+        return self
+# Do I really need these??
+##    def do_nsISupportsIs2(self, iid, interface):
+##        # void                     do_nsISupportsIs2(inout nsIIDRef iid, [iid_is(iid),retval] inout nsQIResult result);
+##        return iid, interface
+##    def do_nsISupportsIs3(self, interface):
+##        # void                     do_nsISupportsIs3(out nsIIDRef iid, [iid_is(iid)] inout nsQIResult result);
+##        return self._com_interfaces_, interface
+##    def do_nsISupportsIs4(self):
+##        # void                     do_nsISupportsIs4(out nsIIDRef iid, [iid_is(iid)] out nsQIResult result);
+##        return self._com_interfaces_, self
+
+    # Methods from the nsIPythonTestInterfaceExtra interface
+    #
+    def MultiplyEachItemInIntegerArray(self, val, valueArray):
+        # void MultiplyEachItemInIntegerArray(
+        #                       in PRInt32 val, 
+        #                       in PRUint32 count, 
+        #                       [array, size_is(count)] inout PRInt32 valueArray);
+        # NOTE - the "sizeis" params are never passed to or returned from Python!
+        results = []
+        for item in valueArray:
+            results.append(item * val)
+        return results
+    def MultiplyEachItemInIntegerArrayAndAppend(self, val, valueArray):
+        #void MultiplyEachItemInIntegerArrayAndAppend(
+        #                       in PRInt32 val, 
+        #                       inout PRUint32 count, 
+        #                       [array, size_is(count)] inout PRInt32 valueArray);
+        results = valueArray[:]
+        for item in valueArray:
+            results.append(item * val)
+        return results
+    def DoubleStringArray(self, valueArray):
+        # void DoubleStringArray(inout PRUint32 count, 
+        #                       [array, size_is(count)] inout string valueArray);
+        results = []
+        for item in valueArray:
+            results.append(item * 2)
+        return results
+
+    def ReverseStringArray(self, valueArray):
+        # void ReverseStringArray(in PRUint32 count, 
+        #                    [array, size_is(count)] inout string valueArray);
+        valueArray.reverse()
+        return valueArray
+
+    # Note that this method shares a single "size_is" between 2 params!
+    def CompareStringArrays(self, ar1, ar2):
+        # void CompareStringArrays([array, size_is(count)] in string arr1,
+        #              [array, size_is(count)] in string arr2,
+        #              in unsigned long count,
+        #             [retval] out short result);
+        return cmp(ar1, ar2)
+
+    def DoubleString(self, val):
+        # void DoubleString(inout PRUint32 count, 
+        #               [size_is(count)] inout string str);
+        return val * 2
+    def DoubleString2(self, val):
+        # void DoubleString2(in PRUint32 in_count, [size_is(in_count)] in string in_str,
+        #                out PRUint32 out_count, [size_is(out_count)] out string out_str);
+        return val * 2
+    def DoubleString3(self, val):
+        # void DoubleString3(in PRUint32 in_count, [size_is(in_count)] in string in_str,
+        #                    out PRUint32 out_count, [size_is(out_count), retval] string out_str);
+        return val * 2
+    def DoubleString4(self, val):
+        # void DoubleString4([size_is(count)] in string in_str, inout PRUint32 count, [size_is(count)] out string out_str);
+        return val * 2
+    def UpString(self, val):
+        # // UpString defines the count as only "in" - meaning the result must be the same size
+        # void UpString(in PRUint32 count, 
+        #               [size_is(count)] inout string str);
+        return val.upper()
+    UpString2 = UpString
+        # // UpString2 defines count as only "in", and a string as only "out"
+        #     void UpString2(in PRUint32 count, 
+        #               [size_is(count)] inout string in_str,
+        #               [size_is(count)]out string out_str);
+
+    def GetFixedString(self, count):
+        # void GetFixedString(in PRUint32 count, [size_is(count)out string out_str);
+        return "A" * count
+
+    # DoubleWideString functions are identical to DoubleString, except use wide chars!
+    def DoubleWideString(self, val):
+        return val * 2
+    def DoubleWideString2(self, val):
+        return val * 2
+    def DoubleWideString3(self, val):
+        return val * 2
+    def DoubleWideString4(self, val):
+        return val * 2
+    def UpWideString(self, val):
+        return val.upper()
+    UpWideString2 = UpWideString
+    def CopyUTF8String(self, v):
+        return v
+    def CopyUTF8String2(self, v):
+        return v.encode("utf8")
+    # Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!)
+    def GetFixedWideString(self, count):
+        # void GetFixedWideString(in PRUint32 count, [size_is(count)out string out_str);
+        return u"A" * count
+
+    def GetStrings(self):
+        # void GetStrings(out PRUint32 count,
+        #            [retval, array, size_is(count)] out string str);
+        return "Hello from the Python test component".split()
+    # Some tests for our special "PRUint8" support.
+    def UpOctetArray( self, data ):
+        # void UpOctetArray(inout PRUint32 count,
+        #                [array, size_is(count)] inout PRUint8 data);
+        return data.upper()
+
+    def UpOctetArray2( self, data ):
+        # void UpOctetArray2(inout PRUint32 count,
+        #                [array, size_is(count)] inout PRUint8 data);
+        data = data.upper()
+        # This time we return a list of integers.
+        return map( ord, data )
+
+    # Arrays of interfaces
+    def CheckInterfaceArray(self, interfaces):
+        # void CheckInterfaceArray(in PRUint32 count,
+        #                          [array, size_is(count)] in nsISupports data,
+        #                          [retval] out PRBool all_non_null);
+        ret = 1
+        for i in interfaces:
+            if i is None:
+                ret = 0
+                break
+        return ret
+    def CopyInterfaceArray(self, a):
+        return a
+    def GetInterfaceArray(self):
+        # void GetInterfaceArray(out PRUint32 count,
+        #                          [array, size_is(count)] out nsISupports data);
+        return self, self, self, None
+    def ExtendInterfaceArray(self, data):
+        # void ExtendInterfaceArray(inout PRUint32 count,
+        #                          [array, size_is(count)] inout nsISupports data);
+        return data * 2
+
+    # Arrays of IIDs
+    def CheckIIDArray(self, data):
+        # void CheckIIDArray(in PRUint32 count,
+        #                          [array, size_is(count)] in nsIIDRef data,
+        #                          [retval] out PRBool all_mine);
+        ret = 1
+        for i in data:
+            if i!= self._com_interfaces_ and i != self._reg_clsid_:
+                ret = 0
+                break
+        return ret
+    def GetIIDArray(self):
+        # void GetIIDArray(out PRUint32 count,
+        #                         [array, size_is(count)] out nsIIDRef data);
+        return self._com_interfaces_, self._reg_clsid_
+    def ExtendIIDArray(self, data):
+        # void ExtendIIDArray(inout PRUint32 count,
+        #                      [array, size_is(count)] inout nsIIDRef data);
+        return data * 2
+
+    # Test our count param can be shared as an "in" param.
+    def SumArrays(self, array1, array2):
+        # void SumArrays(in PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]in array2, [retval]result);
+        if len(array1)!=len(array2):
+            print "SumArrays - not expecting different lengths!"
+        result = 0
+        for i in array1:
+            result = result + i
+        for i in array2:
+            result = result+i
+        return result
+
+    # Test our count param can be shared as an "out" param.
+    def GetArrays(self):
+        # void GetArrays(out PRUint32 count, [array, size_is(count)]out array1, [array, size_is(count)]out array2);
+        return (1,2,3), (4,5,6)
+    # Test we can get an "out" array with an "in" size
+    def GetFixedArray(self, size):
+        # void GetFixedArray(in PRUint32 count, [array, size_is(count)]out PRInt32 array1]);
+        return 0 * size
+    
+    # Test our "in" count param can be shared as one "in", plus one  "out" param.
+    def CopyArray(self, array1):
+        # void CopyArray(in PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]out array2);
+        return array1
+    # Test our "in-out" count param can be shared as one "in", plus one  "out" param.
+    def CopyAndDoubleArray(self, array):
+        # void CopyAndDoubleArray(inout PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]out array2);
+        return array + array
+    # Test our "in-out" count param can be shared as one "in", plus one  "in-out" param.
+    def AppendArray(self, array1, array2):
+        # void AppendArray(inout PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]inout array2);
+        rc = array1
+        if array2 is not None:
+            rc.extend(array2)
+        return rc
+    # Test nsIVariant support
+    def AppendVariant(self, invar, inresult):
+        if type(invar)==type([]):
+            invar_use = invar[0]
+            for v in invar[1:]:
+                invar_use += v
+        else:
+            invar_use = invar
+        if type(inresult)==type([]):
+            inresult_use = inresult[0]
+            for v in inresult[1:]:
+                inresult_use += v
+        else:
+            inresult_use = inresult
+        if inresult_use is None and invar_use is None:
+            return None
+        return inresult_use + invar_use
+
+    def CopyVariant(self, invar):
+        return invar
+
+    def SumVariants(self, variants):
+        if len(variants) == 0:
+            return None
+        result = variants[0]
+        for v in variants[1:]:
+            result += v
+        return result
+
+    # Some tests for the "new" (Feb-2001) DOMString type.
+    def GetDOMStringResult( self, length ):
+        # Result: DOMString &
+        if length == -1:
+            return None
+        return "P" * length
+    def GetDOMStringOut( self, length ):
+        # Result: DOMString &
+        if length == -1:
+            return None
+        return "y" * length
+    def GetDOMStringLength( self, param0 ):
+        # Result: uint32
+        # In: param0: DOMString &
+        if param0 is None: return -1
+        return len(param0)
+
+    def GetDOMStringRefLength( self, param0 ):
+        # Result: uint32
+        # In: param0: DOMString &
+        if param0 is None: return -1
+        return len(param0)
+
+    def GetDOMStringPtrLength( self, param0 ):
+        # Result: uint32
+        # In: param0: DOMString *
+        if param0 is None: return -1
+        return len(param0)
+
+    def ConcatDOMStrings( self, param0, param1 ):
+        # Result: void - None
+        # In: param0: DOMString &
+        # In: param1: DOMString &
+        # Out: DOMString &
+        return param0 + param1
+    def get_domstring_value( self ):
+        # Result: DOMString &
+        return self.domstring_value
+    def set_domstring_value( self, param0 ):
+        # Result: void - None
+        # In: param0: DOMString &
+        self.domstring_value = param0
+
+    def get_domstring_value_ro( self ):
+        # Result: DOMString &
+        return self.domstring_value
Index: trunk/src/libs/xpcom18a4/python/test/test_components.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_components.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_components.py	(revision 11746)
@@ -0,0 +1,109 @@
+# ***** 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, 2001
+# 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 *****
+
+"""Tests the "xpcom.components" object.
+"""
+
+import xpcom.components
+from pyxpcom_test_tools import suite_from_functions, testmain
+
+if not __debug__:
+    raise RuntimeError, "This test uses assert, so must be run in debug mode"
+
+def test_interfaces():
+    "Test the xpcom.components.interfaces object"
+
+    iid = xpcom.components.interfaces.nsISupports
+    assert iid == xpcom._xpcom.IID_nsISupports, "Got the wrong IID!"
+    iid = xpcom.components.interfaces['nsISupports']
+    assert iid == xpcom._xpcom.IID_nsISupports, "Got the wrong IID!"
+    
+    # Test dictionary semantics
+    num_fetched = num_nsisupports = 0
+    for name, iid in xpcom.components.interfaces.items():
+        num_fetched = num_fetched + 1
+        if name == "nsISupports":
+            num_nsisupports = num_nsisupports + 1
+            assert iid == xpcom._xpcom.IID_nsISupports, "Got the wrong IID!"
+        assert xpcom.components.interfaces[name] == iid
+    # Check all the lengths match.
+    assert len(xpcom.components.interfaces.keys()) == len(xpcom.components.interfaces.values()) == \
+               len(xpcom.components.interfaces.items()) == len(xpcom.components.interfaces) == \
+               num_fetched, "The collection lengths were wrong"
+    assert num_nsisupports == 1, "Didnt find exactly 1 nsiSupports!"
+
+def test_classes():
+    # Need a well-known contractID here?
+    prog_id = "@mozilla.org/supports-array;1"
+    clsid = xpcom.components.ID("{bda17d50-0d6b-11d3-9331-00104ba0fd40}")
+
+    # Check we can create the instance (dont check we can do anything with it tho!)
+    klass = xpcom.components.classes[prog_id]
+    instance = klass.createInstance()
+    
+    # Test dictionary semantics
+    num_fetched = num_mine = 0
+    for name, klass in xpcom.components.classes.items():
+        num_fetched = num_fetched + 1
+        if name == prog_id:
+            assert klass.clsid == clsid, "Eeek - didn't get the correct IID - got %s" %klass.clsid
+            num_mine = num_mine + 1
+
+# xpcom appears to add charset info to the contractid!?         
+#        assert xpcom.components.classes[name].contractid == prog_id, "Expected '%s', got '%s'" % (prog_id, xpcom.components.classes[name].contractid)
+    # Check all the lengths match.
+    if len(xpcom.components.classes.keys()) == len(xpcom.components.classes.values()) == \
+               len(xpcom.components.classes.items()) == len(xpcom.components.classes) == \
+               num_fetched:
+        pass
+    else:
+        raise RuntimeError, "The collection lengths were wrong"
+    if num_fetched <= 0:
+        raise RuntimeError, "Didnt get any classes!!!"
+    if num_mine != 1:
+        raise RuntimeError, "Didnt find exactly 1 of my contractid! (%d)" % (num_mine,)
+    
+def test_id():
+    id = xpcom.components.ID(str(xpcom._xpcom.IID_nsISupports))
+    assert id == xpcom._xpcom.IID_nsISupports
+
+# Make this test run under our std test suite
+def suite():
+    return suite_from_functions(test_interfaces, test_classes, test_id)
+
+if __name__=='__main__':
+    testmain()
Index: trunk/src/libs/xpcom18a4/python/test/test_isupports_primitives.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_isupports_primitives.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_isupports_primitives.py	(revision 11746)
@@ -0,0 +1,207 @@
+# ***** 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, 2001
+# 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 *****
+
+# Test our support for the interfaces defined in nsISupportsPrimitives.idl
+#
+# The framework supports nsISupportsCString and nsISupportsString, but
+# only if our class doesnt provide explicit support.
+
+from xpcom import components
+from xpcom import primitives
+import xpcom.server, xpcom.client
+from pyxpcom_test_tools import testmain
+import unittest
+
+class NoSupportsString:
+    _com_interfaces_ = [components.interfaces.nsISupports]
+
+class ImplicitSupportsString:
+    _com_interfaces_ = [components.interfaces.nsISupports]
+    def __str__(self):
+        return "<MyImplicitStrObject>"
+
+class ExplicitSupportsString:
+    _com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
+                        components.interfaces.nsISupportsCString]
+    type = components.interfaces.nsISupportsPrimitive.TYPE_CSTRING
+    test_data = "<MyExplicitStrObject>"
+    # __str__ will be ignored by XPCOM, as we have _explicit_ support.
+    def __str__(self):
+        return "<MyImplicitStrObject>"
+    # These are the ones that will be used.
+    def get_data(self):
+        return self.test_data
+    def toString(self):
+        return self.test_data
+
+class ImplicitSupportsUnicode:
+    _com_interfaces_ = [components.interfaces.nsISupports]
+    test_data = u"Copyright \xa9 the initial developer"
+    def __unicode__(self):
+        # An extended character in unicode tests can't hurt!
+        return self.test_data
+
+class ExplicitSupportsUnicode:
+    _com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
+                        components.interfaces.nsISupportsString]
+    type = components.interfaces.nsISupportsPrimitive.TYPE_STRING
+    # __unicode__ will be ignored by XPCOM, as we have _explicit_ support.
+    test_data = u"Copyright \xa9 the initial developer"
+    def __unicode__(self):
+        return self.test_data
+    def get_data(self):
+        return self.test_data
+
+class ImplicitSupportsInt:
+    _com_interfaces_ = [components.interfaces.nsISupports]
+    def __int__(self):
+        return 99
+
+class ExplicitSupportsInt:
+    _com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
+                        components.interfaces.nsISupportsPRInt32]
+    type = components.interfaces.nsISupportsPrimitive.TYPE_PRINT32
+    def get_data(self):
+        return 99
+
+class ImplicitSupportsLong:
+    _com_interfaces_ = [components.interfaces.nsISupports]
+    def __long__(self):
+        return 99L
+
+class ExplicitSupportsLong:
+    _com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
+                        components.interfaces.nsISupportsPRInt64]
+    type = components.interfaces.nsISupportsPrimitive.TYPE_PRINT64
+    def get_data(self):
+        return 99
+
+class ExplicitSupportsFloat:
+    _com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
+                        components.interfaces.nsISupportsDouble]
+    type = components.interfaces.nsISupportsPrimitive.TYPE_DOUBLE
+    def get_data(self):
+        return 99.99
+
+class ImplicitSupportsFloat:
+    _com_interfaces_ = [components.interfaces.nsISupports]
+    def __float__(self):
+        return 99.99
+
+class PrimitivesTestCase(unittest.TestCase):
+    def testNoSupports(self):
+        ob = xpcom.server.WrapObject( NoSupportsString(), components.interfaces.nsISupports)
+        if not str(ob).startswith("<XPCOM "):
+            raise RuntimeError, "Wrong str() value: %s" % (ob,)
+
+    def testImplicitString(self):
+        ob = xpcom.server.WrapObject( ImplicitSupportsString(), components.interfaces.nsISupports)
+        self.failUnlessEqual(str(ob), "<MyImplicitStrObject>")
+
+    def testExplicitString(self):
+        ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports)
+        self.failUnlessEqual(str(ob), "<MyExplicitStrObject>")
+
+    def testImplicitUnicode(self):
+        ob = xpcom.server.WrapObject( ImplicitSupportsUnicode(), components.interfaces.nsISupports)
+        self.failUnlessEqual(unicode(ob), ImplicitSupportsUnicode.test_data)
+
+    def testExplicitUnicode(self):
+        ob = xpcom.server.WrapObject( ExplicitSupportsUnicode(), components.interfaces.nsISupports)
+        self.failUnlessEqual(unicode(ob), ExplicitSupportsUnicode.test_data)
+
+    def testConvertInt(self):
+        # Try our conversions.
+        ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports)
+        self.failUnlessRaises( ValueError, int, ob)
+
+    def testExplicitInt(self):
+        ob = xpcom.server.WrapObject( ExplicitSupportsInt(), components.interfaces.nsISupports)
+        self.failUnlessAlmostEqual(float(ob), 99.0)
+        self.failUnlessEqual(int(ob), 99)
+
+    def testImplicitInt(self):
+        ob = xpcom.server.WrapObject( ImplicitSupportsInt(), components.interfaces.nsISupports)
+        self.failUnlessAlmostEqual(float(ob), 99.0)
+        self.failUnlessEqual(int(ob), 99)
+
+    def testExplicitLong(self):
+        ob = xpcom.server.WrapObject( ExplicitSupportsLong(), components.interfaces.nsISupports)
+        if long(ob) != 99 or not repr(long(ob)).endswith("L"):
+            raise RuntimeError, "Bad value: %s" % (repr(long(ob)),)
+        self.failUnlessAlmostEqual(float(ob), 99.0)
+
+    def testImplicitLong(self):
+        ob = xpcom.server.WrapObject( ImplicitSupportsLong(), components.interfaces.nsISupports)
+        if long(ob) != 99 or not repr(long(ob)).endswith("L"):
+            raise RuntimeError, "Bad value: %s" % (repr(long(ob)),)
+        self.failUnlessAlmostEqual(float(ob), 99.0)
+
+    def testExplicitFloat(self):
+        ob = xpcom.server.WrapObject( ExplicitSupportsFloat(), components.interfaces.nsISupports)
+        self.failUnlessEqual(float(ob), 99.99)
+        self.failUnlessEqual(int(ob), 99)
+
+    def testImplicitFloat(self):
+        ob = xpcom.server.WrapObject( ImplicitSupportsFloat(), components.interfaces.nsISupports)
+        self.failUnlessEqual(float(ob), 99.99)
+        self.failUnlessEqual(int(ob), 99)
+
+class PrimitivesModuleTestCase(unittest.TestCase):
+    def testExplicitString(self):
+        ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports)
+        self.failUnlessEqual(primitives.GetPrimitive(ob), "<MyExplicitStrObject>")
+
+    def testExplicitUnicode(self):
+        ob = xpcom.server.WrapObject( ExplicitSupportsUnicode(), components.interfaces.nsISupports)
+        self.failUnlessEqual(primitives.GetPrimitive(ob), ExplicitSupportsUnicode.test_data)
+        self.failUnlessEqual(type(primitives.GetPrimitive(ob)), unicode)
+
+    def testExplicitInt(self):
+        ob = xpcom.server.WrapObject( ExplicitSupportsInt(), components.interfaces.nsISupports)
+        self.failUnlessEqual(primitives.GetPrimitive(ob), 99)
+
+    def testExplicitLong(self):
+        ob = xpcom.server.WrapObject( ExplicitSupportsLong(), components.interfaces.nsISupports)
+        self.failUnlessEqual(primitives.GetPrimitive(ob), 99)
+
+    def testExplicitFloat(self):
+        ob = xpcom.server.WrapObject( ExplicitSupportsFloat(), components.interfaces.nsISupports)
+        self.failUnlessEqual(primitives.GetPrimitive(ob), 99.99)
+
+if __name__=='__main__':
+    testmain()
Index: trunk/src/libs/xpcom18a4/python/test/test_misc.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_misc.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_misc.py	(revision 11746)
@@ -0,0 +1,236 @@
+# ***** 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>
+#
+# 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 *****
+
+import xpcom
+import xpcom.client
+import xpcom.server
+import xpcom._xpcom
+import xpcom.components
+import string
+from pyxpcom_test_tools import testmain
+
+import unittest
+
+import traceback, getopt, sys
+
+verbose_level = 0
+
+reportedSampleMissing = 0
+
+def get_sample_component_cpp():
+    global reportedSampleMissing
+    contractid = "@mozilla.org/sample;1" # The C++ version.
+    try:
+        return xpcom.components.classes[contractid].createInstance()
+    except xpcom.COMException:
+        if not reportedSampleMissing:
+            print "***"
+            print "*** This test requires an XPCOM sample component,"
+            print "*** which does not exist.  To build this test, you"
+            print "*** should change to the 'mozilla/xpcom/sample' directory,"
+            print "*** and run 'make', then run this test again."
+            print "***"
+            reportedSampleMissing = 1
+        else:
+            print "(skipping - no C++ sample...) ",
+        return None
+
+def get_sample_component_js():
+    # This should *always* exist - no special make process.
+    contractid = "@mozilla.org/jssample;1" # the JS version
+    return xpcom.components.classes[contractid].createInstance()
+    
+class TestDumpInterfaces(unittest.TestCase):
+    def testAllInterfaces(self):
+        "Dump every interface under the sun!"
+        import xpcom, xpcom.xpt, xpcom._xpcom
+        iim = xpcom._xpcom.XPTI_GetInterfaceInfoManager()
+    
+        if verbose_level:
+            print "Dumping every interface I can find"
+        enum = iim.EnumerateInterfaces()
+        rc = enum.First()
+        num = 0
+        while rc==0:
+            item = enum.CurrentItem(xpcom._xpcom.IID_nsIInterfaceInfo)
+            try:
+                iid = item.GetIID()
+            except xpcom.COMException:
+                if verbose_level:
+                    print "Can't dump", item
+                continue # Dont bother dumping this.
+            interface = xpcom.xpt.Interface(iid)
+            num = num + 1
+            text = interface.Describe()
+            if verbose_level:
+                print text
+    
+            rc = enum.Next()
+        if num < 200:
+            print "Only found", num, "interfaces - this seems unusually low!"
+
+class TestEnumContractIDs(unittest.TestCase):
+    def testContractIDs(self):
+        """Enumerate all the ContractIDs registered"""
+        enum = xpcom.components.registrar.enumerateContractIDs()
+        n = 0
+        while enum.hasMoreElements():
+            item = enum.getNext(xpcom.components.interfaces.nsISupportsCString)
+            n = n + 1
+            if verbose_level:
+                print "ContractID:", item.data
+        if n < 200:
+            print "Only found", n, "ContractIDs - this seems unusually low!"
+
+class TestSampleComponent(unittest.TestCase):
+    def _doTestSampleComponent(self, test_flat = 0):
+        """Test the standard Netscape 'sample' sample"""
+        c = get_sample_component_cpp()
+        if c is None:
+            return
+        if not test_flat:
+            c = c.queryInterface(xpcom.components.interfaces.nsISample)
+        self.failUnlessEqual(c.value, "initial value")
+        c.value = "new value"
+        self.failUnlessEqual(c.value, "new value")
+        c.poke("poked value")
+        self.failUnlessEqual(c.value, "poked value")
+        c.writeValue("Python just poked:")
+
+    def testSampleComponentFlat(self):
+        """Test the standard Netscape 'sample' sample using interface flattening"""
+        self._doTestSampleComponent(1)
+
+    def testSampleComponentOld(self):
+        """Test the standard Netscape 'sample' sample using explicit QI"""
+        self._doTestSampleComponent(0)
+    
+    def _doTestHash(self, c):
+        "Test that hashing COM objects works"
+        d = {}
+        d[c] = None
+        if not d.has_key(c):
+            raise RuntimeError, "Can't get the exact same object back!"
+        if not d.has_key(c.queryInterface(xpcom.components.interfaces.nsISupports)):
+            raise RuntimeError, "Can't get back as nsISupports"
+
+        # And the same in reverse - stick an nsISupports in, and make sure an explicit interface comes back.
+        d = {}
+#        contractid = "@mozilla.org/sample;1" # The C++ version.
+#        c = xpcom.components.classes[contractid].createInstance() \
+#            .queryInterface(xpcom.components.interfaces.nsISupports)
+        d[c] = None
+        if not d.has_key(c):
+            raise RuntimeError, "Can't get the exact same object back!"
+        if not d.has_key(c.queryInterface(xpcom.components.interfaces.nsISample)):
+            raise RuntimeError, "Can't get back as nsISupports"
+
+    def testHashJS(self):
+        c = get_sample_component_js()
+        self._doTestHash(c)
+
+    def testHashCPP(self):
+        c = get_sample_component_cpp()
+        if c is not None:
+            self._doTestHash(c)
+
+
+class TestIIDs(unittest.TestCase):
+    def TestIIDs(self):
+        "Do some basic IID semantic tests."
+        iid_str = "{7ee4bdc6-cb53-42c1-a9e4-616b8e012aba}"
+        IID = xpcom._xpcom.IID
+        self.failUnlessEqual(IID(iid_str), IID(iid_str))
+        self.failUnlessEqual(hash(IID(iid_str)), hash(IID(iid_str)))
+        self.failUnlessEqual(IID(iid_str), IID(iid_str.upper()))
+        self.failUnlessEqual(hash(IID(iid_str)), hash(IID(iid_str.upper())))
+        # If the above work, this shoud too, but WTF
+        dict = {}
+        dict[IID(iid_str)] = None
+        self.failUnless(dict.has_key(IID(iid_str)), "hashes failed in dictionary")
+        self.failUnless(dict.has_key(IID(iid_str.upper())), "uppercase hash failed in dictionary")
+
+class TestRepr(unittest.TestCase):
+    def _doTestRepr(self, progid, interfaces):
+        if isinstance(progid, str):
+            ob = xpcom.components.classes[progid].createInstance()
+        else:
+            ob = progid
+        self.failUnless(repr(ob).find(str(progid)) >= 0, repr(ob))
+        for interface_name in interfaces.split():
+            self.failUnless(repr(ob).find(interface_name) >= 0, repr(ob))
+
+    def testReprPython(self):
+        "Test repr() of Python objects"
+        self._doTestRepr("Python.TestComponent", "nsIPythonTestInterfaceDOMStrings nsIPythonTestInterfaceExtra nsIPythonTestInterface")
+
+    # JS does not provide class-info :(
+    #def testReprJS(self):
+    #    self._doTestRepr("@mozilla.org/jssample;1", "nsISample")
+
+    def testReprSample(self):
+        "Test repr() of non-Python objects"
+        ob = get_sample_component_cpp()
+        if ob is None:
+            return
+        self._doTestRepr(ob, "nsISample")
+
+class TestUnwrap(unittest.TestCase):
+    "Test the unwrap facilities"
+    def testUnwrap(self):
+        # First test that a Python object can be unwrapped.
+        ob = xpcom.components.classes["Python.TestComponent"].createInstance()
+        pyob = xpcom.server.UnwrapObject(ob)
+        # This depends on our __repr__ implementation, but that's OK - it
+        # can be updated should our __repr__ change :)
+        self.failUnless(str(pyob).startswith("<component:py_test_component.PythonTestComponent"))
+        # Test that a non-Python implemented object can NOT be unwrapped.
+        ob = get_sample_component_cpp()
+        if ob is None:
+            return
+        self.failUnlessRaises(ValueError, xpcom.server.UnwrapObject, ob)
+
+class TestNonScriptable(unittest.TestCase):
+    def testQI(self):
+        # Test we can QI for a non-scriptable interface.  We can't *do* much
+        # with it (other than pass it on), but we should still work and get
+        # a basic wrapper.
+        ob = xpcom.components.classes["Python.TestComponent"].createInstance()
+        ob = ob.queryInterface(xpcom._xpcom.IID_nsIInternalPython)
+
+if __name__=='__main__':
+    testmain()
Index: trunk/src/libs/xpcom18a4/python/test/test_streams.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_streams.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_streams.py	(revision 11746)
@@ -0,0 +1,96 @@
+# ***** 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,2001
+# 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 *****
+
+import xpcom
+from xpcom import _xpcom, components, COMException, ServerException, nsError
+from StringIO import StringIO
+import unittest
+from pyxpcom_test_tools import testmain
+
+test_data = "abcdefeghijklmnopqrstuvwxyz"
+
+class koTestSimpleStream:
+    _com_interfaces_ = [components.interfaces.nsIInputStream]
+    # We avoid registering this object - see comments in get_test_inout_? below.
+
+    def __init__(self):
+        self.data=StringIO(test_data)
+        self._non_blocking = False
+
+    def close( self ):
+        pass
+
+    def available( self ):
+        return self.data.len-self.data.pos
+
+    def readStr( self, amount):
+        return self.data.read(amount)
+
+    read=readStr
+
+    def get_observer( self ):
+        raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
+
+    def set_observer( self, param0 ):
+        raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
+
+    def isNonBlocking(self):
+        return self._non_blocking
+
+def get_test_input():
+    # We use a couple of internal hacks here that mean we can avoid having the object
+    # registered.  This code means that we are still working over the xpcom boundaries, tho
+    # (and the point of this test is not the registration, etc).
+    import xpcom.server, xpcom.client
+    ob = xpcom.server.WrapObject( koTestSimpleStream(), _xpcom.IID_nsISupports)
+    ob = xpcom.client.Component(ob._comobj_, components.interfaces.nsIInputStream)
+    return ob
+
+class StreamTests(unittest.TestCase):
+    def testInput(self):
+        self.do_test_input( get_test_input() )
+
+    def do_test_input(self, myStream):
+        self.failUnlessEqual(str(myStream.read(5)), test_data[:5])
+        self.failUnlessEqual(str(myStream.read(0)), '')
+        self.failUnlessEqual(str(myStream.read(5)), test_data[5:10])
+        self.failUnlessEqual(str(myStream.read(-1)), test_data[10:])
+        self.failIf(myStream.isNonBlocking(), "Expected default to be blocking")
+        # stream observer mechanism has changed - we should test that.
+
+if __name__=='__main__':
+    testmain()
Index: trunk/src/libs/xpcom18a4/python/test/test_test_component.js
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_test_component.js	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_test_component.js	(revision 11746)
@@ -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 <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 ***** */
+
+/* Javascript code calling the Python test interface. */
+
+var extended_unicode_string = "The Euro Symbol is '\u20ac'";
+
+function MakeTestInterface()
+{
+    var clazz = Components.classes["Python.TestComponent"];
+    var iface = Components.interfaces.nsIPythonTestInterfaceDOMStrings;
+    return new clazz(iface);
+}    
+
+var c = new MakeTestInterface();
+
+if (c.boolean_value != 1)
+	throw("boolean_value has wrong initial value");
+c.boolean_value = false;
+if (c.boolean_value != false)
+	throw("boolean_value has wrong new value");
+
+// Python's own test does thorough testing of all numeric types
+// Wont bother from here!
+
+if (c.char_value != 'a')
+	throw("char_value has wrong initial value");
+c.char_value = 'b';
+if (c.char_value != 'b')
+	throw("char_value has wrong new value");
+
+if (c.wchar_value != 'b')
+	throw("wchar_value has wrong initial value");
+c.wchar_value = 'c';
+if (c.wchar_value != 'c')
+	throw("wchar_value has wrong new value");
+
+if (c.string_value != 'cee')
+	throw("string_value has wrong initial value");
+c.string_value = 'dee';
+if (c.string_value != 'dee')
+	throw("string_value has wrong new value");
+
+if (c.wstring_value != 'dee')
+	throw("wstring_value has wrong initial value");
+c.wstring_value = 'eee';
+if (c.wstring_value != 'eee')
+	throw("wstring_value has wrong new value");
+c.wstring_value = extended_unicode_string;
+if (c.wstring_value != extended_unicode_string)
+	throw("wstring_value has wrong new value");
+
+if (c.domstring_value != 'dom')
+	throw("domstring_value has wrong initial value");
+c.domstring_value = 'New value';
+if (c.domstring_value != 'New value')
+	throw("domstring_value has wrong new value");
+c.domstring_value = extended_unicode_string;
+if (c.domstring_value != extended_unicode_string)
+	throw("domstring_value has wrong new value");
+
+if (c.utf8string_value != 'utf8string')
+	throw("utf8string_value has wrong initial value");
+c.utf8string_value = 'New value';
+if (c.utf8string_value != 'New value')
+	throw("utf8string_value has wrong new value");
+c.utf8string_value = extended_unicode_string;
+if (c.utf8string_value != extended_unicode_string)
+	throw("utf8string_value has wrong new value");
+
+var v = new Object();
+v.value = "Hello"
+var l = new Object();
+l.value = v.value.length;
+c.DoubleString(l, v);
+if ( v.value != "HelloHello")
+	throw("Could not double the string!");
+
+var v = new Object();
+v.value = "Hello"
+var l = new Object();
+l.value = v.value.length;
+c.DoubleWideString(l, v);
+if ( v.value != "HelloHello")
+	throw("Could not double the wide string!");
+
+// Some basic array tests
+var v = new Array()
+v[0] = 1;
+v[2] = 2;
+v[3] = 3;
+var v2 = new Array()
+v2[0] = 4;
+v2[2] = 5;
+v2[3] = 6;
+if (c.SumArrays(v.length, v, v2) != 21)
+	throw("Could not sum an array of integers!");
+
+var count = new Object();
+count.value = 0;
+var out = [];
+c.DoubleStringArray(count, out);
+
+print("javascript successfully tested the Python test component.");
Index: trunk/src/libs/xpcom18a4/python/test/test_test_component.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_test_component.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_test_component.py	(revision 11746)
@@ -0,0 +1,575 @@
+# ***** 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, 2001
+# 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 *****
+
+import sys, os, time
+import xpcom.components
+import xpcom._xpcom
+import xpcom.nsError
+
+MakeVariant = xpcom._xpcom.MakeVariant
+
+try:
+    import gc
+except ImportError:
+    gc = None
+
+num_errors = 0
+
+component_iid = xpcom.components.ID("{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}")
+new_iid = xpcom.components.ID("{2AF747D3-ECBC-457b-9AF9-5C5D80EDC360}")
+
+contractid = "Python.TestComponent"
+
+really_big_string = "This is really repetitive!" * 10000
+really_big_wstring = u"This is really repetitive!" * 10000
+extended_unicode_string = u"The Euro Symbol is '\u20ac'"
+
+# Exception raised when a -ve integer is converted to an unsigned C integer
+# (via an extension module).  This changed in Python 2.2
+if sys.hexversion > 0x02010000:
+    UnsignedMismatchException = TypeError
+else:
+    UnsignedMismatchException = OverflowError
+
+def print_error(error):
+    print error
+    global num_errors
+    num_errors = num_errors + 1
+
+def _test_value(what, got, expecting):
+    ok = got == expecting
+    if type(got)==type(expecting)==type(0.0):
+        ok = abs(got-expecting) < 0.001
+    if not ok:
+        print_error("*** Error %s - got '%r', but expecting '%r'" % (what, got, expecting))
+
+def test_attribute(ob, attr_name, expected_init, new_value, new_value_really = None):
+    if xpcom.verbose:
+        print "Testing attribute %s" % (attr_name,)
+    if new_value_really is None:
+        new_value_really = new_value # Handy for eg bools - set a BOOL to 2, you still get back 1!
+        
+    _test_value( "getting initial attribute value (%s)" % (attr_name,), getattr(ob, attr_name), expected_init)
+    setattr(ob, attr_name, new_value)
+    _test_value( "getting new attribute value (%s)" % (attr_name,), getattr(ob, attr_name), new_value_really)
+    # And set it back to the expected init.
+    setattr(ob, attr_name, expected_init)
+    _test_value( "getting back initial attribute value after change (%s)" % (attr_name,), getattr(ob, attr_name), expected_init)
+
+def test_string_attribute(ob, attr_name, expected_init, is_dumb_sz = False, ascii_only = False):
+    test_attribute(ob, attr_name, expected_init, "normal value")
+    val = "a null >\0<"
+    if is_dumb_sz:
+        expected = "a null >" # dumb strings are \0 terminated.
+    else:
+        expected = val
+    test_attribute(ob, attr_name, expected_init, val, expected)
+    test_attribute(ob, attr_name, expected_init, "")
+    test_attribute(ob, attr_name, expected_init, really_big_string)
+    test_attribute(ob, attr_name, expected_init, u"normal unicode value")
+    val = u"a null >\0<"
+    if is_dumb_sz:
+        expected = "a null >" # dumb strings are \0 terminated.
+    else:
+        expected = val
+    test_attribute(ob, attr_name, expected_init, val, expected)
+    test_attribute(ob, attr_name, expected_init, u"")
+    test_attribute(ob, attr_name, expected_init, really_big_wstring)
+    if not ascii_only:
+        test_attribute(ob, attr_name, expected_init, extended_unicode_string)
+
+def test_attribute_failure(ob, attr_name, new_value, expected_exception):
+    try:
+        setattr(ob, attr_name, new_value)
+        print_error("*** Setting attribute '%s' to '%r' didnt yield an exception!" % (attr_name, new_value) )
+    except:
+        exc_typ = sys.exc_info()[0]
+        exc_val = sys.exc_info()[1]
+        ok = issubclass(exc_typ, expected_exception)
+        if not ok:
+            print_error("*** Wrong exception setting '%s' to '%r'- got '%s: %s', expected '%s'" % (attr_name, new_value, exc_typ, exc_val, expected_exception))
+
+
+def test_method(method, args, expected_results):
+    if xpcom.verbose:
+        print "Testing %s%s" % (method.__name__, `args`)
+    ret = method(*args)
+    if ret != expected_results:
+        print_error("calling method %s - expected %r, but got %r" % (method.__name__, expected_results, ret))
+
+def test_int_method(meth):
+    test_method(meth, (0,0), (0,0,0))
+    test_method(meth, (1,1), (2,0,1))
+    test_method(meth, (5,2), (7,3,10))
+#    test_method(meth, (2,5), (7,-3,10))
+
+def test_constant(ob, cname, val):
+    v = getattr(ob, cname)
+    if v != val:
+        print_error("Bad value for constant '%s' - got '%r'" % (cname, v))
+    try:
+        setattr(ob, cname, 0)
+        print_error("The object allowed us to set the constant '%s'" % (cname,))
+    except AttributeError:
+        pass
+
+def test_base_interface(c):
+    test_attribute(c, "boolean_value", 1, 0)
+    test_attribute(c, "boolean_value", 1, -1, 1) # Set a bool to anything, you should always get back 0 or 1
+    test_attribute(c, "boolean_value", 1, 4, 1) # Set a bool to anything, you should always get back 0 or 1
+    test_attribute(c, "boolean_value", 1, "1", 1) # This works by virtual of PyNumber_Int - not sure I agree, but...
+    test_attribute_failure(c, "boolean_value", "boo", ValueError)
+    test_attribute_failure(c, "boolean_value", test_base_interface, TypeError)
+
+    test_attribute(c, "octet_value", 2, 5)
+    test_attribute(c, "octet_value", 2, 0)
+    test_attribute(c, "octet_value", 2, 128) # octet is unsigned 8 bit
+    test_attribute(c, "octet_value", 2, 255) # octet is unsigned 8 bit
+    test_attribute(c, "octet_value", 2, -1, 255) # octet is unsigned 8 bit
+    test_attribute_failure(c, "octet_value", "boo", ValueError)
+
+    test_attribute(c, "short_value", 3, 10)
+    test_attribute(c, "short_value", 3, -1) # 16 bit signed
+    test_attribute(c, "short_value", 3, 0xFFFF, -1) # 16 bit signed
+    test_attribute(c, "short_value", 3, 0L)
+    test_attribute(c, "short_value", 3, 1L)
+    test_attribute(c, "short_value", 3, -1L)
+    test_attribute(c, "short_value", 3, 0xFFFFL, -1)
+    test_attribute_failure(c, "short_value", "boo", ValueError)
+
+    test_attribute(c, "ushort_value",  4, 5)
+    test_attribute(c, "ushort_value",  4, 0)
+    test_attribute(c, "ushort_value",  4, -1, 0xFFFF) # 16 bit signed
+    test_attribute(c, "ushort_value",  4, 0xFFFF) # 16 bit signed
+    test_attribute(c, "ushort_value",  4, 0L)
+    test_attribute(c, "ushort_value",  4, 1L)
+    test_attribute(c, "ushort_value",  4, -1L, 0xFFFF)
+    test_attribute_failure(c, "ushort_value", "boo", ValueError)
+
+    test_attribute(c, "long_value",  5, 7)
+    test_attribute(c, "long_value",  5, 0)
+    test_attribute(c, "long_value",  5, -1, -1) # 32 bit signed.
+    test_attribute(c, "long_value",  5, -1) # 32 bit signed.
+    test_attribute(c, "long_value",  5, 0L)
+    test_attribute(c, "long_value",  5, 1L)
+    test_attribute(c, "long_value",  5, -1L)
+    test_attribute_failure(c, "long_value", 0xFFFFL * 0xFFFF, OverflowError) # long int too long to convert
+    test_attribute_failure(c, "long_value", "boo", ValueError)
+
+    test_attribute(c, "ulong_value", 6, 7)
+    test_attribute(c, "ulong_value", 6, 0)
+    test_attribute(c, "ulong_value", 6, -1) # 32 bit signed.
+    test_attribute_failure(c, "ulong_value", "boo", ValueError)
+    
+    test_attribute(c, "long_long_value", 7, 8)
+    test_attribute(c, "long_long_value", 7, 0)
+    test_attribute(c, "long_long_value", 7, -1)
+    test_attribute(c, "long_long_value", 7, 0xFFFF)
+    test_attribute(c, "long_long_value", 7, 0xFFFFL * 2)
+    test_attribute_failure(c, "long_long_value", 0xFFFFL * 0xFFFF * 0xFFFF * 0xFFFF, OverflowError) # long int too long to convert
+    test_attribute_failure(c, "long_long_value", "boo", ValueError)
+    
+    test_attribute(c, "ulong_long_value", 8, 9)
+    test_attribute(c, "ulong_long_value", 8, 0)
+    test_attribute_failure(c, "ulong_long_value", "boo", ValueError)
+    test_attribute_failure(c, "ulong_long_value", -1, UnsignedMismatchException) # can't convert negative value to unsigned long)
+    
+    test_attribute(c, "float_value", 9.0, 10.2)
+    test_attribute(c, "float_value", 9.0, 0)
+    test_attribute(c, "float_value", 9.0, -1)
+    test_attribute(c, "float_value", 9.0, 1L)
+    test_attribute_failure(c, "float_value", "boo", ValueError)
+
+    test_attribute(c, "double_value", 10.0, 9.0)
+    test_attribute(c, "double_value", 10.0, 0)
+    test_attribute(c, "double_value", 10.0, -1)
+    test_attribute(c, "double_value", 10.0, 1L)
+    test_attribute_failure(c, "double_value", "boo", ValueError)
+    
+    test_attribute(c, "char_value", "a", "b")
+    test_attribute(c, "char_value", "a", "\0")
+    test_attribute_failure(c, "char_value", "xy", ValueError)
+    test_attribute(c, "char_value", "a", u"c")
+    test_attribute(c, "char_value", "a", u"\0")
+    test_attribute_failure(c, "char_value", u"xy", ValueError)
+    
+    test_attribute(c, "wchar_value", "b", "a")
+    test_attribute(c, "wchar_value", "b", "\0")
+    test_attribute_failure(c, "wchar_value", "hi", ValueError)
+    test_attribute(c, "wchar_value", "b", u"a")
+    test_attribute(c, "wchar_value", "b", u"\0")
+    test_attribute_failure(c, "wchar_value", u"hi", ValueError)
+    
+    test_string_attribute(c, "string_value", "cee", is_dumb_sz = True, ascii_only = True)
+    test_string_attribute(c, "wstring_value", "dee", is_dumb_sz = True)
+    test_string_attribute(c, "astring_value", "astring")
+    test_string_attribute(c, "acstring_value", "acstring", ascii_only = True)
+
+    test_string_attribute(c, "utf8string_value", "utf8string")
+    # Test a string already encoded gets through correctly.
+    test_attribute(c, "utf8string_value", "utf8string", extended_unicode_string.encode("utf8"), extended_unicode_string)
+
+    # This will fail internal string representation :(  Test we don't crash
+    try:
+        c.wstring_value = "a big char >" + chr(129) + "<"
+        print_error("strings with chars > 128 appear to have stopped failing?")
+    except UnicodeError:
+        pass
+
+    test_attribute(c, "iid_value", component_iid, new_iid)
+    test_attribute(c, "iid_value", component_iid, str(new_iid), new_iid)
+    test_attribute(c, "iid_value", component_iid, xpcom._xpcom.IID(new_iid))
+
+    test_attribute_failure(c, "no_attribute", "boo", AttributeError)
+
+    test_attribute(c, "interface_value", None, c)
+    test_attribute_failure(c, "interface_value", 2, TypeError)
+
+    test_attribute(c, "isupports_value", None, c)
+
+    # The methods
+    test_method(c.do_boolean, (0,1), (1,0,1))
+    test_method(c.do_boolean, (1,0), (1,0,1))
+    test_method(c.do_boolean, (1,1), (0,1,0))
+
+    test_int_method(c.do_octet)
+    test_int_method(c.do_short)
+
+    test_int_method(c.do_unsigned_short)
+    test_int_method(c.do_long)
+    test_int_method(c.do_unsigned_long)
+    test_int_method(c.do_long_long)
+    test_int_method(c.do_unsigned_long)
+    test_int_method(c.do_float)
+    test_int_method(c.do_double)
+
+    test_method(c.do_char, ("A", " "), (chr(ord("A")+ord(" ")), " ","A") )
+    test_method(c.do_char, ("A", "\0"), ("A", "\0","A") )
+    test_method(c.do_wchar, ("A", " "), (chr(ord("A")+ord(" ")), " ","A") )
+    test_method(c.do_wchar, ("A", "\0"), ("A", "\0","A") )
+
+    test_method(c.do_string, ("Hello from ", "Python"), ("Hello from Python", "Hello from ", "Python") )
+    test_method(c.do_string, (u"Hello from ", u"Python"), ("Hello from Python", "Hello from ", "Python") )
+    test_method(c.do_string, (None, u"Python"), ("Python", None, "Python") )
+    test_method(c.do_string, (None, really_big_string), (really_big_string, None, really_big_string) )
+    test_method(c.do_string, (None, really_big_wstring), (really_big_string, None, really_big_string) )
+    test_method(c.do_wstring, ("Hello from ", "Python"), ("Hello from Python", "Hello from ", "Python") )
+    test_method(c.do_wstring, (u"Hello from ", u"Python"), ("Hello from Python", "Hello from ", "Python") )
+    test_method(c.do_string, (None, really_big_wstring), (really_big_wstring, None, really_big_wstring) )
+    test_method(c.do_string, (None, really_big_string), (really_big_wstring, None, really_big_wstring) )
+    test_method(c.do_nsIIDRef, (component_iid, new_iid), (component_iid, component_iid, new_iid))
+    test_method(c.do_nsIIDRef, (new_iid, component_iid), (new_iid, component_iid, component_iid))
+    test_method(c.do_nsIPythonTestInterface, (None, None), (None, None, c))
+    test_method(c.do_nsIPythonTestInterface, (c, c), (c, c, c))
+    test_method(c.do_nsISupports, (None, None), (c, None, None))
+    test_method(c.do_nsISupports, (c,c), (c, c, c))
+    test_method(c.do_nsISupportsIs, (xpcom._xpcom.IID_nsISupports,), c)
+    test_method(c.do_nsISupportsIs, (xpcom.components.interfaces.nsIPythonTestInterface,), c)
+##    test_method(c.do_nsISupportsIs2, (xpcom.components.interfaces.nsIPythonTestInterface,c), (xpcom.components.interfaces.nsIPythonTestInterface,c))
+##    test_method(c.do_nsISupportsIs3, (c,), (xpcom.components.interfaces.nsIPythonTestInterface,c))
+##    test_method(c.do_nsISupportsIs4, (), (xpcom.components.interfaces.nsIPythonTestInterface,c))
+    # Test the constants.
+    test_constant(c, "One", 1)
+    test_constant(c, "Two", 2)
+    test_constant(c, "MinusOne", -1)
+    test_constant(c, "BigLong", 0x7FFFFFFF)
+    test_constant(c, "BiggerLong", -1)
+    test_constant(c, "BigULong", -1)
+    # Test the components.Interfaces semantics
+    i = xpcom.components.interfaces.nsIPythonTestInterface
+    test_constant(i, "One", 1)
+    test_constant(i, "Two", 2)
+    test_constant(i, "MinusOne", -1)
+    test_constant(i, "BigLong", 0x7FFFFFFF)
+    test_constant(i, "BigULong", -1)
+
+def test_derived_interface(c, test_flat = 0):
+    val = "Hello\0there"
+    expected = val * 2
+
+    test_method(c.DoubleString, (val,), expected)
+    test_method(c.DoubleString2, (val,), expected)
+    test_method(c.DoubleString3, (val,), expected)
+    test_method(c.DoubleString4, (val,), expected)
+    test_method(c.UpString, (val,), val.upper())
+    test_method(c.UpString2, (val,), val.upper())
+    test_method(c.GetFixedString, (20,), "A"*20)
+    val = u"Hello\0there"
+    expected = val * 2
+    test_method(c.DoubleWideString, (val,), expected)
+    test_method(c.DoubleWideString2, (val,), expected)
+    test_method(c.DoubleWideString3, (val,), expected)
+    test_method(c.DoubleWideString4, (val,), expected)
+    test_method(c.UpWideString, (val,), val.upper())
+    test_method(c.UpWideString2, (val,), val.upper())
+    test_method(c.GetFixedWideString, (20,), u"A"*20)
+    val = extended_unicode_string
+    test_method(c.CopyUTF8String, ("foo",), "foo")
+    test_method(c.CopyUTF8String, (u"foo",), "foo")
+    test_method(c.CopyUTF8String, (val,), val)
+    test_method(c.CopyUTF8String, (val.encode("utf8"),), val)
+    test_method(c.CopyUTF8String2, ("foo",), "foo")
+    test_method(c.CopyUTF8String2, (u"foo",), "foo")
+    test_method(c.CopyUTF8String2, (val,), val)
+    test_method(c.CopyUTF8String2, (val.encode("utf8"),), val)
+    items = [1,2,3,4,5]
+    test_method(c.MultiplyEachItemInIntegerArray, (3, items,), map(lambda i:i*3, items))
+
+    test_method(c.MultiplyEachItemInIntegerArrayAndAppend, (3, items), items + map(lambda i:i*3, items))
+    items = "Hello from Python".split()
+    expected = map( lambda x: x*2, items)
+    test_method(c.DoubleStringArray, (items,), expected)
+
+    test_method(c.CompareStringArrays, (items, items), cmp(items, items))
+    # Can we pass lists and tuples correctly?
+    test_method(c.CompareStringArrays, (items, tuple(items)), cmp(items, items))
+    items2 = ["Not", "the", "same"]
+    test_method(c.CompareStringArrays, (items, items2), cmp(items, items2))
+
+    expected = items[:]
+    expected.reverse()
+    test_method(c.ReverseStringArray, (items,), expected)
+
+    expected = "Hello from the Python test component".split()
+    test_method(c.GetStrings, (), expected)
+
+    val = "Hello\0there"
+    test_method(c.UpOctetArray, (val,), val.upper())
+    test_method(c.UpOctetArray, (unicode(val),), val.upper())
+    # Passing Unicode objects here used to cause us grief.
+    test_method(c.UpOctetArray2, (val,), val.upper())
+
+    test_method(c.CheckInterfaceArray, ((c, c),), 1)
+    test_method(c.CheckInterfaceArray, ((c, None),), 0)
+    test_method(c.CheckInterfaceArray, ((),), 1)
+    test_method(c.CopyInterfaceArray, ((c, c),), [c,c])
+
+    test_method(c.GetInterfaceArray, (), [c,c,c, None])
+    test_method(c.ExtendInterfaceArray, ((c,c,c, None),), [c,c,c,None,c,c,c,None] )
+
+    expected = [xpcom.components.interfaces.nsIPythonTestInterfaceDOMStrings, xpcom.components.classes[contractid].clsid]
+    test_method(c.GetIIDArray, (), expected)
+
+    val = [xpcom.components.interfaces.nsIPythonTestInterfaceExtra, xpcom.components.classes[contractid].clsid]
+    expected = val * 2
+    test_method(c.ExtendIIDArray, (val,), expected)
+
+    test_method(c.GetArrays, (), ( [1,2,3], [4,5,6] ) )
+    test_method(c.CopyArray, ([1,2,3],), [1,2,3] )
+    test_method(c.CopyAndDoubleArray, ([1,2,3],), [1,2,3,1,2,3] )
+    test_method(c.AppendArray, ([1,2,3],), [1,2,3])
+    test_method(c.AppendArray, ([1,2,3],[4,5,6]), [1,2,3,4,5,6])
+
+    test_method(c.CopyVariant, (None,), None)
+    test_method(c.CopyVariant, (1,), 1)
+    test_method(c.CopyVariant, (1.0,), 1.0)
+    test_method(c.CopyVariant, (-1,), -1)
+    test_method(c.CopyVariant, (sys.maxint+1,), sys.maxint+1)
+    test_method(c.CopyVariant, ("foo",), "foo")
+    test_method(c.CopyVariant, (u"foo",), u"foo")
+    test_method(c.CopyVariant, (c,), c)
+    test_method(c.CopyVariant, (component_iid,), component_iid)
+    test_method(c.CopyVariant, ((1,2),), [1,2])
+    test_method(c.CopyVariant, ((1.2,2.1),), [1.2,2.1])
+    test_method(c.CopyVariant, (("foo","bar"),), ["foo", "bar"])
+    test_method(c.CopyVariant, ((component_iid,component_iid),), [component_iid,component_iid])
+    test_method(c.CopyVariant, ((c,c),), [c,c])
+    sup = c.queryInterface(xpcom.components.interfaces.nsISupports)._comobj_
+    test_method(c.CopyVariant, ((sup, sup),), [sup,sup])
+    test_method(c.AppendVariant, (1,2), 3)
+    test_method(c.AppendVariant, ((1,2),(3,4)), 10)
+    test_method(c.AppendVariant, ("bar", "foo"), "foobar")
+    test_method(c.AppendVariant, (None, None), None)
+
+    test_method(c.SumVariants, ([],), None)
+    # Array's dont expose their interface, so we are unable to auto-wrap
+    # variant arrays, as they aren't aware if the IID of the array
+    test_method(c.SumVariants, ([MakeVariant(1),MakeVariant(2),MakeVariant(3)],), 6)
+    test_method(c.SumVariants, ([MakeVariant('foo'), MakeVariant('bar')],), 'foobar')
+
+    if not test_flat:
+        c = c.queryInterface(xpcom.components.interfaces.nsIPythonTestInterfaceDOMStrings)
+# NULL DOM strings don't work yet.
+#    test_method(c.GetDOMStringResult, (-1,), None)
+    test_method(c.GetDOMStringResult, (3,), "PPP")
+#    test_method(c.GetDOMStringOut, (-1,), None)
+    test_method(c.GetDOMStringOut, (4,), "yyyy")
+    val = "Hello there"
+    test_method(c.GetDOMStringLength, (val,), len(val))
+    test_method(c.GetDOMStringRefLength, (val,), len(val))
+    test_method(c.GetDOMStringPtrLength, (val,), len(val))
+    test_method(c.ConcatDOMStrings, (val,val), val+val)
+    test_attribute(c, "domstring_value", "dom", "new dom")
+    if c.domstring_value_ro != "dom":
+        print "Read-only DOMString not correct - got", c.domstring_ro
+    try:
+        c.dom_string_ro = "new dom"
+        print "Managed to set a readonly attribute - eek!"
+    except AttributeError:
+        pass
+    except:
+        print "Unexpected exception when setting readonly attribute: %s: %s" % (sys.exc_info()[0], sys.exc_info()[1])
+    if c.domstring_value_ro != "dom":
+        print "Read-only DOMString not correct after failed set attempt - got", c.domstring_ro
+
+def do_test_failures():
+    c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterfaceExtra)
+    try:
+        ret = c.do_nsISupportsIs( xpcom._xpcom.IID_nsIInterfaceInfoManager )
+        print "*** got", ret, "***"
+        raise RuntimeError, "We worked when using an IID we dont support!?!"
+    except xpcom.Exception, details:
+        if details.errno != xpcom.nsError.NS_ERROR_NO_INTERFACE:
+            raise RuntimeError, "Wrong COM exception type: %r" % (details,)
+
+def test_failures():
+    # This extra stack-frame ensures Python cleans up sys.last_traceback etc
+    do_test_failures()
+
+def test_all():
+    c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterface)
+    test_base_interface(c)
+    # Now create an instance using the derived IID, and test that.
+    c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterfaceExtra)
+    test_base_interface(c)
+    test_derived_interface(c)
+    # Now create an instance and test interface flattening.
+    c = xpcom.components.classes[contractid].createInstance()
+    test_base_interface(c)
+    test_derived_interface(c, test_flat=1)
+
+    # We had a bug where a "set" of an attribute before a "get" failed.
+    # Don't let it happen again :)
+    c = xpcom.components.classes[contractid].createInstance()
+    c.boolean_value = 0
+    
+    # This name is used in exceptions etc - make sure we got it from nsIClassInfo OK.
+    assert c._object_name_ == "Python.TestComponent"
+
+    test_failures()
+
+try:
+    from sys import gettotalrefcount
+except ImportError:
+    # Not a Debug build - assume no references (can't be leaks then :-)
+    def gettotalrefcount():
+        return 0
+
+from pyxpcom_test_tools import getmemusage
+
+def test_from_js():
+    # Ensure we can find the js test script - same dir as this!
+    # Assume the path of sys.argv[0] is where we can find the js test code.
+    # (Running under the regression test is a little painful)
+    script_dir = os.path.split(sys.argv[0])[0]
+    fname = os.path.join( script_dir, "test_test_component.js")
+    if not os.path.isfile(fname):
+        raise RuntimeError, "Can not find '%s'" % (fname,)
+    # Note we _dont_ pump the test output out, as debug "xpcshell" spews
+    # extra debug info that will cause our output comparison to fail.
+    data = os.popen('xpcshell "' + fname + '"').readlines()
+    good = 0
+    for line in data:
+        if line.strip() == "javascript successfully tested the Python test component.":
+            good = 1
+    if not good:
+        print "** The javascript test appeared to fail!  Test output follows **"
+        print "".join(data)
+        print "** End of javascript test output **"
+        raise RuntimeError, "test failed"
+
+def doit(num_loops = -1):
+    if "-v" in sys.argv: # Hack the verbose flag for the server
+        xpcom.verbose = 1
+    # Do the test lots of times - can help shake-out ref-count bugs.
+    if num_loops == -1: num_loops = 5
+    for i in xrange(num_loops):
+        test_all()
+
+        if i==0:
+            # First loop is likely to "leak" as we cache things.
+            # Leaking after that is a problem.
+            if gc is not None:
+                gc.collect()
+            num_refs = gettotalrefcount()
+            mem_usage = getmemusage()
+
+        if num_errors:
+            break
+
+    if gc is not None:
+        gc.collect()
+
+    lost = gettotalrefcount() - num_refs
+    # Sometimes we get spurious counts off by 1 or 2.
+    # This can't indicate a real leak, as we have looped
+    # more than twice!
+    if abs(lost)>3: # 2 or 3 :)
+        print "*** Lost %d references" % (lost,)
+
+    # sleep to allow the OS to recover
+    time.sleep(1)
+    mem_lost = getmemusage() - mem_usage
+    # working set size is fickle, and when we were leaking strings, this test
+    # would report a leak of 100MB.  So we allow a 3MB buffer - but even this
+    # may still occasionally report spurious warnings.  If you are really
+    # worried, bump the counter to a huge value, and if there is a leak it will
+    # show.
+    if mem_lost > 3000000:
+        print "*** Lost %.6f MB of memory" % (mem_lost/1000000.0,)
+
+    assert num_errors==0, "There were %d errors testing the Python component" % (num_errors,)
+
+def suite():
+    from pyxpcom_test_tools import suite_from_functions
+    return suite_from_functions(doit, test_from_js)
+
+if __name__=='__main__':
+    num_iters = 10 # times times is *lots* - we do a fair bit of work!
+    if __name__=='__main__' and len(sys.argv) > 1:
+        num_iters = int(sys.argv[1])
+
+    print "Testing the Python.TestComponent component"
+    doit(num_iters)
+    print "The Python test component worked."
+    test_from_js()
+    print "JS successfully used our Python test component."
+    xpcom._xpcom.NS_ShutdownXPCOM()
+    ni = xpcom._xpcom._GetInterfaceCount()
+    ng = xpcom._xpcom._GetGatewayCount()
+    if ni or ng:
+        print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
Index: trunk/src/libs/xpcom18a4/python/test/test_weakreferences.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/test/test_weakreferences.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/test/test_weakreferences.py	(revision 11746)
@@ -0,0 +1,114 @@
+# ***** 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, 2001
+# 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 *****
+
+# test_weakreferences.py - Test our weak reference implementation.
+from xpcom import components, _xpcom
+import xpcom.server, xpcom.client
+from pyxpcom_test_tools import suite_from_functions, testmain
+
+try:
+    from sys import gettotalrefcount
+except ImportError:
+    # Not a Debug build - assume no references (can't be leaks then :-)
+    gettotalrefcount = lambda: 0
+
+num_alive = 0
+
+class koTestSimple:
+    _com_interfaces_ = [components.interfaces.nsIInputStream]
+    def __init__(self):
+        global num_alive
+        num_alive += 1
+    def __del__(self):
+        global num_alive
+        num_alive -= 1
+    def close( self ):
+        pass
+
+def test():
+    ob = xpcom.server.WrapObject( koTestSimple(), components.interfaces.nsIInputStream)
+
+    if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
+
+    # Check we can create a weak reference to our object.
+    wr = xpcom.client.WeakReference(ob)
+    if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
+
+    # Check we can call methods via the weak reference.
+    if wr() is None: raise RuntimeError, "Our weak-reference is returning None before it should!"
+    wr().close()
+
+    ob  = None # This should kill the object.    
+    if num_alive != 0: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
+    if wr() is not None: raise RuntimeError, "Our weak-reference is not returning None when it should!"
+
+    # Now a test that we can get a _new_ interface from the weak reference - ie,
+    # an IID the real object has never previously been queried for
+    # (this behaviour previously caused a bug - never again ;-)
+    ob = xpcom.server.WrapObject( koTestSimple(), components.interfaces.nsISupports)
+    if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
+    wr = xpcom.client.WeakReference(ob, components.interfaces.nsIInputStream)
+    if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
+    wr() # This would die once upon a time ;-)
+    ob  = None # This should kill the object.    
+    if num_alive != 0: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
+    if wr() is not None: raise RuntimeError, "Our weak-reference is not returning None when it should!"
+
+def test_refcount(num_loops=-1):
+    # Do the test lots of times - can help shake-out ref-count bugs.
+    if num_loops == -1: num_loops = 10
+    for i in xrange(num_loops):
+        test()
+
+        if i==0:
+            # First loop is likely to "leak" as we cache things.
+            # Leaking after that is a problem.
+            num_refs = gettotalrefcount()
+
+    lost = gettotalrefcount() - num_refs
+    # Sometimes we get spurious counts off by 1 or 2.
+    # This can't indicate a real leak, as we have looped
+    # more than twice!
+    if abs(lost)>2:
+        print "*** Lost %d references" % (lost,)
+
+# Make this test run under our std test suite
+def suite():
+    return suite_from_functions(test_refcount)
+
+if __name__=='__main__':
+    testmain()
Index: trunk/src/libs/xpcom18a4/python/tools/regxpcom.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/tools/regxpcom.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/tools/regxpcom.py	(revision 11746)
@@ -0,0 +1,68 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# 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 *****
+
+# regxpcom.py - basically the standard regxpcom.cpp ported to Python.
+# In general, you should use regxpcom.exe instead of this.
+
+from xpcom import components, _xpcom
+from xpcom.client import Component
+import sys
+import os
+
+registrar = Component(_xpcom.GetComponentRegistrar(),
+                      components.interfaces.nsIComponentRegistrar)
+
+def ProcessArgs(args):
+
+    unregister = 0
+    for arg in args:
+        spec = components.classes['@mozilla.org/file/local;1'].createInstance()
+        spec = spec.QueryInterface(components.interfaces.nsILocalFile)
+        spec.initWithPath(os.path.abspath(arg))
+        if arg == "-u":
+            registrar.autoUnregister(spec)
+            print "Successfully unregistered", spec.path
+        else:
+            registrar.autoRegister(spec)
+            print "Successfully registered", spec.path
+
+if len(sys.argv) < 2:
+    registrar.autoRegister( None)
+else:
+    ProcessArgs(sys.argv[1:])
+
+#_xpcom.NS_ShutdownXPCOM()
Index: trunk/src/libs/xpcom18a4/python/tools/tracer_demo.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/tools/tracer_demo.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/tools/tracer_demo.py	(revision 11746)
@@ -0,0 +1,113 @@
+# ***** 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 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, 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 is a demo is how to use the xpcom.server "tracer" facility.
+#
+# This demo installs a tracer that uses the Python profiler.  It then
+# creates the Python test component, and references some methods
+# and properties.  It then dumps the profile statistics.
+
+# This same technique could also be used for debugging, for example.
+
+import profile
+
+p = profile.Profile()
+getters = {}
+setters = {}
+
+# A wrapper around a function - looks like a function,
+# but actually profiles the delegate.
+class TracerDelegate:
+    def __init__(self, callme):
+        self.callme = callme
+    def __call__(self, *args):
+        return p.runcall(self.callme, *args)
+
+# A wrapper around each of our XPCOM objects.  All PyXPCOM calls
+# in are made on this object, which creates a TracerDelagate around
+# every function.  As the function is called, it collects profile info.
+class Tracer:
+    def __init__(self, ob):
+        self.__dict__['_ob'] = ob
+    def __repr__(self):
+        return "<Tracer around %r>" % (self._ob,)
+    def __str__(self):
+        return "<Tracer around %r>" % (self._ob,)
+    def __getattr__(self, attr):
+        ret = getattr(self._ob, attr) # Attribute error just goes up
+        if callable(ret):
+            return TracerDelegate(ret)
+        else:
+            if not attr.startswith("_com_") and not attr.startswith("_reg_"):
+                getters[attr] = getters.setdefault(attr,0) + 1
+            return ret
+    def __setattr__(self, attr, val):
+        if self.__dict__.has_key(attr):
+            self.__dict__[attr] = val
+            return
+        setters[attr] = setters.setdefault(attr,0) + 1
+        setattr(self._ob, attr, val)
+
+# Installed as a global XPCOM function that if exists, will be called
+# to wrap each XPCOM object created.
+def MakeTracer(ob):
+    # In some cases we may be asked to wrap ourself, so handle that.
+    if isinstance(ob, Tracer):
+        return ob
+    return Tracer(ob)
+
+def test():
+    import xpcom.server, xpcom.components
+    xpcom.server.tracer = MakeTracer
+    contractid = "Python.TestComponent"
+    for i in range(100):
+        c = xpcom.components.classes[contractid].createInstance().queryInterface(xpcom.components.interfaces.nsIPythonTestInterface)
+        c.boolean_value = 0
+        a = c.boolean_value
+        c.do_boolean(0,1)
+    print "Finshed"
+    p.print_stats()
+    print "%-30s%s" % ("Attribute Gets", "Number")
+    print "-" * 36
+    for name, num in getters.items():
+        print "%-30s%d" % (name, num)
+    print "%-30s%s" % ("Attribute Sets", "Number")
+    print "-" * 36
+    for name, num in setters.items():
+        print "%-30s%d" % (name, num)
+
+test()
Index: trunk/src/libs/xpcom18a4/python/vboxxpcom.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/vboxxpcom.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/vboxxpcom.py	(revision 11746)
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2008 Sun Microsystems, Inc.
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
+# Clara, CA 95054 USA or visit http://www.sun.com if you need
+# additional information or have any questions.
+#
+
+import xpcom
+import sys
+
+# this code overcomes somewhat unlucky feature of Python, where it searches
+# for binaries in the same place as platfom independent modules, while
+# rest of Python bindings expect _xpcom to be inside xpcom module
+# XXX: maybe implement per Python version module search
+cglue = __import__('VBoxPython')
+sys.modules['xpcom._xpcom'] = cglue
+xpcom._xpcom = cglue
Index: trunk/src/libs/xpcom18a4/python/xpcom_consts.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/xpcom_consts.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/xpcom_consts.py	(revision 11746)
@@ -0,0 +1,272 @@
+# ***** 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, 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 *****
+
+# Could maybe later have a process that extracted these enums should they change.
+# from nsFileLocations.h
+App_DirectoryBase              = 0x00010000
+App_PrefsDirectory30           = App_DirectoryBase +    1 
+App_PrefsDirectory40           = App_DirectoryBase +    2
+App_PrefsDirectory50           = App_DirectoryBase +    3
+App_ResDirectory               = App_DirectoryBase +    5
+App_UserProfileDirectory30     = App_DirectoryBase +   10
+App_UserProfileDirectory40     = App_DirectoryBase +   11
+App_UserProfileDirectory50     = App_DirectoryBase +   12
+App_DefaultUserProfileRoot30   = App_DirectoryBase +   13
+App_DefaultUserProfileRoot40   = App_DirectoryBase +   14
+App_DefaultUserProfileRoot50   = App_DirectoryBase +   15
+App_ProfileDefaultsFolder30    = App_DirectoryBase +   16
+App_ProfileDefaultsFolder40    = App_DirectoryBase +   17
+App_ProfileDefaultsFolder50    = App_DirectoryBase +   18
+App_PrefDefaultsFolder50       = App_DirectoryBase +   19
+App_DefaultsFolder50           = App_DirectoryBase +   25
+App_ComponentsDirectory        = App_DirectoryBase +   30
+App_ChromeDirectory            = App_DirectoryBase +   31
+App_PluginsDirectory           = App_DirectoryBase +   32
+App_UserChromeDirectory        = App_DirectoryBase +   40
+App_FileBase                   = App_DirectoryBase + 1000
+App_PreferencesFile30          = App_FileBase      +    1
+App_PreferencesFile40          = App_FileBase      +    2
+App_PreferencesFile50          = App_FileBase      +    3
+App_BookmarksFile30            = App_FileBase      +   10
+App_BookmarksFile40            = App_FileBase      +   11
+App_BookmarksFile50            = App_FileBase      +   12
+App_Registry40                 = App_FileBase      +   20
+App_Registry50                 = App_FileBase      +   21
+App_LocalStore50               = App_FileBase   +  30
+App_History50              = App_FileBase   +  40
+App_MailDirectory50        = App_FileBase   +  50
+App_ImapMailDirectory50    = App_FileBase   +  60
+App_NewsDirectory50        = App_FileBase   +  70
+App_MessengerFolderCache50 = App_FileBase   +  80
+App_UsersPanels50          = App_FileBase   +  90
+App_SearchFile50           = App_FileBase   + 100
+App_SearchDirectory50      = App_FileBase   + 101
+
+# From nsSpecialSystemDirectory.h
+OS_DriveDirectory         =   1
+OS_TemporaryDirectory     =   2
+OS_CurrentProcessDirectory=   3
+OS_CurrentWorkingDirectory=   4
+
+XPCOM_CurrentProcessComponentDirectory=   5
+XPCOM_CurrentProcessComponentRegistry=   6            
+
+Moz_BinDirectory          = 10
+
+Mac_SystemDirectory       =   101
+Mac_DesktopDirectory      =   102
+Mac_TrashDirectory        =   103
+Mac_StartupDirectory      =   104
+Mac_ShutdownDirectory     =   105
+Mac_AppleMenuDirectory    =   106
+Mac_ControlPanelDirectory =   107
+Mac_ExtensionDirectory    =   108
+Mac_FontsDirectory        =   109
+Mac_PreferencesDirectory  =   110
+Mac_DocumentsDirectory    =   111
+Mac_InternetSearchDirectory    =   112
+
+Win_SystemDirectory       =   201
+Win_WindowsDirectory      =   202
+
+Win_HomeDirectory         =   203
+Win_Desktop               =   204    
+Win_Programs              =   205    
+Win_Controls              =   206    
+Win_Printers              =   207    
+Win_Personal              =   208    
+Win_Favorites             =   209    
+Win_Startup               =   210    
+Win_Recent                =   211    
+Win_Sendto                =   212    
+Win_Bitbucket             =   213    
+Win_Startmenu             =   214    
+Win_Desktopdirectory      =   215    
+Win_Drives                =   216    
+Win_Network               =   217    
+Win_Nethood               =   218    
+Win_Fonts                 =   219    
+Win_Templates             =   220    
+Win_Common_Startmenu      =   221    
+Win_Common_Programs       =   222    
+Win_Common_Startup        =   223   
+Win_Common_Desktopdirectory = 224   
+Win_Appdata               =   225    
+Win_Printhood             =   226    
+
+Unix_LocalDirectory       =   301
+Unix_LibDirectory         =   302
+Unix_HomeDirectory        =   303
+
+BeOS_SettingsDirectory    =   401
+BeOS_HomeDirectory        =   402
+BeOS_DesktopDirectory     =   403
+BeOS_SystemDirectory      =   404
+
+OS2_SystemDirectory        =   501
+
+# Type/Variant related constants.
+TD_INT8              = 0
+TD_INT16             = 1
+TD_INT32             = 2
+TD_INT64             = 3
+TD_UINT8             = 4
+TD_UINT16            = 5
+TD_UINT32            = 6
+TD_UINT64            = 7
+TD_FLOAT             = 8
+TD_DOUBLE            = 9
+TD_BOOL              = 10
+TD_CHAR              = 11 
+TD_WCHAR             = 12
+TD_VOID              = 13  
+TD_PNSIID            = 14
+TD_DOMSTRING     = 15
+TD_PSTRING           = 16
+TD_PWSTRING          = 17
+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
+
+# From xpt_struct.h
+XPT_TDP_POINTER          = 0x80
+XPT_TDP_UNIQUE_POINTER   = 0x40
+XPT_TDP_REFERENCE        = 0x20
+XPT_TDP_FLAGMASK         = 0xe0
+XPT_TDP_TAGMASK          = (~XPT_TDP_FLAGMASK)
+def XPT_TDP_TAG(tdp): return (tdp & XPT_TDP_TAGMASK)
+
+def XPT_TDP_IS_POINTER(flags): return (flags & XPT_TDP_POINTER)
+def XPT_TDP_IS_UNIQUE_POINTER(flags): return (flags & XPT_TDP_UNIQUE_POINTER)
+def XPT_TDP_IS_REFERENCE(flags): return (flags & XPT_TDP_REFERENCE)
+
+XPT_ID_SCRIPTABLE           = 0x80
+XPT_ID_FLAGMASK             = 0x80
+XPT_ID_TAGMASK              = ~XPT_ID_FLAGMASK
+def XPT_ID_TAG(id): return id & XPT_ID_TAGMASK
+
+def XPT_ID_IS_SCRIPTABLE(flags): return flags & XPT_ID_SCRIPTABLE
+
+XPT_PD_IN       = 0x80
+XPT_PD_OUT      = 0x40
+XPT_PD_RETVAL   = 0x20
+XPT_PD_SHARED   = 0x10
+XPT_PD_DIPPER   = 0x08
+XPT_PD_FLAGMASK = 0xf0
+
+def XPT_PD_IS_IN(flags): return (flags & XPT_PD_IN)
+def XPT_PD_IS_OUT(flags): return (flags & XPT_PD_OUT)
+def XPT_PD_IS_RETVAL(flags): return (flags & XPT_PD_RETVAL)
+def XPT_PD_IS_SHARED(flags): return (flags & XPT_PD_SHARED)
+def XPT_PD_IS_DIPPER(flags): return (flags & XPT_PD_DIPPER)
+
+XPT_MD_GETTER = 0x80
+XPT_MD_SETTER = 0x40
+XPT_MD_NOTXPCOM = 0x20
+XPT_MD_CTOR = 0x10
+XPT_MD_HIDDEN = 0x08
+XPT_MD_FLAGMASK = 0xf8
+
+def XPT_MD_IS_GETTER(flags):     return (flags & XPT_MD_GETTER)
+def XPT_MD_IS_SETTER(flags):     return (flags & XPT_MD_SETTER)
+def XPT_MD_IS_NOTXPCOM(flags):   return (flags & XPT_MD_NOTXPCOM)
+def XPT_MD_IS_CTOR(flags):       return (flags & XPT_MD_CTOR)
+def XPT_MD_IS_HIDDEN(flags):     return (flags & XPT_MD_HIDDEN)
+
+# From xptinfo.h
+
+T_I8                = TD_INT8
+T_I16               = TD_INT16
+T_I32               = TD_INT32
+T_I64               = TD_INT64
+T_U8                = TD_UINT8
+T_U16               = TD_UINT16
+T_U32               = TD_UINT32
+T_U64               = TD_UINT64
+T_FLOAT             = TD_FLOAT
+T_DOUBLE            = TD_DOUBLE
+T_BOOL              = TD_BOOL
+T_CHAR              = TD_CHAR
+T_WCHAR             = TD_WCHAR
+T_VOID              = TD_VOID
+T_IID               = TD_PNSIID
+T_DOMSTRING        = TD_DOMSTRING
+T_CHAR_STR          = TD_PSTRING
+T_WCHAR_STR         = TD_PWSTRING
+T_INTERFACE         = TD_INTERFACE_TYPE
+T_INTERFACE_IS      = TD_INTERFACE_IS_TYPE
+T_ARRAY             = TD_ARRAY
+T_PSTRING_SIZE_IS   = TD_PSTRING_SIZE_IS
+T_PWSTRING_SIZE_IS  = TD_PWSTRING_SIZE_IS
+T_UTF8STRING        = TD_UTF8STRING
+T_CSTRING           = TD_CSTRING
+T_ASTRING           = TD_ASTRING
+
+# from nsIVariant
+VTYPE_INT8 = 0
+VTYPE_INT16 = 1
+VTYPE_INT32 = 2
+VTYPE_INT64 = 3
+VTYPE_UINT8 = 4
+VTYPE_UINT16 = 5
+VTYPE_UINT32 = 6
+VTYPE_UINT64 = 7
+VTYPE_FLOAT = 8
+VTYPE_DOUBLE = 9
+VTYPE_BOOL = 10
+VTYPE_CHAR = 11
+VTYPE_WCHAR = 12
+VTYPE_VOID = 13
+VTYPE_ID = 14
+VTYPE_DOMSTRING = 15
+VTYPE_CHAR_STR = 16
+VTYPE_WCHAR_STR = 17
+VTYPE_INTERFACE = 18
+VTYPE_INTERFACE_IS = 19
+VTYPE_ARRAY = 20
+VTYPE_STRING_SIZE_IS = 21
+VTYPE_WSTRING_SIZE_IS = 22
+VTYPE_UTF8STRING = 23
+VTYPE_CSTRING = 24
+VTYPE_ASTRING = 25
+VTYPE_EMPTY_ARRAY = 254
+VTYPE_EMPTY = 255
Index: trunk/src/libs/xpcom18a4/python/xpt.py
===================================================================
--- trunk/src/libs/xpcom18a4/python/xpt.py	(revision 11746)
+++ trunk/src/libs/xpcom18a4/python/xpt.py	(revision 11746)
@@ -0,0 +1,471 @@
+# ***** 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, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   David Ascher <DavidA@ActiveState.com> (original author)
+#   Mark Hammond <mhammond@skippinet.com.au>
+#
+# 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 *****
+
+"""
+Program: xpt.py
+
+Task: describe interfaces etc using XPCOM reflection.
+
+Subtasks:
+     output (nearly) exactly the same stuff as xpt_dump, for verification
+     output Python source code that can be used as a template for an interface
+
+Status: Works pretty well if you ask me :-)
+
+Author:
+   David Ascher did an original version that parsed XPT files
+   directly.  Mark Hammond changed it to use the reflection interfaces,
+   but kept most of the printing logic.
+
+
+Revision:
+
+  0.1: March 6, 2000
+  0.2: April 2000 - Mark removed lots of Davids lovely parsing code in favour
+                    of the new xpcom interfaces that provide this info.
+
+  May 2000 - Moved into Perforce - track the log there!
+  Early 2001 - Moved into the Mozilla CVS tree - track the log there!  
+
+Todo:
+  Fill out this todo list.
+
+"""
+
+import string, sys
+import xpcom
+import xpcom._xpcom
+
+from xpcom_consts import *
+
+class Interface:
+    def __init__(self, iid):
+        iim = xpcom._xpcom.XPTI_GetInterfaceInfoManager()
+        if hasattr(iid, "upper"): # Is it a stringy thing.
+            item = iim.GetInfoForName(iid)
+        else:
+            item = iim.GetInfoForIID(iid)
+        self.interface_info = item
+        self.namespace = "" # where does this come from?
+        self.methods = Methods(item)
+        self.constants = Constants(item)
+
+    # delegate attributes to the real interface
+    def __getattr__(self, attr):
+        return getattr(self.interface_info, attr)
+
+    def GetParent(self):
+        try:
+            raw_parent = self.interface_info.GetParent()
+            if raw_parent is None:
+                return None
+            return Interface(raw_parent.GetIID())
+        except xpcom.Exception:
+            # Parent interface is probably not scriptable - assume nsISupports.
+            if xpcom.verbose:
+                # The user may be confused as to why this is happening!
+                print "The parent interface of IID '%s' can not be located - assuming nsISupports"
+            return Interface(xpcom._xpcom.IID_nsISupports)
+
+    def Describe_Python(self):
+        method_reprs = []
+        methods = filter(lambda m: not m.IsNotXPCOM(), self.methods)
+        for m in methods:
+            method_reprs.append(m.Describe_Python())
+        method_joiner = "\n"
+        methods_repr = method_joiner.join(method_reprs)
+        return \
+"""class %s:
+    _com_interfaces_ = xpcom.components.interfaces.%s
+    # If this object needs to be registered, the following 2 are also needed.
+    # _reg_clsid_ = "{a new clsid generated for this object}"
+    # _reg_contractid_ = "The.Object.Name"\n%s""" % (self.GetName(), self.GetIID().name, methods_repr)
+
+    def Describe(self):
+        # Make the IID look like xtp_dump - "(" instead of "{"
+        iid_use = "(" + str(self.GetIID())[1:-1] + ")"
+        s = '   - '+self.namespace+'::'+ self.GetName() + ' ' + iid_use + ':\n'
+
+        parent = self.GetParent()
+        if parent is not None:
+            s = s + '      Parent: ' + parent.namespace + '::' + parent.GetName() + '\n'
+        s = s + '      Flags:\n'
+        if self.IsScriptable(): word = 'TRUE'
+        else: word = 'FALSE'
+        s = s + '         Scriptable: ' + word + '\n'
+        s = s + '      Methods:\n'
+        methods = filter(lambda m: not m.IsNotXPCOM(), self.methods)
+        if len(methods):
+            for m in methods:
+                s = s + '   ' + m.Describe() + '\n'
+        else:
+            s = s + '         No Methods\n'
+        s = s + '      Constants:\n'
+        if self.constants:
+            for c in self.constants:
+                s = s + '         ' + c.Describe() + '\n'
+        else:
+            s = s + '         No Constants\n'
+
+        return s
+
+# A class that allows caching and iterating of methods.
+class Methods:
+    def __init__(self, interface_info):
+        self.interface_info = interface_info
+        try:
+            self.items = [None] * interface_info.GetMethodCount()
+        except xpcom.Exception:
+            if xpcom.verbose:
+                print "** GetMethodCount failed?? - assuming no methods"
+            self.items = []
+    def __len__(self):
+        return len(self.items)
+    def __getitem__(self, index):
+        ret = self.items[index]
+        if ret is None:
+            mi = self.interface_info.GetMethodInfo(index)
+            ret = self.items[index] = Method(mi, index, self.interface_info)
+        return ret
+
+class Method:
+
+    def __init__(self, method_info, method_index, interface_info = None):
+        self.interface_info = interface_info
+        self.method_index = method_index
+        self.flags, self.name, param_descs, self.result_desc = method_info
+        # Build the params.
+        self.params = []
+        pi=0
+        for pd in param_descs:
+            self.params.append( Parameter(pd, pi, method_index, interface_info) )
+            pi = pi + 1
+        # Run over the params setting the "sizeof" params to hidden.
+        for p in self.params:
+            td = p.type_desc
+            tag = XPT_TDP_TAG(td[0])
+            if tag==T_ARRAY and p.IsIn():
+                self.params[td[1]].hidden_indicator = 2
+            elif tag in [T_PSTRING_SIZE_IS, T_PWSTRING_SIZE_IS] and p.IsIn():
+                self.params[td[1]].hidden_indicator = 1
+
+    def IsGetter(self):
+        return (self.flags & XPT_MD_GETTER)
+    def IsSetter(self):
+        return (self.flags & XPT_MD_SETTER)
+    def IsNotXPCOM(self):
+        return (self.flags & XPT_MD_NOTXPCOM)
+    def IsConstructor(self):
+        return (self.flags & XPT_MD_CTOR)
+    def IsHidden(self):
+        return (self.flags & XPT_MD_HIDDEN)
+
+    def Describe_Python(self):
+        if self.method_index < 3: # Ignore QI etc
+            return ""
+        base_name = self.name
+        if self.IsGetter():
+            name = "get_%s" % (base_name,)
+        elif self.IsSetter():
+            name = "set_%s" % (base_name,)
+        else:
+            name = base_name
+        param_decls = ["self"]
+        in_comments = []
+        out_descs = []
+        result_comment = "Result: void - None"
+        for p in self.params:
+            in_desc, in_desc_comments, out_desc, this_result_comment = p.Describe_Python()
+            if in_desc is not None:
+                param_decls.append(in_desc)
+            if in_desc_comments is not None:
+                in_comments.append(in_desc_comments)
+            if out_desc is not None:
+                out_descs.append(out_desc)
+            if this_result_comment is not None:
+                result_comment = this_result_comment
+        joiner = "\n        # "
+        in_comment = out_desc = ""
+        if in_comments: in_comment = joiner + joiner.join(in_comments)
+        if out_descs: out_desc = joiner + joiner.join(out_descs)
+
+        return """    def %s( %s ):
+        # %s%s%s
+        pass""" % (name, ", ".join(param_decls), result_comment, in_comment, out_desc)
+
+    def Describe(self):
+        s = ''
+        if self.IsGetter():
+            G = 'G'
+        else:
+            G = ' '
+        if self.IsSetter():
+            S = 'S'
+        else: S = ' '
+        if self.IsHidden():
+            H = 'H'
+        else:
+            H = ' '
+        if self.IsNotXPCOM():
+            N = 'N'
+        else:
+            N = ' '
+        if self.IsConstructor():
+            C = 'C'
+        else:
+            C = ' '
+
+        def desc(a): return a.Describe()
+        method_desc = string.join(map(desc, self.params), ', ')
+        result_type = TypeDescriber(self.result_desc[0], None)
+        return_desc = result_type.Describe()
+        i = string.find(return_desc, 'retval ')
+        if i != -1:
+            return_desc = return_desc[:i] + return_desc[i+len('retval '):]
+        return G+S+H+N+C+' '+return_desc+' '+self.name + '('+ method_desc + ');'
+
+class Parameter:
+    def __init__(self,  param_desc, param_index, method_index, interface_info = None):
+        self.param_flags, self.type_desc = param_desc
+        self.hidden_indicator = 0 # Is this a special "size" type param that will be hidden from Python?
+        self.param_index = param_index
+        self.method_index= method_index
+        self.interface_info = interface_info
+    def __repr__(self):
+        return "<param %(param_index)d (method %(method_index)d) - flags = 0x%(param_flags)x, type = %(type_desc)s>" % self.__dict__
+    def IsIn(self):
+        return XPT_PD_IS_IN(self.param_flags)
+    def IsOut(self):
+        return XPT_PD_IS_OUT(self.param_flags)
+    def IsInOut(self):
+        return self.IsIn() and self.IsOut()
+    def IsRetval(self):
+        return XPT_PD_IS_RETVAL(self.param_flags)
+    def IsShared(self):
+        return XPT_PD_IS_SHARED(self.param_flags)
+    def IsDipper(self):
+        return XPT_PD_IS_DIPPER(self.param_flags)
+
+    def Describe_Python(self):
+        name = "param%d" % (self.param_index,)
+        if self.hidden_indicator:
+            # Could remove the comment - Im trying to tell the user where that param has
+            # gone from the signature!
+            return None, "%s is a hidden parameter" % (name,), None, None
+        t = TypeDescriber(self.type_desc[0], self)
+        decl = in_comment = out_comment = result_comment = None
+        type_desc = t.Describe()
+        if self.IsIn() and not self.IsDipper():
+            decl = name
+            extra=""
+            if self.IsOut():
+                extra = "Out"
+            in_comment = "In%s: %s: %s" % (extra, name, type_desc)
+        elif self.IsOut() or self.IsDipper():
+            if self.IsRetval():
+                result_comment = "Result: %s" % (type_desc,)
+            else:
+                out_comment = "Out: %s" % (type_desc,)
+        return decl, in_comment, out_comment, result_comment
+
+    def Describe(self):
+        parts = []
+        if self.IsInOut():
+            parts.append('inout')
+        elif self.IsIn():
+            parts.append('in')
+        elif self.IsOut():
+            parts.append('out')
+
+        if self.IsDipper(): parts.append("dipper")
+        if self.IsRetval(): parts.append('retval')
+        if self.IsShared(): parts.append('shared')
+        t = TypeDescriber(self.type_desc[0], self)
+        type_str = t.Describe()
+        parts.append(type_str)
+        return string.join(parts)
+
+# A class that allows caching and iterating of constants.
+class Constants:
+    def __init__(self, interface_info):
+        self.interface_info = interface_info
+        try:
+            self.items = [None] * interface_info.GetConstantCount()
+        except xpcom.Exception:
+            if xpcom.verbose:
+                print "** GetConstantCount failed?? - assuming no constants"
+            self.items = []
+    def __len__(self):
+        return len(self.items)
+    def __getitem__(self, index):
+        ret = self.items[index]
+        if ret is None:
+            ci = self.interface_info.GetConstant(index)
+            ret = self.items[index] = Constant(ci)
+        return ret
+
+class Constant:
+    def __init__(self, ci):
+        self.name, self.type, self.value = ci
+
+    def Describe(self):
+        return TypeDescriber(self.type, None).Describe() + ' ' +self.name+' = '+str(self.value)+';'
+
+    __str__ = Describe
+
+def MakeReprForInvoke(param):
+    tag = param.type_desc[0] & XPT_TDP_TAGMASK
+    if tag == T_INTERFACE:
+        i_info = param.interface_info
+        try:
+            iid = i_info.GetIIDForParam(param.method_index, param.param_index)
+        except xpcom.Exception:
+            # IID not available (probably not scriptable) - just use nsISupports.
+            iid = xpcom._xpcom.IID_nsISupports
+        return param.type_desc[0], 0, 0, str(iid)
+    elif tag == T_ARRAY:
+        i_info = param.interface_info
+        array_desc = i_info.GetTypeForParam(param.method_index, param.param_index, 1)
+        return param.type_desc[:-1] + array_desc[:1]
+    return param.type_desc
+
+
+class TypeDescriber:
+    def __init__(self, type_flags, param):
+        self.type_flags = type_flags
+        self.tag = XPT_TDP_TAG(self.type_flags)
+        self.param = param
+    def IsPointer(self):
+        return XPT_TDP_IS_POINTER(self.type_flags)
+    def IsUniquePointer(self):
+        return XPT_TDP_IS_UNIQUE_POINTER(self.type_flags)
+    def IsReference(self):
+        return XPT_TDP_IS_REFERENCE(self.type_flags)
+    def repr_for_invoke(self):
+        return (self.type_flags,)
+    def GetName(self):
+        is_ptr = self.IsPointer()
+        data = type_info_map.get(self.tag)
+        if data is None:
+            data = ("unknown",)
+        if self.IsReference():
+            if len(data) > 2:
+                return data[2]
+            return data[0] + " &"
+        if self.IsPointer():
+            if len(data)>1:
+                return data[1]
+            return data[0] + " *"
+        return data[0]
+
+    def Describe(self):
+        if self.tag == T_ARRAY:
+            # NOTE - Adding a type specifier to the array is different from xpt_dump.exe
+            if self.param is None or self.param.interface_info is None:
+                type_desc = "" # Dont have explicit info about the array type :-(
+            else:
+                i_info = self.param.interface_info
+                type_code = i_info.GetTypeForParam(self.param.method_index, self.param.param_index, 1)
+                type_desc = TypeDescriber( type_code[0], None).Describe()
+            return self.GetName() + "[" + type_desc + "]" 
+        elif self.tag == T_INTERFACE:
+            if self.param is None or self.param.interface_info is None:
+                return "nsISomething" # Dont have explicit info about the IID :-(
+            i_info = self.param.interface_info
+            m_index = self.param.method_index
+            p_index = self.param.param_index
+            try:
+                iid = i_info.GetIIDForParam(m_index, p_index)
+                return iid.name
+            except xpcom.Exception:
+                return "nsISomething"
+        return self.GetName()
+
+# These are just for output purposes, so should be
+# the same as xpt_dump uses
+type_info_map = {
+    T_I8                : ("int8",),
+    T_I16               : ("int16",),
+    T_I32               : ("int32",),
+    T_I64               : ("int64",),
+    T_U8                : ("uint8",),
+    T_U16               : ("uint16",),
+    T_U32               : ("uint32",),
+    T_U64               : ("uint64",),
+    T_FLOAT             : ("float",),
+    T_DOUBLE            : ("double",),
+    T_BOOL              : ("boolean",),
+    T_CHAR              : ("char",),
+    T_WCHAR             : ("wchar_t", "wstring"),
+    T_VOID              : ("void",),
+    T_IID               : ("reserved", "nsIID *", "nsIID &"),
+    T_DOMSTRING         : ("DOMString",),
+    T_CHAR_STR          : ("reserved", "string"),
+    T_WCHAR_STR         : ("reserved", "wstring"),
+    T_INTERFACE         : ("reserved", "Interface"),
+    T_INTERFACE_IS      : ("reserved", "InterfaceIs *"),
+    T_ARRAY             : ("reserved", "Array"),
+    T_PSTRING_SIZE_IS   : ("reserved", "string_s"),
+    T_PWSTRING_SIZE_IS  : ("reserved", "wstring_s"),
+}
+
+def dump_interface(iid, mode):
+    interface = Interface(iid)
+    describer_name = "Describe"
+    if mode == "xptinfo": mode = None
+    if mode is not None:
+        describer_name = describer_name + "_" + mode.capitalize()
+    describer = getattr(interface, describer_name)
+    print describer()
+
+if __name__=='__main__':
+    if len(sys.argv) == 1:
+        print "Usage: xpt.py [-xptinfo] interface_name, ..."
+        print "  -info: Dump in a style similar to the xptdump tool"
+        print "Dumping nsISupports and nsIInterfaceInfo"
+        sys.argv.append('nsIInterfaceInfo')
+        sys.argv.append('-xptinfo')
+        sys.argv.append('nsISupports')
+        sys.argv.append('nsIInterfaceInfo')
+
+    mode = "Python"
+    for i in sys.argv[1:]:
+        if i[0] == "-":
+            mode = i[1:]
+        else:
+            dump_interface(i, mode)
