aMethodIndex, i, aParams, iid);
aMethodIndex, i, aParams, PR_FALSE, iid);
DConnectStub::CallMethod(PRUint16 aMethodIndex,                         const nsXPTMethodInfo *aInfo,                         nsXPTCMiniVariant *aParams){  nsresult rv;  LOG(("DConnectStub::CallMethod [methodIndex=%hu]\n", aMethodIndex));  // dump arguments  PRUint8 i, paramCount = aInfo->GetParamCount();  LOG(("  name=%s\n", aInfo->GetName()));  LOG(("  param-count=%u\n", (PRUint32) paramCount));  ipcMessageWriter writer(16 * paramCount);  // INVOKE message header  DConnectInvoke invoke;  invoke.opcode_major = DCON_OP_INVOKE;  invoke.opcode_minor = 0;  invoke.request_index = NewRequestIndex();  invoke.instance = mInstance;  invoke.method_index = aMethodIndex;  writer.PutBytes(&invoke, sizeof(invoke));  // list of wrappers that get created during parameter serialization.  if we  // are unable to send the INVOKE message, then we'll clean these up.  nsVoidArray wrappers;  for (i=0; i<paramCount; ++i)  {    const nsXPTParamInfo &paramInfo = aInfo->GetParam(i);    if (paramInfo.IsIn() && !paramInfo.IsDipper())    {      const nsXPTType &type = paramInfo.GetType();      if (type.IsInterfacePointer())      {        nsID iid;        rv = gDConnect->GetIIDForMethodParam(mIInfo, aInfo, paramInfo, type,                                             aMethodIndex, i, aParams, iid);        if (NS_SUCCEEDED(rv))          rv = SerializeInterfaceParam(writer, mPeerID, iid, type, aParams[i], wrappers);      }      else        rv = SerializeParam(writer, type, aParams[i]);      if (NS_FAILED(rv))        return rv;    }  }  rv = IPC_SendMessage(mPeerID, kDConnectTargetID,                       writer.GetBuffer(),                       writer.GetSize());  if (NS_FAILED(rv))  {    // INVOKE message wasn't delivered; clean up wrappers    DeleteWrappers(wrappers);    return rv;  }  // now, we wait for the method call to complete.  during that time, it's  // possible that we'll receive other method call requests.  we'll process  // those while waiting for out method call to complete.  it's critical that  // we do so since those other method calls might need to complete before  // out method call can complete!  DConnectInvokeCompletion completion(&invoke);  do  {    rv = IPC_WaitMessage(mPeerID, kDConnectTargetID, &completion,                         DCON_WAIT_TIMEOUT);    if (NS_FAILED(rv))    {      // INVOKE message wasn't received; clean up wrappers      DeleteWrappers(wrappers);      return rv;    }  }  while (completion.IsPending());  rv = completion.GetResult();  if (NS_SUCCEEDED(rv) && completion.ParamsLen() > 0)  {    ipcMessageReader reader(completion.Params(), completion.ParamsLen());    PRUint8 i;    // handle out-params and retvals: DCON_OP_INVOKE_REPLY has the data    for (i=0; i<paramCount; ++i)    {      const nsXPTParamInfo &paramInfo = aInfo->GetParam(i);      if (paramInfo.IsOut() || paramInfo.IsRetval())        DeserializeResult(reader, paramInfo.GetType(), aParams[i]);    }    // fixup any interface pointers using a second pass so we can properly    // handle INTERFACE_IS referencing an IID that is an out param!    for (i=0; i<paramCount; ++i)    {      const nsXPTParamInfo &paramInfo = aInfo->GetParam(i);      if (aParams[i].val.p && (paramInfo.IsOut() || paramInfo.IsRetval()))      {        const nsXPTType &type = paramInfo.GetType();        if (type.IsInterfacePointer())        {          PtrBits bits = (PtrBits) *((void **) aParams[i].val.p);          if (bits & 0x1)          {            *((void **) aParams[i].val.p) = (void *) (bits & ~0x1);            nsID iid;            rv = gDConnect->GetIIDForMethodParam(mIInfo, aInfo, paramInfo, type,                                                 aMethodIndex, i, aParams, iid);            if (NS_SUCCEEDED(rv))            {              DConnectStub *stub;              void **pptr = (void **) aParams[i].val.p;              rv = CreateStub(iid, mPeerID, (DConAddr) *pptr, &stub);              if (NS_SUCCEEDED(rv))                *((nsISupports **) aParams[i].val.p) = stub;            }          }          else          {            // pointer is to one of our instance wrappers.            DConnectInstance *wrapper = (DConnectInstance *) aParams[i].val.p;            *((void **) aParams[i].val.p) = wrapper->RealInstance();          }        }      }    }  }  return rv;}