VirtualBox

Ignore:
Timestamp:
Feb 7, 2008 3:59:12 PM (17 years ago)
Author:
vboxsync
Message:

XPCOM/IPC/DConnect: Implemented support for one-dimensional arrays (poted r27277:27975 from brahches/dmik/s2; see /vbox/log/branches/dmik/s2/src/libs/xpcom18a4?rev=27975&stop_rev=27277 for details).

Location:
trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp

    r5970 r6850  
    6969// XXX TODO:
    7070//  1. add thread affinity field to SETUP messages
    71 //  2. support array parameters
    7271
    7372//-----------------------------------------------------------------------------
     
    8584
    8685#define DCON_WAIT_TIMEOUT PR_INTERVAL_NO_TIMEOUT
    87 
    88 // used elsewhere like nsAtomTable to safely represent the integral value
    89 // of an address.
    90 typedef unsigned long PtrBits;
    9186
    9287//-----------------------------------------------------------------------------
     
    274269    return count;
    275270  }
    276  
     271
    277272private:
    278273  nsAutoRefCnt               mRefCnt;
     
    410405
    411406    case nsXPTType::T_ARRAY:
    412       LOG(("array types are not yet supported\n"));
    413       return NS_ERROR_NOT_IMPLEMENTED;
     407      // arrays are serialized after all other params outside this routine
     408      break;
     409
     410    case nsXPTType::T_VOID:
     411    case nsXPTType::T_PSTRING_SIZE_IS:
     412    case nsXPTType::T_PWSTRING_SIZE_IS:
     413    default:
     414      LOG(("unexpected parameter type: %d\n", t.TagPart()));
     415      return NS_ERROR_UNEXPECTED;
     416  }
     417  return NS_OK;
     418}
     419
     420static nsresult
     421DeserializeParam(ipcMessageReader &reader, const nsXPTType &t, nsXPTCVariant &v)
     422{
     423  // defaults
     424  v.ptr = nsnull;
     425  v.type = t;
     426  v.flags = 0;
     427
     428  switch (t.TagPart())
     429  {
     430    case nsXPTType::T_I8:
     431    case nsXPTType::T_U8:
     432      v.val.u8 = reader.GetInt8();
     433      break;
     434
     435    case nsXPTType::T_I16:
     436    case nsXPTType::T_U16:
     437      v.val.u16 = reader.GetInt16();
     438      break;
     439
     440    case nsXPTType::T_I32:
     441    case nsXPTType::T_U32:
     442      v.val.u32 = reader.GetInt32();
     443      break;
     444
     445    case nsXPTType::T_I64:
     446    case nsXPTType::T_U64:
     447      reader.GetBytes(&v.val.u64, sizeof(v.val.u64));
     448      break;
     449
     450    case nsXPTType::T_FLOAT:
     451      reader.GetBytes(&v.val.f, sizeof(v.val.f));
     452      break;
     453
     454    case nsXPTType::T_DOUBLE:
     455      reader.GetBytes(&v.val.d, sizeof(v.val.d));
     456      break;
     457
     458    case nsXPTType::T_BOOL:
     459      reader.GetBytes(&v.val.b, sizeof(v.val.b));
     460      break;
     461
     462    case nsXPTType::T_CHAR:
     463      reader.GetBytes(&v.val.c, sizeof(v.val.c));
     464      break;
     465
     466    case nsXPTType::T_WCHAR:
     467      reader.GetBytes(&v.val.wc, sizeof(v.val.wc));
     468      break;
     469
     470    case nsXPTType::T_IID:
     471      {
     472        nsID *buf = (nsID *) nsMemory::Alloc(sizeof(nsID));
     473        reader.GetBytes(buf, sizeof(nsID));
     474        v.val.p = buf;
     475        v.SetValIsAllocated();
     476      }
     477      break;
     478
     479    case nsXPTType::T_CHAR_STR:
     480      {
     481        PRUint32 len = reader.GetInt32();
     482        if (len == (PRUint32) -1)
     483        {
     484          // it's a null string
     485          v.val.p = nsnull;
     486        }
     487        else
     488        {
     489          char *buf = (char *) nsMemory::Alloc(len + 1);
     490          reader.GetBytes(buf, len);
     491          buf[len] = char(0);
     492
     493          v.val.p = buf;
     494          v.SetValIsAllocated();
     495        }
     496      }
     497      break;
     498
     499    case nsXPTType::T_WCHAR_STR:
     500      {
     501        PRUint32 len = reader.GetInt32();
     502        if (len == (PRUint32) -1)
     503        {
     504          // it's a null string
     505          v.val.p = nsnull;
     506        }
     507        else
     508        {
     509          PRUnichar *buf = (PRUnichar *) nsMemory::Alloc(len + 2);
     510          reader.GetBytes(buf, len);
     511          buf[len / 2] = PRUnichar(0);
     512
     513          v.val.p = buf;
     514          v.SetValIsAllocated();
     515        }
     516      }
     517      break;
     518
     519    case nsXPTType::T_INTERFACE:
     520    case nsXPTType::T_INTERFACE_IS:
     521      {
     522        reader.GetBytes(&v.val.p, sizeof(void *));
     523        // stub creation will be handled outside this routine.  we only
     524        // deserialize the DConAddr into v.val.p temporarily.
     525      }
     526      break;
     527
     528    case nsXPTType::T_ASTRING:
     529    case nsXPTType::T_DOMSTRING:
     530      {
     531        PRUint32 len = reader.GetInt32();
     532
     533        nsString *str = new nsString();
     534        str->SetLength(len / 2);
     535        PRUnichar *buf = str->BeginWriting();
     536        reader.GetBytes(buf, len);
     537
     538        v.val.p = str;
     539        v.SetValIsDOMString();
     540      }
     541      break;
     542
     543    case nsXPTType::T_UTF8STRING:
     544    case nsXPTType::T_CSTRING:
     545      {
     546        PRUint32 len = reader.GetInt32();
     547
     548        nsCString *str = new nsCString();
     549        str->SetLength(len);
     550        char *buf = str->BeginWriting();
     551        reader.GetBytes(buf, len);
     552
     553        v.val.p = str;
     554
     555        // this distinction here is pretty pointless
     556        if (t.TagPart() == nsXPTType::T_CSTRING)
     557          v.SetValIsCString();
     558        else
     559          v.SetValIsUTF8String();
     560      }
     561      break;
     562
     563    case nsXPTType::T_ARRAY:
     564      // arrays are deserialized after all other params outside this routine
     565      break;
    414566
    415567    case nsXPTType::T_VOID:
     
    424576
    425577static nsresult
    426 DeserializeParam(ipcMessageReader &reader, const nsXPTType &t, nsXPTCVariant &v)
    427 {
    428   // defaults
    429   v.ptr = nsnull;
    430   v.type = t;
    431   v.flags = 0;
    432 
    433   switch (t.TagPart())
    434   {
    435     case nsXPTType::T_I8:
    436     case nsXPTType::T_U8:
    437       v.val.u8 = reader.GetInt8();
    438       break;
    439 
    440     case nsXPTType::T_I16:
    441     case nsXPTType::T_U16:
    442       v.val.u16 = reader.GetInt16();
    443       break;
    444 
    445     case nsXPTType::T_I32:
    446     case nsXPTType::T_U32:
    447       v.val.u32 = reader.GetInt32();
    448       break;
    449 
    450     case nsXPTType::T_I64:
    451     case nsXPTType::T_U64:
    452       reader.GetBytes(&v.val.u64, sizeof(v.val.u64));
    453       break;
    454 
    455     case nsXPTType::T_FLOAT:
    456       reader.GetBytes(&v.val.f, sizeof(v.val.f));
    457       break;
    458 
    459     case nsXPTType::T_DOUBLE:
    460       reader.GetBytes(&v.val.d, sizeof(v.val.d));
    461       break;
    462 
    463     case nsXPTType::T_BOOL:
    464       reader.GetBytes(&v.val.b, sizeof(v.val.b));
    465       break;
    466 
    467     case nsXPTType::T_CHAR:
    468       reader.GetBytes(&v.val.c, sizeof(v.val.c));
    469       break;
    470 
    471     case nsXPTType::T_WCHAR:
    472       reader.GetBytes(&v.val.wc, sizeof(v.val.wc));
    473       break;
    474 
    475     case nsXPTType::T_IID:
    476       {
    477         nsID *buf = (nsID *) nsMemory::Alloc(sizeof(nsID));
    478         reader.GetBytes(buf, sizeof(nsID));
    479         v.val.p = v.ptr = buf;
    480         v.flags = nsXPTCVariant::PTR_IS_DATA | nsXPTCVariant::VAL_IS_ALLOCD;
    481       }
    482       break;
    483 
    484     case nsXPTType::T_CHAR_STR:
    485       {
    486         PRUint32 len = reader.GetInt32();
    487         if (len == (PRUint32) -1)
    488         {
    489           // it's a null string
    490           v.val.p = v.ptr = 0;
    491           v.flags = nsXPTCVariant::PTR_IS_DATA;
    492         }
    493         else
    494         {
    495           char *buf = (char *) nsMemory::Alloc(len + 1);
    496           reader.GetBytes(buf, len);
    497           buf[len] = char(0);
    498 
    499           v.val.p = v.ptr = buf;
    500           v.flags = nsXPTCVariant::PTR_IS_DATA | nsXPTCVariant::VAL_IS_ALLOCD;
    501         }
    502       }
    503       break;
    504 
    505     case nsXPTType::T_WCHAR_STR:
    506       {
    507         PRUint32 len = reader.GetInt32();
    508         if (len == (PRUint32) -1)
    509         {
    510           // it's a null string
    511           v.val.p = v.ptr = 0;
    512           v.flags = nsXPTCVariant::PTR_IS_DATA;
    513         }
    514         else
    515         {
    516           PRUnichar *buf = (PRUnichar *) nsMemory::Alloc(len + 2);
    517           reader.GetBytes(buf, len);
    518           buf[len / 2] = PRUnichar(0);
    519 
    520           v.val.p = v.ptr = buf;
    521           v.flags = nsXPTCVariant::PTR_IS_DATA | nsXPTCVariant::VAL_IS_ALLOCD;
    522         }
    523       }
    524       break;
    525 
    526     case nsXPTType::T_INTERFACE:
    527     case nsXPTType::T_INTERFACE_IS:
    528       {
    529         reader.GetBytes(&v.ptr, sizeof(void *));
    530         v.val.p = nsnull;
    531         v.flags = nsXPTCVariant::PTR_IS_DATA;
    532       }
    533       break;
    534 
    535     case nsXPTType::T_ASTRING:
    536     case nsXPTType::T_DOMSTRING:
    537       {
    538         PRUint32 len = reader.GetInt32();
    539 
    540         nsString *str = new nsString();
    541         str->SetLength(len / 2);
    542         PRUnichar *buf = str->BeginWriting();
    543         reader.GetBytes(buf, len);
    544 
    545         v.val.p = v.ptr = str;
    546         v.flags = nsXPTCVariant::PTR_IS_DATA | nsXPTCVariant::VAL_IS_DOMSTR;
    547       }
    548       break;
    549 
    550     case nsXPTType::T_UTF8STRING:
    551     case nsXPTType::T_CSTRING:
    552       {
    553         PRUint32 len = reader.GetInt32();
    554 
    555         nsCString *str = new nsCString();
    556         str->SetLength(len);
    557         char *buf = str->BeginWriting();
    558         reader.GetBytes(buf, len);
    559 
    560         v.val.p = v.ptr = str;
    561         v.flags = nsXPTCVariant::PTR_IS_DATA;
    562 
    563         // this distinction here is pretty pointless
    564         if (t.TagPart() == nsXPTType::T_CSTRING)
    565           v.flags |= nsXPTCVariant::VAL_IS_CSTR;
    566         else
    567           v.flags |= nsXPTCVariant::VAL_IS_UTF8STR;
    568       }
    569       break;
    570 
    571     case nsXPTType::T_ARRAY:
    572       LOG(("array types are not yet supported\n"));
    573       return NS_ERROR_NOT_IMPLEMENTED;
    574 
    575     case nsXPTType::T_VOID:
    576     case nsXPTType::T_PSTRING_SIZE_IS:
    577     case nsXPTType::T_PWSTRING_SIZE_IS:
    578     default:
    579       LOG(("unexpected parameter type\n"));
    580       return NS_ERROR_UNEXPECTED;
    581   }
    582   return NS_OK;
    583 }
    584 
    585 static nsresult
    586578SetupParam(const nsXPTParamInfo &p, nsXPTCVariant &v)
    587579{
     
    591583  {
    592584    v.ptr = nsnull;
     585    v.flags = 0;
    593586
    594587    switch (t.TagPart())
     
    596589      case nsXPTType::T_ASTRING:
    597590      case nsXPTType::T_DOMSTRING:
    598         v.ptr = new nsString();
    599         if (!v.ptr)
     591        v.val.p = new nsString();
     592        if (!v.val.p)
    600593          return NS_ERROR_OUT_OF_MEMORY;
    601         v.val.p = v.ptr;
    602594        v.type = t;
    603         v.flags = nsXPTCVariant::PTR_IS_DATA | nsXPTCVariant::VAL_IS_DOMSTR;
     595        v.SetValIsDOMString();
    604596        break;
    605597
    606598      case nsXPTType::T_UTF8STRING:
    607599      case nsXPTType::T_CSTRING:
    608         v.ptr = new nsCString();
    609         if (!v.ptr)
     600        v.val.p = new nsCString();
     601        if (!v.val.p)
    610602          return NS_ERROR_OUT_OF_MEMORY;
    611         v.val.p = v.ptr;
    612603        v.type = t;
    613         v.flags = nsXPTCVariant::PTR_IS_DATA | nsXPTCVariant::VAL_IS_CSTR;
     604        v.SetValIsCString();
    614605        break;
    615606
     
    624615    v.ptr = &v.val;
    625616    v.type = t;
    626     v.flags = nsXPTCVariant::PTR_IS_DATA;
    627 
    628     // nsID, string and wstring types are not understood as dippers (see
    629     // DIPPER_TYPE in xpidl.h) but they behave like dippers too. Therefore we
    630     // need to treat them so manually.
     617    v.flags = 0;
     618    v.SetPtrIsData();
     619
     620    // the ownership of output nsID, string, wstring, interface pointers and
     621    // arrays is transferred to the receiving party. Therefore, we need to
     622    // instruct FinishParam() to perform a cleanup after serializing them.
    631623    switch (t.TagPart())
    632624    {
     
    634626      case nsXPTType::T_CHAR_STR:
    635627      case nsXPTType::T_WCHAR_STR:
    636         // add VAL_IS_ALLOCD to cause FinishParam() to do cleanup
    637         v.flags |= nsXPTCVariant::VAL_IS_ALLOCD;
     628      case nsXPTType::T_ARRAY:
     629        v.SetValIsAllocated();
     630        break;
     631      case nsXPTType::T_INTERFACE:
     632      case nsXPTType::T_INTERFACE_IS:
     633        v.SetValIsInterface();
    638634        break;
    639635      default:
     
    652648
    653649  if (v.IsValAllocated())
    654       nsMemory::Free(v.val.p);
     650    nsMemory::Free(v.val.p);
    655651  else if (v.IsValInterface())
    656652    ((nsISupports *) v.val.p)->Release();
     
    797793
    798794    case nsXPTType::T_ARRAY:
    799       LOG(("array types are not yet supported\n"));
    800       return NS_ERROR_NOT_IMPLEMENTED;
     795      // arrays are deserialized after all other params outside this routine
     796      break;
    801797
    802798    case nsXPTType::T_VOID:
     
    808804  }
    809805  return NS_OK;
     806}
     807
     808//-----------------------------------------------------------------------------
     809//
     810// Returns an element from the nsXPTCMiniVariant array by properly casting it to
     811// nsXPTCVariant when requested
     812#define GET_PARAM(params, isXPTCVariantArray, idx) \
     813    (isXPTCVariantArray ? ((nsXPTCVariant *) params) [idx] : params [idx])
     814
     815// isResult is PR_TRUE if the size_is and length_is params are out or retval
     816// so that nsXPTCMiniVariants contain pointers to their locations instead of the
     817// values themselves.
     818static nsresult
     819GetArrayParamInfo(nsIInterfaceInfo *iinfo, uint16 methodIndex,
     820                  const nsXPTMethodInfo &methodInfo, nsXPTCMiniVariant *params,
     821                  PRBool isXPTCVariantArray, const nsXPTParamInfo &paramInfo,
     822                  PRBool isResult, PRUint32 &size, PRUint32 &length,
     823                  nsXPTType &elemType)
     824{
     825  // XXX multidimensional arrays are not supported so dimension is always 0 for
     826  // getting the size_is argument number of the array itself and 1 for getting
     827  // the type of elements stored in the array.
     828
     829  nsresult rv;
     830
     831  // get the array size
     832  PRUint8 sizeArg;
     833  rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0, &sizeArg);
     834  if (NS_FAILED(rv))
     835    return rv;
     836
     837  // get the number of valid elements
     838  PRUint8 lenArg;
     839  rv = iinfo->GetLengthIsArgNumberForParam(methodIndex, &paramInfo, 0, &lenArg);
     840  if (NS_FAILED(rv))
     841    return rv;
     842
     843  // according to XPT specs
     844  // (http://www.mozilla.org/scriptable/typelib_file.html), size_is and
     845  // length_is for arrays is always uint32. Check this too.
     846  {
     847    nsXPTParamInfo pi = methodInfo.GetParam (sizeArg);
     848    if (pi.GetType().TagPart() != nsXPTType::T_U32)
     849    {
     850      LOG(("unexpected size_is() parameter type: $d\n",
     851           pi.GetType().TagPart()));
     852      return NS_ERROR_UNEXPECTED;
     853    }
     854
     855    pi = methodInfo.GetParam (lenArg);
     856    if (pi.GetType().TagPart() != nsXPTType::T_U32)
     857    {
     858      LOG(("unexpected length_is() parameter type: $d\n",
     859           pi.GetType().TagPart()));
     860      return NS_ERROR_UNEXPECTED;
     861    }
     862  }
     863
     864  if (isResult)
     865  {
     866    length = *((PRUint32 *) GET_PARAM(params,isXPTCVariantArray, lenArg).val.p);
     867    size = *((PRUint32 *) GET_PARAM(params, isXPTCVariantArray, sizeArg).val.p);
     868  }
     869  else
     870  {
     871    length = GET_PARAM(params, isXPTCVariantArray, lenArg).val.u32;
     872    size = GET_PARAM(params, isXPTCVariantArray, sizeArg).val.u32;
     873  }
     874
     875  if (length > size)
     876  {
     877    NS_WARNING("length_is() value is greater than size_is() value");
     878    length = size;
     879  }
     880
     881  // get type of array elements
     882  rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &elemType);
     883  if (NS_FAILED(rv))
     884    return rv;
     885
     886  if (elemType.IsArithmetic() &&
     887      (elemType.IsPointer() || elemType.IsUniquePointer() ||
     888       elemType.IsReference()))
     889  {
     890    LOG(("arrays of pointers and references to arithmetic types are "
     891         "not yet supported\n"));
     892    return NS_ERROR_NOT_IMPLEMENTED;
     893  }
     894
     895  if (elemType.IsArray())
     896  {
     897    LOG(("multidimensional arrays are not yet supported\n"));
     898    return NS_ERROR_NOT_IMPLEMENTED;
     899  }
     900
     901  return NS_OK;
     902}
     903
     904static nsresult
     905GetTypeSize(const nsXPTType &type, PRUint32 &size, PRBool &isSimple)
     906{
     907  // get the type size in bytes
     908  size = 0;
     909  isSimple = PR_TRUE;
     910  switch (type.TagPart())
     911  {
     912    case nsXPTType::T_I8:             size = sizeof(PRInt8);      break;
     913    case nsXPTType::T_I16:            size = sizeof(PRInt16);     break;
     914    case nsXPTType::T_I32:            size = sizeof(PRInt32);     break;
     915    case nsXPTType::T_I64:            size = sizeof(PRInt64);     break;
     916    case nsXPTType::T_U8:             size = sizeof(PRUint8);     break;
     917    case nsXPTType::T_U16:            size = sizeof(PRUint16);    break;
     918    case nsXPTType::T_U32:            size = sizeof(PRUint32);    break;
     919    case nsXPTType::T_U64:            size = sizeof(PRUint64);    break;
     920    case nsXPTType::T_FLOAT:          size = sizeof(float);       break;
     921    case nsXPTType::T_DOUBLE:         size = sizeof(double);      break;
     922    case nsXPTType::T_BOOL:           size = sizeof(PRBool);      break;
     923    case nsXPTType::T_CHAR:           size = sizeof(char);        break;
     924    case nsXPTType::T_WCHAR:          size = sizeof(PRUnichar);   break;
     925    case nsXPTType::T_IID:            /* fall through */
     926    case nsXPTType::T_CHAR_STR:       /* fall through */
     927    case nsXPTType::T_WCHAR_STR:      /* fall through */
     928    case nsXPTType::T_INTERFACE:      /* fall through */
     929    case nsXPTType::T_INTERFACE_IS:   /* fall through */
     930    case nsXPTType::T_ASTRING:        /* fall through */
     931    case nsXPTType::T_DOMSTRING:      /* fall through */
     932    case nsXPTType::T_UTF8STRING:     /* fall through */
     933    case nsXPTType::T_CSTRING:        /* fall through */
     934      size = sizeof(void *);
     935      isSimple = PR_FALSE;
     936      break;
     937    default:
     938      LOG(("unexpected parameter type: %d\n", type.TagPart()));
     939      return NS_ERROR_UNEXPECTED;
     940  }
     941
     942  return NS_OK;
     943}
     944
     945static nsresult
     946SerializeArrayParam(ipcDConnectService *dConnect,
     947                    ipcMessageWriter &writer, PRUint32 peerID,
     948                    nsIInterfaceInfo *iinfo, uint16 methodIndex,
     949                    const nsXPTMethodInfo &methodInfo,
     950                    nsXPTCMiniVariant *params, PRBool isXPTCVariantArray,
     951                    const nsXPTParamInfo &paramInfo,
     952                    void *array, nsVoidArray &wrappers)
     953{
     954  if (!array)
     955  {
     956    // put 0 to indicate null array
     957    writer.PutInt8(0);
     958    return NS_OK;
     959  }
     960
     961  // put 1 to indicate non-null array
     962  writer.PutInt8(1);
     963
     964  PRUint32 size = 0;
     965  PRUint32 length = 0;
     966  nsXPTType elemType;
     967
     968  nsresult rv = GetArrayParamInfo(iinfo, methodIndex, methodInfo, params,
     969                                  isXPTCVariantArray, paramInfo, PR_FALSE,
     970                                  size, length, elemType);
     971  if (NS_FAILED (rv))
     972      return rv;
     973
     974  PRUint32 elemSize = 0;
     975  PRBool isSimple = PR_TRUE;
     976  rv = GetTypeSize(elemType, elemSize, isSimple);
     977  if (NS_FAILED (rv))
     978      return rv;
     979
     980  if (isSimple)
     981  {
     982    // this is a simple arithmetic type, write the whole array at once
     983    writer.PutBytes(array, length * elemSize);
     984    return NS_OK;
     985  }
     986
     987  // iterate over valid (length_is) elements of the array
     988  // and serialize each of them
     989  nsXPTCMiniVariant v;
     990  for (PRUint32 i = 0; i < length; ++i)
     991  {
     992    v.val.p = ((void **) array) [i];
     993
     994    if (elemType.IsInterfacePointer())
     995    {
     996      nsID iid;
     997      rv = dConnect->GetIIDForMethodParam(iinfo, &methodInfo, paramInfo, elemType,
     998                                          methodIndex, params, isXPTCVariantArray,
     999                                          iid);
     1000      if (NS_SUCCEEDED(rv))
     1001        rv = dConnect->SerializeInterfaceParam(writer, peerID, iid,
     1002                                               (nsISupports *) v.val.p,
     1003                                               wrappers);
     1004    }
     1005    else
     1006      rv = SerializeParam(writer, elemType, v);
     1007
     1008    if (NS_FAILED(rv))
     1009        return rv;
     1010  }
     1011
     1012  return NS_OK;
     1013}
     1014
     1015// isResult is PR_TRUE if the array param is out or retval
     1016static nsresult
     1017DeserializeArrayParam(ipcDConnectService *dConnect,
     1018                      ipcMessageReader &reader, PRUint32 peerID,
     1019                      nsIInterfaceInfo *iinfo, uint16 methodIndex,
     1020                      const nsXPTMethodInfo &methodInfo,
     1021                      nsXPTCMiniVariant *params, PRBool isXPTCVariantArray,
     1022                      const nsXPTParamInfo &paramInfo,
     1023                      PRBool isResult, void *&array)
     1024{
     1025  PRUint32 size = 0;
     1026  PRUint32 length = 0;
     1027  nsXPTType elemType;
     1028
     1029  nsresult rv = GetArrayParamInfo(iinfo, methodIndex, methodInfo, params,
     1030                                  isXPTCVariantArray, paramInfo, isResult,
     1031                                  size, length, elemType);
     1032  if (NS_FAILED(rv))
     1033    return rv;
     1034
     1035  PRUint8 prefix = reader.GetInt8();
     1036  if (prefix == 0)
     1037  {
     1038    // it's a null array
     1039    array = nsnull;
     1040    return NS_OK;
     1041  }
     1042  // sanity
     1043  if (prefix != 1)
     1044  {
     1045    LOG(("unexpected array prefix: %u\n", prefix));
     1046    return NS_ERROR_UNEXPECTED;
     1047  }
     1048
     1049  PRUint32 elemSize = 0;
     1050  PRBool isSimple = PR_TRUE;
     1051  rv = GetTypeSize(elemType, elemSize, isSimple);
     1052  if (NS_FAILED (rv))
     1053      return rv;
     1054
     1055  void *arr = nsMemory::Alloc(size * elemSize);
     1056  if (arr == nsnull)
     1057    return NS_ERROR_OUT_OF_MEMORY;
     1058
     1059  // initialize the unused space of the array with zeroes
     1060  if (length < size)
     1061    memset(((PRUint8 *) arr) + length * elemSize, 0,
     1062           (size - length) * elemSize);
     1063
     1064  if (isSimple)
     1065  {
     1066    // this is a simple arithmetic type, read the whole array at once
     1067    reader.GetBytes(arr, length * elemSize);
     1068
     1069    array = arr;
     1070    return NS_OK;
     1071  }
     1072
     1073  // iterate over valid (length_is) elements of the array
     1074  // and deserialize each of them individually
     1075  nsXPTCVariant v;
     1076  for (PRUint32 i = 0; i < length; ++i)
     1077  {
     1078    rv = DeserializeParam(reader, elemType, v);
     1079
     1080    if (NS_SUCCEEDED(rv) && elemType.IsInterfacePointer())
     1081    {
     1082      // grab the DConAddr value temporarily stored in the param
     1083      PtrBits bits = (PtrBits) v.val.p;
     1084
     1085      // DeserializeInterfaceParamBits needs IID only if it's a remote object
     1086      nsID iid;
     1087      if (bits & PTRBITS_REMOTE_BIT)
     1088        rv = dConnect->GetIIDForMethodParam(iinfo, &methodInfo, paramInfo,
     1089                                            elemType, methodIndex,
     1090                                            params, isXPTCVariantArray, iid);
     1091      if (NS_SUCCEEDED(rv))
     1092      {
     1093        nsISupports *obj = nsnull;
     1094        rv = dConnect->DeserializeInterfaceParamBits(bits, peerID, iid, obj);
     1095        if (NS_SUCCEEDED(rv))
     1096          v.val.p = obj;
     1097      }
     1098    }
     1099
     1100    if (NS_FAILED(rv))
     1101      break;
     1102
     1103    // note that we discard extended param informaton provided by nsXPTCVariant
     1104    // and will have to "reconstruct" it from the type tag in FinishArrayParam()
     1105    ((void **) arr) [i] = v.val.p;
     1106  }
     1107
     1108  if (NS_FAILED(rv))
     1109    nsMemory::Free(arr);
     1110  else
     1111    array = arr;
     1112
     1113  return rv;
     1114}
     1115
     1116static void
     1117FinishArrayParam(nsIInterfaceInfo *iinfo, uint16 methodIndex,
     1118                 const nsXPTMethodInfo &methodInfo, nsXPTCMiniVariant *params,
     1119                 PRBool isXPTCVariantArray, const nsXPTParamInfo &paramInfo,
     1120                 const nsXPTCMiniVariant &arrayVal)
     1121{
     1122  // nothing to do for a null array
     1123  void *arr = arrayVal.val.p;
     1124  if (!arr)
     1125    return;
     1126
     1127  PRUint32 size = 0;
     1128  PRUint32 length = 0;
     1129  nsXPTType elemType;
     1130
     1131  // note that FinishArrayParam is called only from OnInvoke to free memory
     1132  // after the call has been served. When OnInvoke sets up out and retval
     1133  // parameters for the real method, it passes pointers to the nsXPTCMiniVariant
     1134  // elements of the params array themselves so that they will eventually
     1135  // receive the returned values. For this reason, both in 'in' param and
     1136  // 'out/retaval' param cases, size_is and length_is may be read by
     1137  // GetArrayParamInfo() by value. Therefore, isResult is always PR_FALSE.
     1138  nsresult rv = GetArrayParamInfo(iinfo, methodIndex, methodInfo, params,
     1139                                  isXPTCVariantArray, paramInfo, PR_FALSE,
     1140                                  size, length, elemType);
     1141  if (NS_FAILED (rv))
     1142      return;
     1143
     1144  nsXPTCVariant v;
     1145  v.ptr = nsnull;
     1146  v.flags = 0;
     1147
     1148  // iterate over valid (length_is) elements of the array
     1149  // and free each of them
     1150  for (PRUint32 i = 0; i < length; ++i)
     1151  {
     1152    v.type = elemType.TagPart();
     1153
     1154    switch (elemType.TagPart())
     1155    {
     1156      case nsXPTType::T_I8:             /* fall through */
     1157      case nsXPTType::T_I16:            /* fall through */
     1158      case nsXPTType::T_I32:            /* fall through */
     1159      case nsXPTType::T_I64:            /* fall through */
     1160      case nsXPTType::T_U8:             /* fall through */
     1161      case nsXPTType::T_U16:            /* fall through */
     1162      case nsXPTType::T_U32:            /* fall through */
     1163      case nsXPTType::T_U64:            /* fall through */
     1164      case nsXPTType::T_FLOAT:          /* fall through */
     1165      case nsXPTType::T_DOUBLE:         /* fall through */
     1166      case nsXPTType::T_BOOL:           /* fall through */
     1167      case nsXPTType::T_CHAR:           /* fall through */
     1168      case nsXPTType::T_WCHAR:          /* fall through */
     1169        // nothing to free for arithmetic types
     1170        continue;
     1171      case nsXPTType::T_IID:            /* fall through */
     1172      case nsXPTType::T_CHAR_STR:       /* fall through */
     1173      case nsXPTType::T_WCHAR_STR:      /* fall through */
     1174        v.val.p = ((void **) arr) [i];
     1175        v.SetValIsAllocated();
     1176        break;
     1177      case nsXPTType::T_INTERFACE:      /* fall through */
     1178      case nsXPTType::T_INTERFACE_IS:   /* fall through */
     1179        v.val.p = ((void **) arr) [i];
     1180        v.SetValIsInterface();
     1181        break;
     1182      case nsXPTType::T_ASTRING:        /* fall through */
     1183      case nsXPTType::T_DOMSTRING:      /* fall through */
     1184        v.val.p = ((void **) arr) [i];
     1185        v.SetValIsDOMString();
     1186        break;
     1187      case nsXPTType::T_UTF8STRING:     /* fall through */
     1188        v.val.p = ((void **) arr) [i];
     1189        v.SetValIsUTF8String();
     1190        break;
     1191      case nsXPTType::T_CSTRING:        /* fall through */
     1192        v.val.p = ((void **) arr) [i];
     1193        v.SetValIsCString();
     1194        break;
     1195      default:
     1196        LOG(("unexpected parameter type: %d\n", elemType.TagPart()));
     1197        return;
     1198    }
     1199
     1200    FinishParam(v);
     1201  }
    8101202}
    8111203
     
    9951387    return DConnectStubKey::Key(mPeerID, mInstance);
    9961388  }
    997  
     1389
    9981390  NS_IMETHOD_(nsrefcnt) AddRefIPC();
    999  
     1391
    10001392private:
    10011393  nsCOMPtr<nsIInterfaceInfo> mIInfo;
     
    10061398  // the "client id" of our IPC peer.  this guy owns the real object.
    10071399  PRUint32 mPeerID;
    1008  
     1400
    10091401  // cached nsISupports stub for this object
    10101402  DConnectStub *mCachedISupports;
    1011  
     1403
    10121404  // stack of reference counter values (protected by
    10131405  // ipcDConnectService::StubLock())
     
    11611553      // the wrapper from the instance map on failure)
    11621554      wrapper->AddRefIPC();
    1163        
     1555
    11641556      if (!wrappers.AppendElement(wrapper))
    11651557      {
     
    11711563      // wrapper remains referenced when passing it to the client
    11721564      // (will be released upon DCON_OP_RELEASE)
    1173      
    1174       // send address of the instance wrapper, and set the low bit
    1175       // to indicate that this is an instance wrapper.
    1176       PtrBits bits = ((PtrBits) wrapper) | 0x1;
     1565
     1566      // send address of the instance wrapper, and set the low bit to indicate
     1567      // to the remote party that this is a remote instance wrapper.
     1568      PtrBits bits = ((PtrBits) wrapper) | PTRBITS_REMOTE_BIT;
    11771569      writer.PutBytes(&bits, sizeof(bits));
    11781570    }
    11791571    NS_IF_RELEASE(stub);
    11801572  }
     1573  return NS_OK;
     1574}
     1575
     1576// NOTE: peer and iid are ignored if bits doesn't contain PTRBITS_REMOTE_BIT
     1577nsresult
     1578ipcDConnectService::DeserializeInterfaceParamBits(PtrBits bits, PRUint32 peer,
     1579                                                  const nsID &iid,
     1580                                                  nsISupports *&obj)
     1581{
     1582  nsresult rv;
     1583
     1584  obj = nsnull;
     1585
     1586  if (bits & PTRBITS_REMOTE_BIT)
     1587  {
     1588    // pointer is to a remote object.  we need to build a stub.
     1589
     1590    bits &= ~PTRBITS_REMOTE_BIT;
     1591
     1592    DConnectStub *stub;
     1593    rv = CreateStub(iid, peer, (DConAddr) bits, &stub);
     1594    if (NS_SUCCEEDED(rv))
     1595      obj = stub;
     1596  }
     1597  else if (bits)
     1598  {
     1599    // pointer is to one of our instance wrappers. Replace it with the
     1600    // real instance.
     1601
     1602    DConnectInstance *wrapper = (DConnectInstance *) bits;
     1603    // make sure we've been sent a valid wrapper
     1604    if (!CheckInstanceAndAddRef(wrapper))
     1605    {
     1606      NS_NOTREACHED("instance wrapper not found");
     1607      return NS_ERROR_INVALID_ARG;
     1608    }
     1609    obj = wrapper->RealInstance();
     1610    NS_ADDREF(obj);
     1611    NS_RELEASE(wrapper);
     1612  }
     1613  else
     1614  {
     1615    // obj is alredy nsnull
     1616  }
     1617
    11811618  return NS_OK;
    11821619}
     
    14341871        // the wrapper from the instance map on failure)
    14351872        wrapper->AddRefIPC();
    1436        
     1873
    14371874        if (!wrappers.AppendElement(wrapper))
    14381875        {
     
    14451882        // (will be released upon DCON_OP_RELEASE)
    14461883
    1447         // send address of the instance wrapper, and set the low bit
    1448         // to indicate that this is an instance wrapper.
    1449         PtrBits bits = ((PtrBits) wrapper) | 0x1;
     1884        // send address of the instance wrapper, and set the low bit to indicate
     1885        // to the remote party that this is a remote instance wrapper.
     1886        PtrBits bits = ((PtrBits) wrapper) | PTRBITS_REMOTE_BIT;
    14501887        writer.PutBytes(&bits, sizeof(bits));
    14511888
     
    15441981  PtrBits bits = (PtrBits) (instance);
    15451982
    1546   if (bits & 0x1)
     1983  if (bits & PTRBITS_REMOTE_BIT)
    15471984  {
    15481985    // pointer is a peer-side exception instance wrapper,
     
    15852022    else
    15862023    {
    1587       DConAddr addr = (DConAddr) (bits & ~0x1);
     2024      DConAddr addr = (DConAddr) (bits & ~PTRBITS_REMOTE_BIT);
    15882025      nsRefPtr<DConnectStub> stub;
    15892026      rv = CreateStub(nsIException::GetIID(), peer, addr,
     
    16482085  LOG(("{%p} DConnectStub::<dtor>(): peer=%d instance=%p {%s}\n",
    16492086       this, mPeerID, mInstance, name));
    1650 #endif   
    1651    
     2087#endif
     2088
    16522089  // release the cached nsISupports instance if it's not the same object
    16532090  if (mCachedISupports != 0 && mCachedISupports != this)
     
    16872124    {
    16882125      nsrefcnt top = (nsrefcnt) (long) mRefCntLevels.Peek();
    1689       NS_ASSERTION(top <= count + 1, "refcount is beyond the top level"); 
     2126      NS_ASSERTION(top <= count + 1, "refcount is beyond the top level");
    16902127
    16912128      if (top == count + 1)
     
    17082145        // leave the lock before sending a message
    17092146        stubLock.unlock();
    1710      
     2147
    17112148        nsresult rv;
    17122149
     
    17162153        msg.request_index = 0; // not used, set to some unused value
    17172154        msg.instance = mInstance;
    1718    
     2155
    17192156        // fire off asynchronously... we don't expect any response to this message.
    17202157        rv = IPC_SendMessage(mPeerID, kDConnectTargetID,
     
    17302167    NS_LOG_RELEASE(this, count, "DConnectStub");
    17312168  }
    1732  
     2169
    17332170  if (0 == count)
    17342171  {
     
    18302267    // stub lock remains held until we've queried the peer
    18312268  }
    1832  
     2269
    18332270  // else, we need to query the peer object by making an IPC call
    18342271
     
    19012338    return rv;
    19022339  nsCOMPtr <nsIExceptionManager> em;
    1903   rv = es->GetCurrentExceptionManager (getter_AddRefs(em)); 
     2340  rv = es->GetCurrentExceptionManager (getter_AddRefs(em));
    19042341  if (NS_FAILED (rv))
    19052342    return rv;
     
    19072344  if (NS_FAILED (rv))
    19082345    return rv;
    1909    
     2346
    19102347  // ensure ipcDConnectService is not deleted before we finish
    19112348  nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
     
    19512388        nsID iid;
    19522389        rv = dConnect->GetIIDForMethodParam(mIInfo, aInfo, paramInfo, type,
    1953                                              aMethodIndex, i, aParams, PR_FALSE, iid);
     2390                                             aMethodIndex, aParams, PR_FALSE, iid);
    19542391        if (NS_SUCCEEDED(rv))
    19552392          rv = dConnect->SerializeInterfaceParam(writer, mPeerID, iid,
     
    19672404      // report error early if NULL pointer is passed as an output parameter
    19682405      return NS_ERROR_NULL_POINTER;
     2406    }
     2407  }
     2408
     2409  // serialize input array parameters after everything else since the
     2410  // deserialization procedure will need to get a size_is value which may be
     2411  // stored in any preceeding or following param
     2412  for (i=0; i<paramCount; ++i)
     2413  {
     2414    const nsXPTParamInfo &paramInfo = aInfo->GetParam(i);
     2415
     2416    if (paramInfo.GetType().IsArray() &&
     2417        paramInfo.IsIn() && !paramInfo.IsDipper())
     2418    {
     2419      rv = SerializeArrayParam(dConnect, writer, mPeerID, mIInfo, aMethodIndex,
     2420                               *aInfo, aParams, PR_FALSE, paramInfo,
     2421                               aParams[i].val.p, wrappers);
     2422      if (NS_FAILED(rv))
     2423        return rv;
    19692424    }
    19702425  }
     
    20112466  if (NS_FAILED(rv))
    20122467  {
    2013     NS_ASSERTION(completion.ParamsLen() >= sizeof(void*),
     2468    NS_ASSERTION(completion.ParamsLen() == 0 ||
     2469                 completion.ParamsLen() >= sizeof(void*),
    20142470                 "invalid nsIException serialization length");
    20152471    if (completion.ParamsLen() >= sizeof(void*))
     
    20472503
    20482504    // fixup any interface pointers using a second pass so we can properly
    2049     // handle INTERFACE_IS referencing an IID that is an out param!
     2505    // handle INTERFACE_IS referencing an IID that is an out param! This pass is
     2506    // also used to deserialize arrays (array data goes after all other params).
    20502507    for (i=0; i<paramCount && NS_SUCCEEDED(rv); ++i)
    20512508    {
     
    20532510      if (aParams[i].val.p && (paramInfo.IsOut() || paramInfo.IsRetval()))
    20542511      {
     2512        void **pptr = (void **) aParams[i].val.p;
    20552513        const nsXPTType &type = paramInfo.GetType();
    20562514        if (type.IsInterfacePointer())
    20572515        {
    2058           PtrBits bits = (PtrBits) *((void **) aParams[i].val.p);
    2059           if (bits & 0x1)
     2516          // grab the DConAddr value temporarily stored in the param
     2517          PtrBits bits = (PtrBits) *pptr;
     2518          *pptr = nsnull;
     2519
     2520          // DeserializeInterfaceParamBits needs IID only if it's a remote object
     2521          nsID iid;
     2522          if (bits & PTRBITS_REMOTE_BIT)
     2523            rv = dConnect->GetIIDForMethodParam(mIInfo, aInfo, paramInfo, type,
     2524                                                aMethodIndex, aParams, PR_FALSE,
     2525                                                iid);
     2526          if (NS_SUCCEEDED(rv))
    20602527          {
    2061             *((void **) aParams[i].val.p) = (void *) (bits & ~0x1);
    2062 
    2063             nsID iid;
    2064             rv = dConnect->GetIIDForMethodParam(mIInfo, aInfo, paramInfo, type,
    2065                                                  aMethodIndex, i, aParams, PR_FALSE, iid);
    2066             if (NS_SUCCEEDED(rv))
    2067             {
    2068               DConnectStub *stub;
    2069               void **pptr = (void **) aParams[i].val.p;
    2070               rv = dConnect->CreateStub(iid, mPeerID, (DConAddr) *pptr, &stub);
     2528              nsISupports *obj = nsnull;
     2529              rv = dConnect->DeserializeInterfaceParamBits(bits, mPeerID, iid, obj);
    20712530              if (NS_SUCCEEDED(rv))
    2072                 *((nsISupports **) aParams[i].val.p) = stub;
    2073             }
     2531                *pptr = obj;
    20742532          }
    2075           else if (bits)
    2076           {
    2077             // pointer is to one of our instance wrappers. Replace it with the
    2078             // real instance.
    2079             DConnectInstance *wrapper = (DConnectInstance *) bits;
    2080             if (dConnect->CheckInstanceAndAddRef(wrapper))
    2081             {
    2082               *((void **) aParams[i].val.p) = wrapper->RealInstance();
    2083               NS_ADDREF(wrapper->RealInstance());
    2084               wrapper->Release();
    2085             }
    2086             else
    2087             {
    2088               NS_NOTREACHED("instance wrapper not found");
    2089               rv = NS_ERROR_INVALID_ARG;
    2090             }
    2091           }
    2092           else
    2093           {
    2094             *((void **) aParams[i].val.p) = nsnull;
    2095           }
     2533        }
     2534        else if (type.IsArray())
     2535        {
     2536          void *array = nsnull;
     2537          rv = DeserializeArrayParam(dConnect, reader, mPeerID, mIInfo,
     2538                                     aMethodIndex, *aInfo, aParams, PR_FALSE,
     2539                                     paramInfo, PR_TRUE, array);
     2540          if (NS_SUCCEEDED(rv))
     2541            *pptr = array;
    20962542        }
    20972543      }
     
    23792825  // (after which no DConnectInstances may exist), so forcibly delete them
    23802826  // disregarding the reference counter
    2381    
     2827
    23822828#ifdef IPC_LOGGING
    23832829  const char *name;
     
    24902936  printf("ipcDConnectService Stats\n");
    24912937  printf(" => number of worker threads: %d\n", mWorkers.Count());
     2938  LOG(("ipcDConnectService Stats\n"));
     2939  LOG((" => number of worker threads: %d\n", mWorkers.Count()));
    24922940#endif
    24932941
     
    25312979                                         const nsXPTType &type,
    25322980                                         PRUint16 methodIndex,
    2533                                          PRUint8 paramIndex,
    25342981                                         nsXPTCMiniVariant *dispatchParams,
    2535                                          PRBool isFullVariantArray,
     2982                                         PRBool isXPTCVariantArray,
    25362983                                         nsID &result)
    25372984{
     
    25563003      return NS_ERROR_UNEXPECTED;
    25573004
    2558     nsID *p;
    2559     if (isFullVariantArray)
    2560       p = (nsID *) ((nsXPTCVariant *) dispatchParams)[argnum].val.p;
    2561     else
    2562       p = (nsID *) dispatchParams[argnum].val.p;
     3005    nsID *p = (nsID *) GET_PARAM(dispatchParams, isXPTCVariantArray, argnum).val.p;
    25633006    if (!p)
    25643007      return NS_ERROR_UNEXPECTED;
     
    31303573ipcDConnectService::OnRelease(PRUint32 peer, const DConnectRelease *release)
    31313574{
    3132   LOG(("ipcDConnectService::OnRelease [peer=%u instance=%p]\n", 
     3575  LOG(("ipcDConnectService::OnRelease [peer=%u instance=%p]\n",
    31333576       peer, release->instance));
    31343577
     
    32163659
    32173660    // XXX are inout params an issue?
     3661    // yes, we will need to do v.ptr = &v.val for them (DeserializeParam doesn't
     3662    // currently do that) to let the callee correctly pick it up and change.
    32183663
    32193664    if (paramInfo.IsIn() && !paramInfo.IsDipper())
     
    32273672
    32283673  // fixup any interface pointers.  we do this with a second pass so that
    3229   // we can properly handle INTERFACE_IS.
     3674  // we can properly handle INTERFACE_IS. This pass is also used to deserialize
     3675  // arrays (array data goes after all other params).
    32303676  for (i=0; i<paramCount; ++i)
    32313677  {
    32323678    const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
    3233     const nsXPTType &type = paramInfo.GetType();
    3234 
    3235     if (paramInfo.IsIn() && type.IsInterfacePointer())
    3236     {
    3237       PtrBits bits = (PtrBits) params[i].ptr;
    3238       if (bits & 0x1)
    3239       {
    3240         // pointer is to a remote object.  we need to build a stub.
    3241         params[i].ptr = (void *) (bits & ~0x1);
    3242 
     3679    if (paramInfo.IsIn())
     3680    {
     3681      const nsXPTType &type = paramInfo.GetType();
     3682      if (type.IsInterfacePointer())
     3683      {
     3684        // grab the DConAddr value temporarily stored in the param
     3685        PtrBits bits = (PtrBits) params[i].val.p;
     3686
     3687        // DeserializeInterfaceParamBits needs IID only if it's a remote object
    32433688        nsID iid;
    3244         rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
    3245                                   invoke->method_index, i, params, PR_TRUE, iid);
    3246         if (NS_SUCCEEDED(rv))
     3689        if (bits & PTRBITS_REMOTE_BIT)
    32473690        {
    3248           DConnectStub *stub;
    3249           rv = CreateStub(iid, peer, (DConAddr) params[i].ptr, &stub);
    3250           if (NS_SUCCEEDED(rv))
    3251           {
    3252             params[i].val.p = params[i].ptr = stub;
    3253             params[i].SetValIsInterface();
    3254           }
     3691          rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
     3692                                    invoke->method_index, params, PR_TRUE, iid);
     3693          if (NS_FAILED(rv))
     3694            goto end;
    32553695        }
     3696
     3697        nsISupports *obj = nsnull;
     3698        rv = DeserializeInterfaceParamBits(bits, peer, iid, obj);
    32563699        if (NS_FAILED(rv))
    32573700          goto end;
    3258       }
    3259       else if (bits)
    3260       {
    3261         // pointer is to one of our instance wrappers.
    3262 
    3263         DConnectInstance *wrapper = (DConnectInstance *) params[i].ptr;
    3264         // make sure we've been sent a valid wrapper
    3265         if (!CheckInstanceAndAddRef(wrapper))
    3266         {
    3267           NS_NOTREACHED("instance wrapper not found");
    3268           rv = NS_ERROR_INVALID_ARG;
     3701
     3702        params[i].val.p = obj;
     3703        // mark as interface to let FinishParam() release this param
     3704        params[i].SetValIsInterface();
     3705      }
     3706      else if (type.IsArray())
     3707      {
     3708        void *array = nsnull;
     3709        rv = DeserializeArrayParam(this, reader, peer, iinfo,
     3710                                   invoke->method_index, *methodInfo, params,
     3711                                   PR_TRUE, paramInfo, PR_FALSE, array);
     3712        if (NS_FAILED(rv))
    32693713          goto end;
    3270         }
    3271         params[i].val.p = params[i].ptr = wrapper->RealInstance();
    3272         wrapper->Release();
    3273         // do not mark as an interface -- doesn't need to be freed
    3274       }
    3275       else
    3276       {
    3277         params[i].val.p = params[i].ptr = nsnull;
    3278         // do not mark as an interface -- doesn't need to be freed
     3714
     3715        params[i].val.p = array;
     3716        // mark to let FinishParam() free this param
     3717        params[i].SetValIsAllocated();
    32793718      }
    32803719    }
     
    33133752end:
    33143753  LOG(("sending INVOKE_REPLY: rv=%x\n", rv));
    3315  
     3754
    33163755  // balance CheckInstanceAndAddRef()
    33173756  if (wrapper)
     
    33503789          nsID iid;
    33513790          rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
    3352                                     invoke->method_index, i, params, PR_TRUE, iid);
     3791                                    invoke->method_index, params, PR_TRUE, iid);
    33533792          if (NS_SUCCEEDED(rv))
    33543793            rv = SerializeInterfaceParam(writer, peer, iid,
    33553794                                         (nsISupports *) params[i].val.p, wrappers);
    3356 
    3357           // mark as an interface to let FinishParam() to release this param
    3358           if (NS_SUCCEEDED(rv))
    3359             params[i].SetValIsInterface();
    33603795        }
    33613796        else
     
    33693804      }
    33703805    }
     3806
     3807    if (NS_SUCCEEDED(rv))
     3808    {
     3809      // serialize output array parameters after everything else since the
     3810      // deserialization procedure will need to get a size_is value which may be
     3811      // stored in any preceeding or following param
     3812      for (i=0; i<paramCount; ++i)
     3813      {
     3814        const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
     3815
     3816        if (paramInfo.GetType().IsArray() &&
     3817            (paramInfo.IsRetval() || paramInfo.IsOut()))
     3818        {
     3819          rv = SerializeArrayParam(this, writer, peer, iinfo, invoke->method_index,
     3820                                   *methodInfo, params, PR_TRUE, paramInfo,
     3821                                   params[i].val.p, wrappers);
     3822          if (NS_FAILED(rv))
     3823          {
     3824            reply.result = rv;
     3825            break;
     3826          }
     3827        }
     3828      }
     3829    }
    33713830  }
    33723831
     
    33833842  if (params)
    33843843  {
     3844    // free individual elements of arrays (note: before freeing arrays
     3845    // themselves in FinishParam())
     3846    for (i=0; i<paramUsed; ++i)
     3847    {
     3848      const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
     3849      if (paramInfo.GetType().IsArray())
     3850        FinishArrayParam(iinfo, invoke->method_index, *methodInfo,
     3851                         params, PR_TRUE, paramInfo, params[i]);
     3852    }
     3853
    33853854    for (i=0; i<paramUsed; ++i)
    33863855      FinishParam(params[i]);
  • trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h

    r4863 r6850  
    185185};
    186186
     187// used elsewhere like nsAtomTable to safely represent the integral value
     188// of an address.
     189typedef unsigned long PtrBits;
     190
     191// bit flag that defines if a PtrBits value represents a remote object
     192#define PTRBITS_REMOTE_BIT 0x1
     193
    187194class DConnectStub;
    188195typedef nsDataHashtable<DConnectStubKey, DConnectStub *> DConnectStubMap;
     
    209216                                            const nsXPTType &type,
    210217                                            PRUint16 methodIndex,
    211                                             PRUint8 paramIndex,
    212218                                            nsXPTCMiniVariant *dispatchParams,
    213                                             PRBool isFullVariantArray,
     219                                            PRBool isXPTCVariantArray,
    214220                                            nsID &result);
    215221
     
    218224                                               nsISupports *obj,
    219225                                               nsVoidArray &wrappers);
     226  NS_HIDDEN_(nsresult) DeserializeInterfaceParamBits(PtrBits bits, PRUint32 peer,
     227                                                     const nsID &iid,
     228                                                     nsISupports *&obj);
    220229
    221230  NS_HIDDEN_(nsresult) SerializeException(ipcMessageWriter &writer,
     
    241250  PRLock *StubLock() { return mStubLock; }
    242251  PRLock *StubQILock() { return mStubQILock; }
    243  
     252
    244253  static nsRefPtr <ipcDConnectService> GetInstance() {
    245254    return nsRefPtr <ipcDConnectService> (mInstance);
     
    293302  // our IPC client ID
    294303  PRUint32 mSelfID;
    295  
     304
    296305  // global lock to protect access to protect DConnectStub::QueryInterface()
    297306  // (we cannot use mStubLock because it isn't supposed to be held long,
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette