fix for 86789 git-svn-id: svn://10.0.0.236/trunk@97937 18797224-902f-48f8-a5cc-f745e15eee43
475 lines
18 KiB
C++
475 lines
18 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Sun Microsystems,
|
|
* Inc. Portions created by Sun are
|
|
* Copyright (C) 1999 Sun Microsystems, Inc. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Igor Kushnirskiy <idk@eng.sun.com>
|
|
*/
|
|
#include "nsIAllocator.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "bcXPCOMMarshalToolkit.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "bcXPCOMStubsAndProxies.h"
|
|
#include "nsCRT.h"
|
|
#include "bcXPCOMLog.h"
|
|
|
|
static NS_DEFINE_CID(kXPCOMStubsAndProxies,BC_XPCOMSTUBSANDPROXIES_CID);
|
|
static nsID nullID = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
|
|
|
bcXPCOMMarshalToolkit::bcXPCOMMarshalToolkit(PRUint16 _methodIndex, nsIInterfaceInfo *_interfaceInfo,
|
|
nsXPTCMiniVariant* _params, bcIORB *_orb) {
|
|
callSide = onClient;
|
|
orb = _orb;
|
|
methodIndex = _methodIndex;
|
|
interfaceInfo = _interfaceInfo;
|
|
interfaceInfo->GetMethodInfo(methodIndex,(const nsXPTMethodInfo**) &info); // These do *not* make copies ***explicit bending of XPCOM rules***
|
|
PRUint32 paramCount = info->GetParamCount();
|
|
if (paramCount > 0) {
|
|
params = (nsXPTCVariant*)malloc(sizeof(nsXPTCVariant) * paramCount);
|
|
if (params == nsnull) {
|
|
return;
|
|
}
|
|
for (unsigned int i = 0; i < paramCount; i++) {
|
|
uint8 flags = info->GetParam(i).IsOut() ? nsXPTCVariant::PTR_IS_DATA : 0;
|
|
(params)[i].Init(_params[i], info->GetParam(i).GetType(),flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
bcXPCOMMarshalToolkit::bcXPCOMMarshalToolkit(PRUint16 _methodIndex, nsIInterfaceInfo *_interfaceInfo,
|
|
nsXPTCVariant* _params, bcIORB *_orb) {
|
|
callSide = onServer;
|
|
orb = _orb;
|
|
methodIndex = _methodIndex;
|
|
interfaceInfo = _interfaceInfo;
|
|
interfaceInfo->GetMethodInfo(methodIndex,(const nsXPTMethodInfo **)&info); // These do *not* make copies ***explicit bending of XPCOM rules***
|
|
params = _params;
|
|
}
|
|
|
|
bcXPCOMMarshalToolkit::~bcXPCOMMarshalToolkit() {
|
|
//nb
|
|
}
|
|
|
|
class xpAllocator : public bcIAllocator { //nb make is smarter. It should deallocate allocated memory.
|
|
public:
|
|
xpAllocator(nsIAllocator *_allocator) {
|
|
allocator = _allocator;
|
|
}
|
|
virtual ~xpAllocator() {}
|
|
virtual void * Alloc(size_t size) {
|
|
return allocator->Alloc(size);
|
|
}
|
|
virtual void Free(void *ptr) {
|
|
allocator->Free(ptr);
|
|
}
|
|
virtual void * Realloc(void* ptr, size_t size) {
|
|
return allocator->Realloc(ptr,size);
|
|
}
|
|
private:
|
|
nsCOMPtr<nsIAllocator> allocator;
|
|
};
|
|
|
|
|
|
nsresult bcXPCOMMarshalToolkit::Marshal(bcIMarshaler *m) {
|
|
PRLogModuleInfo *log = bcXPCOMLog::GetLog();
|
|
PR_LOG(log,PR_LOG_DEBUG,("--bcXPCOMMarshalToolkit::Marshal\n"));
|
|
nsresult r = NS_OK;
|
|
PRUint32 paramCount = info->GetParamCount();
|
|
for (unsigned int i = 0; (i < paramCount) && NS_SUCCEEDED(r); i++) {
|
|
nsXPTParamInfo param = info->GetParam(i);
|
|
PRBool isOut = param.IsOut();
|
|
if ((callSide == onClient && !param.IsIn())
|
|
|| (callSide == onServer && !param.IsOut())) {
|
|
continue;
|
|
}
|
|
nsXPTCVariant *value = & params[i];
|
|
void *data;
|
|
data = (isOut) ? value->ptr : value;
|
|
r = MarshalElement(m,data,¶m,param.GetType().TagPart(),i);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
nsresult bcXPCOMMarshalToolkit::UnMarshal(bcIUnMarshaler *um) {
|
|
bcIAllocator * allocator = new xpAllocator(nsAllocator::GetGlobalAllocator());
|
|
PRUint32 paramCount = info->GetParamCount();
|
|
for (unsigned int i = 0; i < paramCount; i++) {
|
|
nsXPTParamInfo param = info->GetParam(i);
|
|
PRBool isOut = param.IsOut();
|
|
nsXPTCMiniVariant * value;
|
|
value = ¶ms[i]; //we need to set value for client side
|
|
nsXPTType type = param.GetType();
|
|
uint8 flags = isOut ? nsXPTCVariant::PTR_IS_DATA : 0;
|
|
if (callSide == onServer
|
|
&& param.IsOut()) { //we need to allocate memory for out parametr
|
|
value->val.p = allocator->Alloc(sizeof(nsXPTCMiniVariant)); // sizeof(nsXPTCMiniVariant) is good
|
|
params[i].Init(*value,type,flags);
|
|
}
|
|
if ( (callSide == onServer && !param.IsIn()
|
|
|| (callSide == onClient && !param.IsOut()))){
|
|
continue;
|
|
}
|
|
void *data = (isOut) ? params[i].ptr : value;
|
|
UnMarshalElement(data, um, ¶m, param.GetType().TagPart(),allocator);
|
|
value = (nsXPTCMiniVariant*)((isOut) ? &data : data);
|
|
params[i].Init(*value,type, flags);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult bcXPCOMMarshalToolkit::GetArraySizeFromParam( nsIInterfaceInfo *_interfaceInfo,
|
|
const nsXPTMethodInfo* method,
|
|
const nsXPTParamInfo& param,
|
|
uint16 _methodIndex,
|
|
uint8 paramIndex,
|
|
nsXPTCVariant* nativeParams,
|
|
SizeMode mode,
|
|
PRUint32* result) {
|
|
//code borrowed from mozilla/js/src/xpconnect/src/xpcwrappedjsclass.cpp
|
|
uint8 argnum;
|
|
nsresult rv;
|
|
if(mode == GET_SIZE) {
|
|
rv = _interfaceInfo->GetSizeIsArgNumberForParam(_methodIndex, ¶m, 0, &argnum);
|
|
} else {
|
|
rv = _interfaceInfo->GetLengthIsArgNumberForParam(_methodIndex, ¶m, 0, &argnum);
|
|
}
|
|
if(NS_FAILED(rv)) {
|
|
return PR_FALSE;
|
|
}
|
|
const nsXPTParamInfo& arg_param = method->GetParam(argnum);
|
|
const nsXPTType& arg_type = arg_param.GetType();
|
|
|
|
// XXX require PRUint32 here - need to require in compiler too!
|
|
if(arg_type.IsPointer() || arg_type.TagPart() != nsXPTType::T_U32)
|
|
return PR_FALSE;
|
|
|
|
if(arg_param.IsOut())
|
|
*result = *(PRUint32*)nativeParams[argnum].ptr;
|
|
else
|
|
*result = nativeParams[argnum].val.u32;
|
|
|
|
return PR_TRUE;
|
|
}
|
|
|
|
bcXPType bcXPCOMMarshalToolkit::XPTType2bcXPType(uint8 type) {
|
|
switch(type) {
|
|
case nsXPTType::T_I8 :
|
|
return bc_T_I8;
|
|
case nsXPTType::T_U8 :
|
|
return bc_T_U8;
|
|
case nsXPTType::T_I16 :
|
|
return bc_T_I16;
|
|
case nsXPTType::T_U16 :
|
|
return bc_T_U16;
|
|
case nsXPTType::T_I32 :
|
|
return bc_T_I32;
|
|
case nsXPTType::T_U32 :
|
|
return bc_T_U32;
|
|
case nsXPTType::T_I64 :
|
|
return bc_T_I64;
|
|
case nsXPTType::T_U64 :
|
|
return bc_T_U64;
|
|
case nsXPTType::T_FLOAT :
|
|
return bc_T_FLOAT;
|
|
case nsXPTType::T_DOUBLE :
|
|
return bc_T_DOUBLE;
|
|
case nsXPTType::T_BOOL :
|
|
return bc_T_BOOL;
|
|
case nsXPTType::T_CHAR :
|
|
return bc_T_CHAR;
|
|
case nsXPTType::T_WCHAR :
|
|
return bc_T_WCHAR;
|
|
case nsXPTType::T_IID :
|
|
return bc_T_IID;
|
|
case nsXPTType::T_CHAR_STR :
|
|
case nsXPTType::T_PSTRING_SIZE_IS:
|
|
return bc_T_CHAR_STR;
|
|
case nsXPTType::T_WCHAR_STR :
|
|
case nsXPTType::T_PWSTRING_SIZE_IS:
|
|
return bc_T_WCHAR_STR;
|
|
case nsXPTType::T_INTERFACE :
|
|
case nsXPTType::T_INTERFACE_IS :
|
|
return bc_T_INTERFACE;
|
|
case nsXPTType::T_ARRAY:
|
|
return bc_T_ARRAY;
|
|
default:
|
|
return bc_T_UNDEFINED;
|
|
|
|
}
|
|
}
|
|
|
|
nsresult bcXPCOMMarshalToolkit::MarshalElement(bcIMarshaler *m, void *data, nsXPTParamInfo * param,
|
|
uint8 type, uint8 ind) {
|
|
PRLogModuleInfo * log = bcXPCOMLog::GetLog();
|
|
PR_LOG(log,PR_LOG_DEBUG,("--bcXPCOMMarshalToolkit::MarshalElement ind=%d\n",ind));
|
|
nsresult r = NS_OK;
|
|
switch(type) {
|
|
case nsXPTType::T_IID :
|
|
if (data == NULL) {
|
|
data = &nullID;
|
|
} else {
|
|
data = *(char**)data;
|
|
}
|
|
case nsXPTType::T_I8 :
|
|
case nsXPTType::T_I16 :
|
|
case nsXPTType::T_I32 :
|
|
case nsXPTType::T_I64 :
|
|
case nsXPTType::T_U8 :
|
|
case nsXPTType::T_U16 :
|
|
case nsXPTType::T_U32 :
|
|
case nsXPTType::T_U64 :
|
|
case nsXPTType::T_FLOAT :
|
|
case nsXPTType::T_DOUBLE :
|
|
case nsXPTType::T_BOOL :
|
|
case nsXPTType::T_CHAR :
|
|
case nsXPTType::T_WCHAR :
|
|
m->WriteSimple(data, XPTType2bcXPType(type));
|
|
break;
|
|
case nsXPTType::T_CHAR_STR :
|
|
case nsXPTType::T_WCHAR_STR :
|
|
{
|
|
data = *(char **)data;
|
|
size_t length = 0;
|
|
if (data != NULL) {
|
|
if (type == nsXPTType::T_WCHAR_STR) {
|
|
length = nsCRT::strlen((const PRUnichar*)data);
|
|
PR_LOG(log, PR_LOG_DEBUG,
|
|
("--[c++] bcXPCOMMarshalToolkit::MarshalElement T_WCHAR_STR length=%d\n",length));
|
|
length *= 2;
|
|
length +=2;
|
|
for (unsigned int i = 0; i < length && type == nsXPTType::T_WCHAR_STR; i++) {
|
|
char c = ((char*)data)[i];
|
|
PR_LOG(log, PR_LOG_DEBUG,
|
|
("--[c++] bcXPCOMMarshalToolkit::MarshalElement T_WCHAR_STR [%d] = %d %c\n",i,c,c));
|
|
}
|
|
} else {
|
|
length = nsCRT::strlen((const char*)data);
|
|
length+=1;
|
|
}
|
|
}
|
|
m->WriteString(data,length);
|
|
break;
|
|
}
|
|
case nsXPTType::T_INTERFACE :
|
|
case nsXPTType::T_INTERFACE_IS :
|
|
{
|
|
nsIID *iid;
|
|
if (type == nsXPTType::T_INTERFACE) {
|
|
if(NS_FAILED(r = interfaceInfo->
|
|
GetIIDForParam(methodIndex, param, &iid))) {
|
|
return r;
|
|
}
|
|
} else {
|
|
uint8 argnum;
|
|
if (NS_FAILED(r = interfaceInfo->GetInterfaceIsArgNumberForParam(methodIndex,
|
|
param, &argnum))) {
|
|
return r;
|
|
}
|
|
const nsXPTParamInfo& arg_param = info->GetParam(argnum);
|
|
const nsXPTType& arg_type = arg_param.GetType();
|
|
if(arg_type.IsPointer() &&
|
|
arg_type.TagPart() == nsXPTType::T_IID) {
|
|
if(arg_param.IsOut())
|
|
iid =*((nsID**)params[argnum].ptr);
|
|
else
|
|
iid = (nsID*)params[argnum].val.p;
|
|
}
|
|
}
|
|
PR_LOG(log, PR_LOG_DEBUG, ("--[c++]XPCOMMarshallToolkit INTERFACE iid=%s\n",iid->ToString()));
|
|
bcOID oid = 0;
|
|
if (*(char**)data != NULL) {
|
|
NS_WITH_SERVICE(bcXPCOMStubsAndProxies, xpcomStubsAndProxies, kXPCOMStubsAndProxies, &r);
|
|
if (NS_FAILED(r)) {
|
|
return r;
|
|
}
|
|
xpcomStubsAndProxies->GetOID(*(nsISupports**)data, orb,&oid);
|
|
}
|
|
m->WriteSimple(&oid, XPTType2bcXPType(type));
|
|
m->WriteSimple(iid,bc_T_IID);
|
|
break;
|
|
}
|
|
case nsXPTType::T_PSTRING_SIZE_IS:
|
|
case nsXPTType::T_PWSTRING_SIZE_IS:
|
|
case nsXPTType::T_ARRAY: //nb array of interfaces [to do]
|
|
{
|
|
PRUint32 arraySize;
|
|
if (!GetArraySizeFromParam(interfaceInfo,info, *param,methodIndex,
|
|
ind,params,GET_LENGTH, &arraySize)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
if (type == nsXPTType::T_ARRAY) {
|
|
nsXPTType datumType;
|
|
if(NS_FAILED(interfaceInfo->GetTypeForParam(methodIndex, param, 1,&datumType))) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
m->WriteSimple(&arraySize,bc_T_U32);
|
|
PRInt16 elemSize = GetSimpleSize(datumType);
|
|
char *current = *(char**)data;
|
|
for (unsigned int i = 0; i < arraySize; i++, current+=elemSize) {
|
|
MarshalElement(m,current,param,datumType.TagPart(),0);
|
|
}
|
|
} else {
|
|
size_t length = 0;
|
|
if (type == nsXPTType::T_PWSTRING_SIZE_IS) {
|
|
length = arraySize * sizeof(PRUnichar);
|
|
} else {
|
|
length = arraySize;
|
|
}
|
|
m->WriteString(data, length);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
nsresult
|
|
bcXPCOMMarshalToolkit::UnMarshalElement(void *data, bcIUnMarshaler *um, nsXPTParamInfo * param, uint8 type, bcIAllocator * allocator) {
|
|
PRLogModuleInfo *log = bcXPCOMLog::GetLog();
|
|
nsresult r = NS_OK;
|
|
switch(type) {
|
|
case nsXPTType::T_IID :
|
|
{
|
|
nsID *id = new nsID();
|
|
um->ReadSimple(id,XPTType2bcXPType(type));
|
|
if (nullID.Equals(*id)) {
|
|
delete id;
|
|
*(char**)data = NULL;
|
|
} else {
|
|
*(char**)data = (char*)id;
|
|
}
|
|
break;
|
|
}
|
|
case nsXPTType::T_I8 :
|
|
case nsXPTType::T_I16 :
|
|
case nsXPTType::T_I32 :
|
|
case nsXPTType::T_I64 :
|
|
case nsXPTType::T_U8 :
|
|
case nsXPTType::T_U16 :
|
|
case nsXPTType::T_U32 :
|
|
case nsXPTType::T_U64 :
|
|
case nsXPTType::T_FLOAT :
|
|
case nsXPTType::T_DOUBLE :
|
|
case nsXPTType::T_BOOL :
|
|
case nsXPTType::T_CHAR :
|
|
case nsXPTType::T_WCHAR :
|
|
um->ReadSimple(data,XPTType2bcXPType(type));
|
|
PR_LOG(log, PR_LOG_DEBUG, ("--[c++] bcXPCOMMarshalToolkit::UnMarshalElement %c\n",*(char*)data));
|
|
break;
|
|
case nsXPTType::T_PSTRING_SIZE_IS:
|
|
case nsXPTType::T_PWSTRING_SIZE_IS:
|
|
case nsXPTType::T_CHAR_STR :
|
|
case nsXPTType::T_WCHAR_STR :
|
|
size_t size;
|
|
um->ReadString(data,&size,allocator);
|
|
{
|
|
char *str = *(char**)data;
|
|
for (int i = 0; i < size && type == nsXPTType::T_WCHAR_STR; i++) {
|
|
char c = str[i];
|
|
PR_LOG(log, PR_LOG_DEBUG, ("--[c++] bcXPCOMMarshalToolkit::UnMarshalElement T_WCHAR_STR [%d] = %d %c\n",i,(int)c,c));
|
|
}
|
|
}
|
|
break;
|
|
case nsXPTType::T_INTERFACE :
|
|
case nsXPTType::T_INTERFACE_IS :
|
|
{
|
|
PR_LOG(log, PR_LOG_DEBUG, ("--[c++] we have an interface\n"));
|
|
bcOID oid;
|
|
um->ReadSimple(&oid,XPTType2bcXPType(type));
|
|
PR_LOG(log, PR_LOG_DEBUG, ("%d oid\n",(int) oid));
|
|
nsIID iid;
|
|
um->ReadSimple(&iid,bc_T_IID);
|
|
nsISupports *proxy = NULL;
|
|
if (oid != 0) {
|
|
NS_WITH_SERVICE(bcXPCOMStubsAndProxies, xpcomStubsAndProxies,
|
|
kXPCOMStubsAndProxies, &r);
|
|
if (NS_FAILED(r)) {
|
|
return r;
|
|
}
|
|
xpcomStubsAndProxies->GetProxy(oid, iid, orb,&proxy);
|
|
}
|
|
*(nsISupports**)data = proxy;
|
|
break;
|
|
}
|
|
case nsXPTType::T_ARRAY:
|
|
{
|
|
nsXPTType datumType;
|
|
if(NS_FAILED(interfaceInfo->GetTypeForParam(methodIndex, param, 1,&datumType))) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
PRUint32 arraySize;
|
|
PRInt16 elemSize = GetSimpleSize(datumType);
|
|
um->ReadSimple(&arraySize,bc_T_U32);
|
|
|
|
char * current;
|
|
*(char**)data = current = (char *) allocator->Alloc(elemSize*arraySize);
|
|
//nb what about arraySize=0?
|
|
for (unsigned int i = 0; i < arraySize; i++, current+=elemSize) {
|
|
UnMarshalElement(current, um, param, datumType.TagPart(), allocator);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
PRInt16 bcXPCOMMarshalToolkit::GetSimpleSize(uint8 type) {
|
|
PRInt16 size = -1;
|
|
switch(type) {
|
|
case nsXPTType::T_I8:
|
|
case nsXPTType::T_U8:
|
|
size = sizeof(PRInt8);
|
|
break;
|
|
case nsXPTType::T_I16:
|
|
case nsXPTType::T_U16:
|
|
size = sizeof(PRInt16);
|
|
break;
|
|
case nsXPTType::T_I32:
|
|
case nsXPTType::T_U32:
|
|
size = sizeof(PRInt32);
|
|
break;
|
|
case nsXPTType::T_I64:
|
|
case nsXPTType::T_U64:
|
|
size = sizeof(PRInt64);
|
|
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;
|
|
default:
|
|
size = sizeof(void*);
|
|
}
|
|
return size;
|
|
}
|
|
|
|
|