Index: /trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp
===================================================================
--- /trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp	(revision 6849)
+++ /trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp	(revision 6850)
@@ -69,5 +69,4 @@
 // XXX TODO:
 //  1. add thread affinity field to SETUP messages
-//  2. support array parameters
 
 //-----------------------------------------------------------------------------
@@ -85,8 +84,4 @@
 
 #define DCON_WAIT_TIMEOUT PR_INTERVAL_NO_TIMEOUT
-
-// used elsewhere like nsAtomTable to safely represent the integral value
-// of an address.
-typedef unsigned long PtrBits;
 
 //-----------------------------------------------------------------------------
@@ -274,5 +269,5 @@
     return count;
   }
-  
+
 private:
   nsAutoRefCnt               mRefCnt;
@@ -410,6 +405,163 @@
 
     case nsXPTType::T_ARRAY:
-      LOG(("array types are not yet supported\n"));
-      return NS_ERROR_NOT_IMPLEMENTED;
+      // arrays are serialized after all other params outside this routine
+      break;
+
+    case nsXPTType::T_VOID:
+    case nsXPTType::T_PSTRING_SIZE_IS:
+    case nsXPTType::T_PWSTRING_SIZE_IS:
+    default:
+      LOG(("unexpected parameter type: %d\n", t.TagPart()));
+      return NS_ERROR_UNEXPECTED;
+  }
+  return NS_OK;
+}
+
+static nsresult
+DeserializeParam(ipcMessageReader &reader, const nsXPTType &t, nsXPTCVariant &v)
+{
+  // defaults
+  v.ptr = nsnull;
+  v.type = t;
+  v.flags = 0;
+
+  switch (t.TagPart())
+  {
+    case nsXPTType::T_I8:
+    case nsXPTType::T_U8:
+      v.val.u8 = reader.GetInt8();
+      break;
+
+    case nsXPTType::T_I16:
+    case nsXPTType::T_U16:
+      v.val.u16 = reader.GetInt16();
+      break;
+
+    case nsXPTType::T_I32:
+    case nsXPTType::T_U32:
+      v.val.u32 = reader.GetInt32();
+      break;
+
+    case nsXPTType::T_I64:
+    case nsXPTType::T_U64:
+      reader.GetBytes(&v.val.u64, sizeof(v.val.u64));
+      break;
+
+    case nsXPTType::T_FLOAT:
+      reader.GetBytes(&v.val.f, sizeof(v.val.f));
+      break;
+
+    case nsXPTType::T_DOUBLE:
+      reader.GetBytes(&v.val.d, sizeof(v.val.d));
+      break;
+
+    case nsXPTType::T_BOOL:
+      reader.GetBytes(&v.val.b, sizeof(v.val.b));
+      break;
+
+    case nsXPTType::T_CHAR:
+      reader.GetBytes(&v.val.c, sizeof(v.val.c));
+      break;
+
+    case nsXPTType::T_WCHAR:
+      reader.GetBytes(&v.val.wc, sizeof(v.val.wc));
+      break;
+
+    case nsXPTType::T_IID:
+      {
+        nsID *buf = (nsID *) nsMemory::Alloc(sizeof(nsID));
+        reader.GetBytes(buf, sizeof(nsID));
+        v.val.p = buf;
+        v.SetValIsAllocated();
+      }
+      break;
+
+    case nsXPTType::T_CHAR_STR:
+      {
+        PRUint32 len = reader.GetInt32();
+        if (len == (PRUint32) -1)
+        {
+          // it's a null string
+          v.val.p = nsnull;
+        }
+        else
+        {
+          char *buf = (char *) nsMemory::Alloc(len + 1);
+          reader.GetBytes(buf, len);
+          buf[len] = char(0);
+
+          v.val.p = buf;
+          v.SetValIsAllocated();
+        }
+      }
+      break;
+
+    case nsXPTType::T_WCHAR_STR:
+      {
+        PRUint32 len = reader.GetInt32();
+        if (len == (PRUint32) -1)
+        {
+          // it's a null string
+          v.val.p = nsnull;
+        }
+        else
+        {
+          PRUnichar *buf = (PRUnichar *) nsMemory::Alloc(len + 2);
+          reader.GetBytes(buf, len);
+          buf[len / 2] = PRUnichar(0);
+
+          v.val.p = buf;
+          v.SetValIsAllocated();
+        }
+      }
+      break;
+
+    case nsXPTType::T_INTERFACE:
+    case nsXPTType::T_INTERFACE_IS:
+      {
+        reader.GetBytes(&v.val.p, sizeof(void *));
+        // stub creation will be handled outside this routine.  we only
+        // deserialize the DConAddr into v.val.p temporarily.
+      }
+      break;
+
+    case nsXPTType::T_ASTRING:
+    case nsXPTType::T_DOMSTRING:
+      {
+        PRUint32 len = reader.GetInt32();
+
+        nsString *str = new nsString();
+        str->SetLength(len / 2);
+        PRUnichar *buf = str->BeginWriting();
+        reader.GetBytes(buf, len);
+
+        v.val.p = str;
+        v.SetValIsDOMString();
+      }
+      break;
+
+    case nsXPTType::T_UTF8STRING:
+    case nsXPTType::T_CSTRING:
+      {
+        PRUint32 len = reader.GetInt32();
+
+        nsCString *str = new nsCString();
+        str->SetLength(len);
+        char *buf = str->BeginWriting();
+        reader.GetBytes(buf, len);
+
+        v.val.p = str;
+
+        // this distinction here is pretty pointless
+        if (t.TagPart() == nsXPTType::T_CSTRING)
+          v.SetValIsCString();
+        else
+          v.SetValIsUTF8String();
+      }
+      break;
+
+    case nsXPTType::T_ARRAY:
+      // arrays are deserialized after all other params outside this routine
+      break;
 
     case nsXPTType::T_VOID:
@@ -424,164 +576,4 @@
 
 static nsresult
-DeserializeParam(ipcMessageReader &reader, const nsXPTType &t, nsXPTCVariant &v)
-{
-  // defaults
-  v.ptr = nsnull;
-  v.type = t;
-  v.flags = 0;
-
-  switch (t.TagPart())
-  {
-    case nsXPTType::T_I8:
-    case nsXPTType::T_U8:
-      v.val.u8 = reader.GetInt8();
-      break;
-
-    case nsXPTType::T_I16:
-    case nsXPTType::T_U16:
-      v.val.u16 = reader.GetInt16();
-      break;
-
-    case nsXPTType::T_I32:
-    case nsXPTType::T_U32:
-      v.val.u32 = reader.GetInt32();
-      break;
-
-    case nsXPTType::T_I64:
-    case nsXPTType::T_U64:
-      reader.GetBytes(&v.val.u64, sizeof(v.val.u64));
-      break;
-
-    case nsXPTType::T_FLOAT:
-      reader.GetBytes(&v.val.f, sizeof(v.val.f));
-      break;
-
-    case nsXPTType::T_DOUBLE:
-      reader.GetBytes(&v.val.d, sizeof(v.val.d));
-      break;
-
-    case nsXPTType::T_BOOL:
-      reader.GetBytes(&v.val.b, sizeof(v.val.b));
-      break;
-
-    case nsXPTType::T_CHAR:
-      reader.GetBytes(&v.val.c, sizeof(v.val.c));
-      break;
-
-    case nsXPTType::T_WCHAR:
-      reader.GetBytes(&v.val.wc, sizeof(v.val.wc));
-      break;
-
-    case nsXPTType::T_IID:
-      {
-        nsID *buf = (nsID *) nsMemory::Alloc(sizeof(nsID));
-        reader.GetBytes(buf, sizeof(nsID));
-        v.val.p = v.ptr = buf;
-        v.flags = nsXPTCVariant::PTR_IS_DATA | nsXPTCVariant::VAL_IS_ALLOCD;
-      }
-      break;
-
-    case nsXPTType::T_CHAR_STR:
-      {
-        PRUint32 len = reader.GetInt32();
-        if (len == (PRUint32) -1)
-        {
-          // it's a null string
-          v.val.p = v.ptr = 0;
-          v.flags = nsXPTCVariant::PTR_IS_DATA;
-        }
-        else
-        {
-          char *buf = (char *) nsMemory::Alloc(len + 1);
-          reader.GetBytes(buf, len);
-          buf[len] = char(0);
-
-          v.val.p = v.ptr = buf;
-          v.flags = nsXPTCVariant::PTR_IS_DATA | nsXPTCVariant::VAL_IS_ALLOCD;
-        }
-      }
-      break;
-
-    case nsXPTType::T_WCHAR_STR:
-      {
-        PRUint32 len = reader.GetInt32();
-        if (len == (PRUint32) -1)
-        {
-          // it's a null string
-          v.val.p = v.ptr = 0;
-          v.flags = nsXPTCVariant::PTR_IS_DATA;
-        }
-        else
-        {
-          PRUnichar *buf = (PRUnichar *) nsMemory::Alloc(len + 2);
-          reader.GetBytes(buf, len);
-          buf[len / 2] = PRUnichar(0);
-
-          v.val.p = v.ptr = buf;
-          v.flags = nsXPTCVariant::PTR_IS_DATA | nsXPTCVariant::VAL_IS_ALLOCD;
-        }
-      }
-      break;
-
-    case nsXPTType::T_INTERFACE:
-    case nsXPTType::T_INTERFACE_IS:
-      {
-        reader.GetBytes(&v.ptr, sizeof(void *));
-        v.val.p = nsnull;
-        v.flags = nsXPTCVariant::PTR_IS_DATA;
-      }
-      break;
-
-    case nsXPTType::T_ASTRING:
-    case nsXPTType::T_DOMSTRING:
-      {
-        PRUint32 len = reader.GetInt32();
-
-        nsString *str = new nsString();
-        str->SetLength(len / 2);
-        PRUnichar *buf = str->BeginWriting();
-        reader.GetBytes(buf, len);
-
-        v.val.p = v.ptr = str;
-        v.flags = nsXPTCVariant::PTR_IS_DATA | nsXPTCVariant::VAL_IS_DOMSTR;
-      }
-      break;
-
-    case nsXPTType::T_UTF8STRING:
-    case nsXPTType::T_CSTRING:
-      {
-        PRUint32 len = reader.GetInt32();
-
-        nsCString *str = new nsCString();
-        str->SetLength(len);
-        char *buf = str->BeginWriting();
-        reader.GetBytes(buf, len);
-
-        v.val.p = v.ptr = str;
-        v.flags = nsXPTCVariant::PTR_IS_DATA;
-
-        // this distinction here is pretty pointless
-        if (t.TagPart() == nsXPTType::T_CSTRING)
-          v.flags |= nsXPTCVariant::VAL_IS_CSTR;
-        else
-          v.flags |= nsXPTCVariant::VAL_IS_UTF8STR;
-      }
-      break;
-
-    case nsXPTType::T_ARRAY:
-      LOG(("array types are not yet supported\n"));
-      return NS_ERROR_NOT_IMPLEMENTED;
-
-    case nsXPTType::T_VOID:
-    case nsXPTType::T_PSTRING_SIZE_IS:
-    case nsXPTType::T_PWSTRING_SIZE_IS:
-    default:
-      LOG(("unexpected parameter type\n"));
-      return NS_ERROR_UNEXPECTED;
-  }
-  return NS_OK;
-}
-
-static nsresult
 SetupParam(const nsXPTParamInfo &p, nsXPTCVariant &v)
 {
@@ -591,4 +583,5 @@
   {
     v.ptr = nsnull;
+    v.flags = 0;
 
     switch (t.TagPart())
@@ -596,20 +589,18 @@
       case nsXPTType::T_ASTRING:
       case nsXPTType::T_DOMSTRING:
-        v.ptr = new nsString();
-        if (!v.ptr)
+        v.val.p = new nsString();
+        if (!v.val.p)
           return NS_ERROR_OUT_OF_MEMORY;
-        v.val.p = v.ptr;
         v.type = t;
-        v.flags = nsXPTCVariant::PTR_IS_DATA | nsXPTCVariant::VAL_IS_DOMSTR;
+        v.SetValIsDOMString();
         break;
 
       case nsXPTType::T_UTF8STRING:
       case nsXPTType::T_CSTRING:
-        v.ptr = new nsCString();
-        if (!v.ptr)
+        v.val.p = new nsCString();
+        if (!v.val.p)
           return NS_ERROR_OUT_OF_MEMORY;
-        v.val.p = v.ptr;
         v.type = t;
-        v.flags = nsXPTCVariant::PTR_IS_DATA | nsXPTCVariant::VAL_IS_CSTR;
+        v.SetValIsCString();
         break;
 
@@ -624,9 +615,10 @@
     v.ptr = &v.val;
     v.type = t;
-    v.flags = nsXPTCVariant::PTR_IS_DATA;
-
-    // nsID, string and wstring types are not understood as dippers (see
-    // DIPPER_TYPE in xpidl.h) but they behave like dippers too. Therefore we
-    // need to treat them so manually.
+    v.flags = 0;
+    v.SetPtrIsData();
+
+    // the ownership of output nsID, string, wstring, interface pointers and
+    // arrays is transferred to the receiving party. Therefore, we need to
+    // instruct FinishParam() to perform a cleanup after serializing them.
     switch (t.TagPart())
     {
@@ -634,6 +626,10 @@
       case nsXPTType::T_CHAR_STR:
       case nsXPTType::T_WCHAR_STR:
-        // add VAL_IS_ALLOCD to cause FinishParam() to do cleanup
-        v.flags |= nsXPTCVariant::VAL_IS_ALLOCD;
+      case nsXPTType::T_ARRAY:
+        v.SetValIsAllocated();
+        break;
+      case nsXPTType::T_INTERFACE:
+      case nsXPTType::T_INTERFACE_IS:
+        v.SetValIsInterface();
         break;
       default:
@@ -652,5 +648,5 @@
 
   if (v.IsValAllocated())
-      nsMemory::Free(v.val.p);
+    nsMemory::Free(v.val.p);
   else if (v.IsValInterface())
     ((nsISupports *) v.val.p)->Release();
@@ -797,6 +793,6 @@
 
     case nsXPTType::T_ARRAY:
-      LOG(("array types are not yet supported\n"));
-      return NS_ERROR_NOT_IMPLEMENTED;
+      // arrays are deserialized after all other params outside this routine
+      break;
 
     case nsXPTType::T_VOID:
@@ -808,4 +804,400 @@
   }
   return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+//
+// Returns an element from the nsXPTCMiniVariant array by properly casting it to
+// nsXPTCVariant when requested
+#define GET_PARAM(params, isXPTCVariantArray, idx) \
+    (isXPTCVariantArray ? ((nsXPTCVariant *) params) [idx] : params [idx])
+
+// isResult is PR_TRUE if the size_is and length_is params are out or retval
+// so that nsXPTCMiniVariants contain pointers to their locations instead of the
+// values themselves.
+static nsresult
+GetArrayParamInfo(nsIInterfaceInfo *iinfo, uint16 methodIndex,
+                  const nsXPTMethodInfo &methodInfo, nsXPTCMiniVariant *params,
+                  PRBool isXPTCVariantArray, const nsXPTParamInfo &paramInfo,
+                  PRBool isResult, PRUint32 &size, PRUint32 &length,
+                  nsXPTType &elemType)
+{
+  // XXX multidimensional arrays are not supported so dimension is always 0 for
+  // getting the size_is argument number of the array itself and 1 for getting
+  // the type of elements stored in the array.
+
+  nsresult rv;
+
+  // get the array size
+  PRUint8 sizeArg;
+  rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0, &sizeArg);
+  if (NS_FAILED(rv))
+    return rv;
+
+  // get the number of valid elements
+  PRUint8 lenArg;
+  rv = iinfo->GetLengthIsArgNumberForParam(methodIndex, &paramInfo, 0, &lenArg);
+  if (NS_FAILED(rv))
+    return rv;
+
+  // according to XPT specs
+  // (http://www.mozilla.org/scriptable/typelib_file.html), size_is and
+  // length_is for arrays is always uint32. Check this too.
+  {
+    nsXPTParamInfo pi = methodInfo.GetParam (sizeArg);
+    if (pi.GetType().TagPart() != nsXPTType::T_U32)
+    {
+      LOG(("unexpected size_is() parameter type: $d\n",
+           pi.GetType().TagPart()));
+      return NS_ERROR_UNEXPECTED;
+    }
+
+    pi = methodInfo.GetParam (lenArg);
+    if (pi.GetType().TagPart() != nsXPTType::T_U32)
+    {
+      LOG(("unexpected length_is() parameter type: $d\n",
+           pi.GetType().TagPart()));
+      return NS_ERROR_UNEXPECTED;
+    }
+  }
+
+  if (isResult)
+  {
+    length = *((PRUint32 *) GET_PARAM(params,isXPTCVariantArray, lenArg).val.p);
+    size = *((PRUint32 *) GET_PARAM(params, isXPTCVariantArray, sizeArg).val.p);
+  }
+  else
+  {
+    length = GET_PARAM(params, isXPTCVariantArray, lenArg).val.u32;
+    size = GET_PARAM(params, isXPTCVariantArray, sizeArg).val.u32;
+  }
+
+  if (length > size)
+  {
+    NS_WARNING("length_is() value is greater than size_is() value");
+    length = size;
+  }
+
+  // get type of array elements
+  rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &elemType);
+  if (NS_FAILED(rv))
+    return rv;
+
+  if (elemType.IsArithmetic() &&
+      (elemType.IsPointer() || elemType.IsUniquePointer() ||
+       elemType.IsReference()))
+  {
+    LOG(("arrays of pointers and references to arithmetic types are "
+         "not yet supported\n"));
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+
+  if (elemType.IsArray())
+  {
+    LOG(("multidimensional arrays are not yet supported\n"));
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+
+  return NS_OK;
+}
+
+static nsresult
+GetTypeSize(const nsXPTType &type, PRUint32 &size, PRBool &isSimple)
+{
+  // get the type size in bytes
+  size = 0;
+  isSimple = PR_TRUE;
+  switch (type.TagPart())
+  {
+    case nsXPTType::T_I8:             size = sizeof(PRInt8);      break;
+    case nsXPTType::T_I16:            size = sizeof(PRInt16);     break;
+    case nsXPTType::T_I32:            size = sizeof(PRInt32);     break;
+    case nsXPTType::T_I64:            size = sizeof(PRInt64);     break;
+    case nsXPTType::T_U8:             size = sizeof(PRUint8);     break;
+    case nsXPTType::T_U16:            size = sizeof(PRUint16);    break;
+    case nsXPTType::T_U32:            size = sizeof(PRUint32);    break;
+    case nsXPTType::T_U64:            size = sizeof(PRUint64);    break;
+    case nsXPTType::T_FLOAT:          size = sizeof(float);       break;
+    case nsXPTType::T_DOUBLE:         size = sizeof(double);      break;
+    case nsXPTType::T_BOOL:           size = sizeof(PRBool);      break;
+    case nsXPTType::T_CHAR:           size = sizeof(char);        break;
+    case nsXPTType::T_WCHAR:          size = sizeof(PRUnichar);   break;
+    case nsXPTType::T_IID:            /* fall through */
+    case nsXPTType::T_CHAR_STR:       /* fall through */
+    case nsXPTType::T_WCHAR_STR:      /* fall through */
+    case nsXPTType::T_INTERFACE:      /* fall through */
+    case nsXPTType::T_INTERFACE_IS:   /* fall through */
+    case nsXPTType::T_ASTRING:        /* fall through */
+    case nsXPTType::T_DOMSTRING:      /* fall through */
+    case nsXPTType::T_UTF8STRING:     /* fall through */
+    case nsXPTType::T_CSTRING:        /* fall through */
+      size = sizeof(void *);
+      isSimple = PR_FALSE;
+      break;
+    default:
+      LOG(("unexpected parameter type: %d\n", type.TagPart()));
+      return NS_ERROR_UNEXPECTED;
+  }
+
+  return NS_OK;
+}
+
+static nsresult
+SerializeArrayParam(ipcDConnectService *dConnect,
+                    ipcMessageWriter &writer, PRUint32 peerID,
+                    nsIInterfaceInfo *iinfo, uint16 methodIndex,
+                    const nsXPTMethodInfo &methodInfo,
+                    nsXPTCMiniVariant *params, PRBool isXPTCVariantArray,
+                    const nsXPTParamInfo &paramInfo,
+                    void *array, nsVoidArray &wrappers)
+{
+  if (!array)
+  {
+    // put 0 to indicate null array
+    writer.PutInt8(0);
+    return NS_OK;
+  }
+
+  // put 1 to indicate non-null array
+  writer.PutInt8(1);
+
+  PRUint32 size = 0;
+  PRUint32 length = 0;
+  nsXPTType elemType;
+
+  nsresult rv = GetArrayParamInfo(iinfo, methodIndex, methodInfo, params,
+                                  isXPTCVariantArray, paramInfo, PR_FALSE,
+                                  size, length, elemType);
+  if (NS_FAILED (rv))
+      return rv;
+
+  PRUint32 elemSize = 0;
+  PRBool isSimple = PR_TRUE;
+  rv = GetTypeSize(elemType, elemSize, isSimple);
+  if (NS_FAILED (rv))
+      return rv;
+
+  if (isSimple)
+  {
+    // this is a simple arithmetic type, write the whole array at once
+    writer.PutBytes(array, length * elemSize);
+    return NS_OK;
+  }
+
+  // iterate over valid (length_is) elements of the array
+  // and serialize each of them
+  nsXPTCMiniVariant v;
+  for (PRUint32 i = 0; i < length; ++i)
+  {
+    v.val.p = ((void **) array) [i];
+
+    if (elemType.IsInterfacePointer())
+    {
+      nsID iid;
+      rv = dConnect->GetIIDForMethodParam(iinfo, &methodInfo, paramInfo, elemType,
+                                          methodIndex, params, isXPTCVariantArray,
+                                          iid);
+      if (NS_SUCCEEDED(rv))
+        rv = dConnect->SerializeInterfaceParam(writer, peerID, iid,
+                                               (nsISupports *) v.val.p,
+                                               wrappers);
+    }
+    else
+      rv = SerializeParam(writer, elemType, v);
+
+    if (NS_FAILED(rv))
+        return rv;
+  }
+
+  return NS_OK;
+}
+
+// isResult is PR_TRUE if the array param is out or retval
+static nsresult
+DeserializeArrayParam(ipcDConnectService *dConnect,
+                      ipcMessageReader &reader, PRUint32 peerID,
+                      nsIInterfaceInfo *iinfo, uint16 methodIndex,
+                      const nsXPTMethodInfo &methodInfo,
+                      nsXPTCMiniVariant *params, PRBool isXPTCVariantArray,
+                      const nsXPTParamInfo &paramInfo,
+                      PRBool isResult, void *&array)
+{
+  PRUint32 size = 0;
+  PRUint32 length = 0;
+  nsXPTType elemType;
+
+  nsresult rv = GetArrayParamInfo(iinfo, methodIndex, methodInfo, params,
+                                  isXPTCVariantArray, paramInfo, isResult,
+                                  size, length, elemType);
+  if (NS_FAILED(rv))
+    return rv;
+
+  PRUint8 prefix = reader.GetInt8();
+  if (prefix == 0)
+  {
+    // it's a null array
+    array = nsnull;
+    return NS_OK;
+  }
+  // sanity
+  if (prefix != 1)
+  {
+    LOG(("unexpected array prefix: %u\n", prefix));
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  PRUint32 elemSize = 0;
+  PRBool isSimple = PR_TRUE;
+  rv = GetTypeSize(elemType, elemSize, isSimple);
+  if (NS_FAILED (rv))
+      return rv;
+
+  void *arr = nsMemory::Alloc(size * elemSize);
+  if (arr == nsnull)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  // initialize the unused space of the array with zeroes
+  if (length < size)
+    memset(((PRUint8 *) arr) + length * elemSize, 0,
+           (size - length) * elemSize);
+
+  if (isSimple)
+  {
+    // this is a simple arithmetic type, read the whole array at once
+    reader.GetBytes(arr, length * elemSize);
+
+    array = arr;
+    return NS_OK;
+  }
+
+  // iterate over valid (length_is) elements of the array
+  // and deserialize each of them individually
+  nsXPTCVariant v;
+  for (PRUint32 i = 0; i < length; ++i)
+  {
+    rv = DeserializeParam(reader, elemType, v);
+
+    if (NS_SUCCEEDED(rv) && elemType.IsInterfacePointer())
+    {
+      // grab the DConAddr value temporarily stored in the param
+      PtrBits bits = (PtrBits) v.val.p;
+
+      // DeserializeInterfaceParamBits needs IID only if it's a remote object
+      nsID iid;
+      if (bits & PTRBITS_REMOTE_BIT)
+        rv = dConnect->GetIIDForMethodParam(iinfo, &methodInfo, paramInfo,
+                                            elemType, methodIndex,
+                                            params, isXPTCVariantArray, iid);
+      if (NS_SUCCEEDED(rv))
+      {
+        nsISupports *obj = nsnull;
+        rv = dConnect->DeserializeInterfaceParamBits(bits, peerID, iid, obj);
+        if (NS_SUCCEEDED(rv))
+          v.val.p = obj;
+      }
+    }
+
+    if (NS_FAILED(rv))
+      break;
+
+    // note that we discard extended param informaton provided by nsXPTCVariant
+    // and will have to "reconstruct" it from the type tag in FinishArrayParam()
+    ((void **) arr) [i] = v.val.p;
+  }
+
+  if (NS_FAILED(rv))
+    nsMemory::Free(arr);
+  else
+    array = arr;
+
+  return rv;
+}
+
+static void
+FinishArrayParam(nsIInterfaceInfo *iinfo, uint16 methodIndex,
+                 const nsXPTMethodInfo &methodInfo, nsXPTCMiniVariant *params,
+                 PRBool isXPTCVariantArray, const nsXPTParamInfo &paramInfo,
+                 const nsXPTCMiniVariant &arrayVal)
+{
+  // nothing to do for a null array
+  void *arr = arrayVal.val.p;
+  if (!arr)
+    return;
+
+  PRUint32 size = 0;
+  PRUint32 length = 0;
+  nsXPTType elemType;
+
+  // note that FinishArrayParam is called only from OnInvoke to free memory
+  // after the call has been served. When OnInvoke sets up out and retval
+  // parameters for the real method, it passes pointers to the nsXPTCMiniVariant
+  // elements of the params array themselves so that they will eventually
+  // receive the returned values. For this reason, both in 'in' param and
+  // 'out/retaval' param cases, size_is and length_is may be read by
+  // GetArrayParamInfo() by value. Therefore, isResult is always PR_FALSE.
+  nsresult rv = GetArrayParamInfo(iinfo, methodIndex, methodInfo, params,
+                                  isXPTCVariantArray, paramInfo, PR_FALSE,
+                                  size, length, elemType);
+  if (NS_FAILED (rv))
+      return;
+
+  nsXPTCVariant v;
+  v.ptr = nsnull;
+  v.flags = 0;
+
+  // iterate over valid (length_is) elements of the array
+  // and free each of them
+  for (PRUint32 i = 0; i < length; ++i)
+  {
+    v.type = elemType.TagPart();
+
+    switch (elemType.TagPart())
+    {
+      case nsXPTType::T_I8:             /* fall through */
+      case nsXPTType::T_I16:            /* fall through */
+      case nsXPTType::T_I32:            /* fall through */
+      case nsXPTType::T_I64:            /* fall through */
+      case nsXPTType::T_U8:             /* fall through */
+      case nsXPTType::T_U16:            /* fall through */
+      case nsXPTType::T_U32:            /* fall through */
+      case nsXPTType::T_U64:            /* fall through */
+      case nsXPTType::T_FLOAT:          /* fall through */
+      case nsXPTType::T_DOUBLE:         /* fall through */
+      case nsXPTType::T_BOOL:           /* fall through */
+      case nsXPTType::T_CHAR:           /* fall through */
+      case nsXPTType::T_WCHAR:          /* fall through */
+        // nothing to free for arithmetic types
+        continue;
+      case nsXPTType::T_IID:            /* fall through */
+      case nsXPTType::T_CHAR_STR:       /* fall through */
+      case nsXPTType::T_WCHAR_STR:      /* fall through */
+        v.val.p = ((void **) arr) [i];
+        v.SetValIsAllocated();
+        break;
+      case nsXPTType::T_INTERFACE:      /* fall through */
+      case nsXPTType::T_INTERFACE_IS:   /* fall through */
+        v.val.p = ((void **) arr) [i];
+        v.SetValIsInterface();
+        break;
+      case nsXPTType::T_ASTRING:        /* fall through */
+      case nsXPTType::T_DOMSTRING:      /* fall through */
+        v.val.p = ((void **) arr) [i];
+        v.SetValIsDOMString();
+        break;
+      case nsXPTType::T_UTF8STRING:     /* fall through */
+        v.val.p = ((void **) arr) [i];
+        v.SetValIsUTF8String();
+        break;
+      case nsXPTType::T_CSTRING:        /* fall through */
+        v.val.p = ((void **) arr) [i];
+        v.SetValIsCString();
+        break;
+      default:
+        LOG(("unexpected parameter type: %d\n", elemType.TagPart()));
+        return;
+    }
+
+    FinishParam(v);
+  }
 }
 
@@ -995,7 +1387,7 @@
     return DConnectStubKey::Key(mPeerID, mInstance);
   }
-  
+
   NS_IMETHOD_(nsrefcnt) AddRefIPC();
-  
+
 private:
   nsCOMPtr<nsIInterfaceInfo> mIInfo;
@@ -1006,8 +1398,8 @@
   // the "client id" of our IPC peer.  this guy owns the real object.
   PRUint32 mPeerID;
-  
+
   // cached nsISupports stub for this object
   DConnectStub *mCachedISupports;
-  
+
   // stack of reference counter values (protected by
   // ipcDConnectService::StubLock())
@@ -1161,5 +1553,5 @@
       // the wrapper from the instance map on failure)
       wrapper->AddRefIPC();
-        
+
       if (!wrappers.AppendElement(wrapper))
       {
@@ -1171,12 +1563,57 @@
       // wrapper remains referenced when passing it to the client
       // (will be released upon DCON_OP_RELEASE)
-      
-      // send address of the instance wrapper, and set the low bit
-      // to indicate that this is an instance wrapper.
-      PtrBits bits = ((PtrBits) wrapper) | 0x1;
+
+      // send address of the instance wrapper, and set the low bit to indicate
+      // to the remote party that this is a remote instance wrapper.
+      PtrBits bits = ((PtrBits) wrapper) | PTRBITS_REMOTE_BIT;
       writer.PutBytes(&bits, sizeof(bits));
     }
     NS_IF_RELEASE(stub);
   }
+  return NS_OK;
+}
+
+// NOTE: peer and iid are ignored if bits doesn't contain PTRBITS_REMOTE_BIT
+nsresult
+ipcDConnectService::DeserializeInterfaceParamBits(PtrBits bits, PRUint32 peer,
+                                                  const nsID &iid,
+                                                  nsISupports *&obj)
+{
+  nsresult rv;
+
+  obj = nsnull;
+
+  if (bits & PTRBITS_REMOTE_BIT)
+  {
+    // pointer is to a remote object.  we need to build a stub.
+
+    bits &= ~PTRBITS_REMOTE_BIT;
+
+    DConnectStub *stub;
+    rv = CreateStub(iid, peer, (DConAddr) bits, &stub);
+    if (NS_SUCCEEDED(rv))
+      obj = stub;
+  }
+  else if (bits)
+  {
+    // pointer is to one of our instance wrappers. Replace it with the
+    // real instance.
+
+    DConnectInstance *wrapper = (DConnectInstance *) bits;
+    // make sure we've been sent a valid wrapper
+    if (!CheckInstanceAndAddRef(wrapper))
+    {
+      NS_NOTREACHED("instance wrapper not found");
+      return NS_ERROR_INVALID_ARG;
+    }
+    obj = wrapper->RealInstance();
+    NS_ADDREF(obj);
+    NS_RELEASE(wrapper);
+  }
+  else
+  {
+    // obj is alredy nsnull
+  }
+
   return NS_OK;
 }
@@ -1434,5 +1871,5 @@
         // the wrapper from the instance map on failure)
         wrapper->AddRefIPC();
-        
+
         if (!wrappers.AppendElement(wrapper))
         {
@@ -1445,7 +1882,7 @@
         // (will be released upon DCON_OP_RELEASE)
 
-        // send address of the instance wrapper, and set the low bit
-        // to indicate that this is an instance wrapper.
-        PtrBits bits = ((PtrBits) wrapper) | 0x1;
+        // send address of the instance wrapper, and set the low bit to indicate
+        // to the remote party that this is a remote instance wrapper.
+        PtrBits bits = ((PtrBits) wrapper) | PTRBITS_REMOTE_BIT;
         writer.PutBytes(&bits, sizeof(bits));
 
@@ -1544,5 +1981,5 @@
   PtrBits bits = (PtrBits) (instance);
 
-  if (bits & 0x1)
+  if (bits & PTRBITS_REMOTE_BIT)
   {
     // pointer is a peer-side exception instance wrapper,
@@ -1585,5 +2022,5 @@
     else
     {
-      DConAddr addr = (DConAddr) (bits & ~0x1);
+      DConAddr addr = (DConAddr) (bits & ~PTRBITS_REMOTE_BIT);
       nsRefPtr<DConnectStub> stub;
       rv = CreateStub(nsIException::GetIID(), peer, addr,
@@ -1648,6 +2085,6 @@
   LOG(("{%p} DConnectStub::<dtor>(): peer=%d instance=%p {%s}\n",
        this, mPeerID, mInstance, name));
-#endif    
-    
+#endif
+
   // release the cached nsISupports instance if it's not the same object
   if (mCachedISupports != 0 && mCachedISupports != this)
@@ -1687,5 +2124,5 @@
     {
       nsrefcnt top = (nsrefcnt) (long) mRefCntLevels.Peek();
-      NS_ASSERTION(top <= count + 1, "refcount is beyond the top level"); 
+      NS_ASSERTION(top <= count + 1, "refcount is beyond the top level");
 
       if (top == count + 1)
@@ -1708,5 +2145,5 @@
         // leave the lock before sending a message
         stubLock.unlock();
-      
+
         nsresult rv;
 
@@ -1716,5 +2153,5 @@
         msg.request_index = 0; // not used, set to some unused value
         msg.instance = mInstance;
-    
+
         // fire off asynchronously... we don't expect any response to this message.
         rv = IPC_SendMessage(mPeerID, kDConnectTargetID,
@@ -1730,5 +2167,5 @@
     NS_LOG_RELEASE(this, count, "DConnectStub");
   }
-  
+
   if (0 == count)
   {
@@ -1830,5 +2267,5 @@
     // stub lock remains held until we've queried the peer
   }
-  
+
   // else, we need to query the peer object by making an IPC call
 
@@ -1901,5 +2338,5 @@
     return rv;
   nsCOMPtr <nsIExceptionManager> em;
-  rv = es->GetCurrentExceptionManager (getter_AddRefs(em));  
+  rv = es->GetCurrentExceptionManager (getter_AddRefs(em));
   if (NS_FAILED (rv))
     return rv;
@@ -1907,5 +2344,5 @@
   if (NS_FAILED (rv))
     return rv;
-    
+
   // ensure ipcDConnectService is not deleted before we finish
   nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
@@ -1951,5 +2388,5 @@
         nsID iid;
         rv = dConnect->GetIIDForMethodParam(mIInfo, aInfo, paramInfo, type,
-                                             aMethodIndex, i, aParams, PR_FALSE, iid);
+                                             aMethodIndex, aParams, PR_FALSE, iid);
         if (NS_SUCCEEDED(rv))
           rv = dConnect->SerializeInterfaceParam(writer, mPeerID, iid,
@@ -1967,4 +2404,22 @@
       // report error early if NULL pointer is passed as an output parameter
       return NS_ERROR_NULL_POINTER;
+    }
+  }
+
+  // serialize input array parameters after everything else since the
+  // deserialization procedure will need to get a size_is value which may be
+  // stored in any preceeding or following param
+  for (i=0; i<paramCount; ++i)
+  {
+    const nsXPTParamInfo &paramInfo = aInfo->GetParam(i);
+
+    if (paramInfo.GetType().IsArray() &&
+        paramInfo.IsIn() && !paramInfo.IsDipper())
+    {
+      rv = SerializeArrayParam(dConnect, writer, mPeerID, mIInfo, aMethodIndex,
+                               *aInfo, aParams, PR_FALSE, paramInfo,
+                               aParams[i].val.p, wrappers);
+      if (NS_FAILED(rv))
+        return rv;
     }
   }
@@ -2011,5 +2466,6 @@
   if (NS_FAILED(rv))
   {
-    NS_ASSERTION(completion.ParamsLen() >= sizeof(void*),
+    NS_ASSERTION(completion.ParamsLen() == 0 ||
+                 completion.ParamsLen() >= sizeof(void*),
                  "invalid nsIException serialization length");
     if (completion.ParamsLen() >= sizeof(void*))
@@ -2047,5 +2503,6 @@
 
     // fixup any interface pointers using a second pass so we can properly
-    // handle INTERFACE_IS referencing an IID that is an out param!
+    // handle INTERFACE_IS referencing an IID that is an out param! This pass is
+    // also used to deserialize arrays (array data goes after all other params).
     for (i=0; i<paramCount && NS_SUCCEEDED(rv); ++i)
     {
@@ -2053,45 +2510,34 @@
       if (aParams[i].val.p && (paramInfo.IsOut() || paramInfo.IsRetval()))
       {
+        void **pptr = (void **) aParams[i].val.p;
         const nsXPTType &type = paramInfo.GetType();
         if (type.IsInterfacePointer())
         {
-          PtrBits bits = (PtrBits) *((void **) aParams[i].val.p);
-          if (bits & 0x1)
+          // grab the DConAddr value temporarily stored in the param
+          PtrBits bits = (PtrBits) *pptr;
+          *pptr = nsnull;
+
+          // DeserializeInterfaceParamBits needs IID only if it's a remote object
+          nsID iid;
+          if (bits & PTRBITS_REMOTE_BIT)
+            rv = dConnect->GetIIDForMethodParam(mIInfo, aInfo, paramInfo, type,
+                                                aMethodIndex, aParams, PR_FALSE,
+                                                iid);
+          if (NS_SUCCEEDED(rv))
           {
-            *((void **) aParams[i].val.p) = (void *) (bits & ~0x1);
-
-            nsID iid;
-            rv = dConnect->GetIIDForMethodParam(mIInfo, aInfo, paramInfo, type,
-                                                 aMethodIndex, i, aParams, PR_FALSE, iid);
-            if (NS_SUCCEEDED(rv))
-            {
-              DConnectStub *stub;
-              void **pptr = (void **) aParams[i].val.p;
-              rv = dConnect->CreateStub(iid, mPeerID, (DConAddr) *pptr, &stub);
+              nsISupports *obj = nsnull;
+              rv = dConnect->DeserializeInterfaceParamBits(bits, mPeerID, iid, obj);
               if (NS_SUCCEEDED(rv))
-                *((nsISupports **) aParams[i].val.p) = stub;
-            }
+                *pptr = obj;
           }
-          else if (bits)
-          {
-            // pointer is to one of our instance wrappers. Replace it with the
-            // real instance.
-            DConnectInstance *wrapper = (DConnectInstance *) bits;
-            if (dConnect->CheckInstanceAndAddRef(wrapper))
-            {
-              *((void **) aParams[i].val.p) = wrapper->RealInstance();
-              NS_ADDREF(wrapper->RealInstance());
-              wrapper->Release();
-            }
-            else
-            {
-              NS_NOTREACHED("instance wrapper not found");
-              rv = NS_ERROR_INVALID_ARG;
-            }
-          }
-          else
-          {
-            *((void **) aParams[i].val.p) = nsnull;
-          }
+        }
+        else if (type.IsArray())
+        {
+          void *array = nsnull;
+          rv = DeserializeArrayParam(dConnect, reader, mPeerID, mIInfo,
+                                     aMethodIndex, *aInfo, aParams, PR_FALSE,
+                                     paramInfo, PR_TRUE, array);
+          if (NS_SUCCEEDED(rv))
+            *pptr = array;
         }
       }
@@ -2379,5 +2825,5 @@
   // (after which no DConnectInstances may exist), so forcibly delete them
   // disregarding the reference counter
-    
+
 #ifdef IPC_LOGGING
   const char *name;
@@ -2490,4 +2936,6 @@
   printf("ipcDConnectService Stats\n");
   printf(" => number of worker threads: %d\n", mWorkers.Count());
+  LOG(("ipcDConnectService Stats\n"));
+  LOG((" => number of worker threads: %d\n", mWorkers.Count()));
 #endif
 
@@ -2531,7 +2979,6 @@
                                          const nsXPTType &type,
                                          PRUint16 methodIndex,
-                                         PRUint8 paramIndex,
                                          nsXPTCMiniVariant *dispatchParams,
-                                         PRBool isFullVariantArray,
+                                         PRBool isXPTCVariantArray,
                                          nsID &result)
 {
@@ -2556,9 +3003,5 @@
       return NS_ERROR_UNEXPECTED;
 
-    nsID *p;
-    if (isFullVariantArray)
-      p = (nsID *) ((nsXPTCVariant *) dispatchParams)[argnum].val.p;
-    else
-      p = (nsID *) dispatchParams[argnum].val.p;
+    nsID *p = (nsID *) GET_PARAM(dispatchParams, isXPTCVariantArray, argnum).val.p;
     if (!p)
       return NS_ERROR_UNEXPECTED;
@@ -3130,5 +3573,5 @@
 ipcDConnectService::OnRelease(PRUint32 peer, const DConnectRelease *release)
 {
-  LOG(("ipcDConnectService::OnRelease [peer=%u instance=%p]\n", 
+  LOG(("ipcDConnectService::OnRelease [peer=%u instance=%p]\n",
        peer, release->instance));
 
@@ -3216,4 +3659,6 @@
 
     // XXX are inout params an issue?
+    // yes, we will need to do v.ptr = &v.val for them (DeserializeParam doesn't
+    // currently do that) to let the callee correctly pick it up and change.
 
     if (paramInfo.IsIn() && !paramInfo.IsDipper())
@@ -3227,54 +3672,48 @@
 
   // fixup any interface pointers.  we do this with a second pass so that
-  // we can properly handle INTERFACE_IS.
+  // we can properly handle INTERFACE_IS. This pass is also used to deserialize
+  // arrays (array data goes after all other params).
   for (i=0; i<paramCount; ++i)
   {
     const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
-    const nsXPTType &type = paramInfo.GetType();
-
-    if (paramInfo.IsIn() && type.IsInterfacePointer())
-    {
-      PtrBits bits = (PtrBits) params[i].ptr;
-      if (bits & 0x1)
-      {
-        // pointer is to a remote object.  we need to build a stub.
-        params[i].ptr = (void *) (bits & ~0x1);
-
+    if (paramInfo.IsIn())
+    {
+      const nsXPTType &type = paramInfo.GetType();
+      if (type.IsInterfacePointer())
+      {
+        // grab the DConAddr value temporarily stored in the param
+        PtrBits bits = (PtrBits) params[i].val.p;
+
+        // DeserializeInterfaceParamBits needs IID only if it's a remote object
         nsID iid;
-        rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
-                                  invoke->method_index, i, params, PR_TRUE, iid);
-        if (NS_SUCCEEDED(rv))
+        if (bits & PTRBITS_REMOTE_BIT)
         {
-          DConnectStub *stub;
-          rv = CreateStub(iid, peer, (DConAddr) params[i].ptr, &stub);
-          if (NS_SUCCEEDED(rv))
-          {
-            params[i].val.p = params[i].ptr = stub;
-            params[i].SetValIsInterface();
-          }
+          rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
+                                    invoke->method_index, params, PR_TRUE, iid);
+          if (NS_FAILED(rv))
+            goto end;
         }
+
+        nsISupports *obj = nsnull;
+        rv = DeserializeInterfaceParamBits(bits, peer, iid, obj);
         if (NS_FAILED(rv))
           goto end;
-      }
-      else if (bits)
-      {
-        // pointer is to one of our instance wrappers.
-
-        DConnectInstance *wrapper = (DConnectInstance *) params[i].ptr;
-        // make sure we've been sent a valid wrapper
-        if (!CheckInstanceAndAddRef(wrapper))
-        {
-          NS_NOTREACHED("instance wrapper not found");
-          rv = NS_ERROR_INVALID_ARG;
+
+        params[i].val.p = obj;
+        // mark as interface to let FinishParam() release this param
+        params[i].SetValIsInterface();
+      }
+      else if (type.IsArray())
+      {
+        void *array = nsnull;
+        rv = DeserializeArrayParam(this, reader, peer, iinfo,
+                                   invoke->method_index, *methodInfo, params,
+                                   PR_TRUE, paramInfo, PR_FALSE, array);
+        if (NS_FAILED(rv))
           goto end;
-        }
-        params[i].val.p = params[i].ptr = wrapper->RealInstance();
-        wrapper->Release();
-        // do not mark as an interface -- doesn't need to be freed
-      }
-      else
-      {
-        params[i].val.p = params[i].ptr = nsnull;
-        // do not mark as an interface -- doesn't need to be freed
+
+        params[i].val.p = array;
+        // mark to let FinishParam() free this param
+        params[i].SetValIsAllocated();
       }
     }
@@ -3313,5 +3752,5 @@
 end:
   LOG(("sending INVOKE_REPLY: rv=%x\n", rv));
-  
+
   // balance CheckInstanceAndAddRef()
   if (wrapper)
@@ -3350,12 +3789,8 @@
           nsID iid;
           rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
-                                    invoke->method_index, i, params, PR_TRUE, iid);
+                                    invoke->method_index, params, PR_TRUE, iid);
           if (NS_SUCCEEDED(rv))
             rv = SerializeInterfaceParam(writer, peer, iid,
                                          (nsISupports *) params[i].val.p, wrappers);
-
-          // mark as an interface to let FinishParam() to release this param
-          if (NS_SUCCEEDED(rv))
-            params[i].SetValIsInterface();
         }
         else
@@ -3369,4 +3804,28 @@
       }
     }
+
+    if (NS_SUCCEEDED(rv))
+    {
+      // serialize output array parameters after everything else since the
+      // deserialization procedure will need to get a size_is value which may be
+      // stored in any preceeding or following param
+      for (i=0; i<paramCount; ++i)
+      {
+        const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
+
+        if (paramInfo.GetType().IsArray() &&
+            (paramInfo.IsRetval() || paramInfo.IsOut()))
+        {
+          rv = SerializeArrayParam(this, writer, peer, iinfo, invoke->method_index,
+                                   *methodInfo, params, PR_TRUE, paramInfo,
+                                   params[i].val.p, wrappers);
+          if (NS_FAILED(rv))
+          {
+            reply.result = rv;
+            break;
+          }
+        }
+      }
+    }
   }
 
@@ -3383,4 +3842,14 @@
   if (params)
   {
+    // free individual elements of arrays (note: before freeing arrays
+    // themselves in FinishParam())
+    for (i=0; i<paramUsed; ++i)
+    {
+      const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
+      if (paramInfo.GetType().IsArray())
+        FinishArrayParam(iinfo, invoke->method_index, *methodInfo,
+                         params, PR_TRUE, paramInfo, params[i]);
+    }
+
     for (i=0; i<paramUsed; ++i)
       FinishParam(params[i]);
Index: /trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h
===================================================================
--- /trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h	(revision 6849)
+++ /trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h	(revision 6850)
@@ -185,4 +185,11 @@
 };
 
+// used elsewhere like nsAtomTable to safely represent the integral value
+// of an address.
+typedef unsigned long PtrBits;
+
+// bit flag that defines if a PtrBits value represents a remote object
+#define PTRBITS_REMOTE_BIT 0x1
+
 class DConnectStub;
 typedef nsDataHashtable<DConnectStubKey, DConnectStub *> DConnectStubMap;
@@ -209,7 +216,6 @@
                                             const nsXPTType &type,
                                             PRUint16 methodIndex,
-                                            PRUint8 paramIndex,
                                             nsXPTCMiniVariant *dispatchParams,
-                                            PRBool isFullVariantArray,
+                                            PRBool isXPTCVariantArray,
                                             nsID &result);
 
@@ -218,4 +224,7 @@
                                                nsISupports *obj,
                                                nsVoidArray &wrappers);
+  NS_HIDDEN_(nsresult) DeserializeInterfaceParamBits(PtrBits bits, PRUint32 peer,
+                                                     const nsID &iid,
+                                                     nsISupports *&obj);
 
   NS_HIDDEN_(nsresult) SerializeException(ipcMessageWriter &writer,
@@ -241,5 +250,5 @@
   PRLock *StubLock() { return mStubLock; }
   PRLock *StubQILock() { return mStubQILock; }
-  
+
   static nsRefPtr <ipcDConnectService> GetInstance() {
     return nsRefPtr <ipcDConnectService> (mInstance);
@@ -293,5 +302,5 @@
   // our IPC client ID
   PRUint32 mSelfID;
-  
+
   // global lock to protect access to protect DConnectStub::QueryInterface()
   // (we cannot use mStubLock because it isn't supposed to be held long,
