/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_cli_ure.hxx" #pragma warning(push, 1) #include "windows.h" #pragma warning(pop) #include #include "rtl/ustring.hxx" #include "rtl/ustrbuf.hxx" #include "uno/sequence2.h" #include "typelib/typedescription.hxx" #include "cli_proxy.h" #include "cli_base.h" #include "cli_bridge.h" #using #undef VOID namespace css = com::sun::star; namespace sri = System::Runtime::InteropServices; namespace sr = System::Reflection; namespace st = System::Text; namespace ucss = unoidl::com::sun::star; using namespace rtl; using namespace std; namespace cli_uno { System::String* mapUnoPolymorphicName(System::String* unoName); OUString mapCliTypeName(System::String* typeName); System::String* mapCliPolymorphicName(System::String* unoName); System::String* mapPolymorphicName(System::String* unoName, bool bCliToUno); inline auto_ptr< rtl_mem > seq_allocate( sal_Int32 nElements, sal_Int32 nSize ) { auto_ptr< rtl_mem > seq( rtl_mem::allocate( SAL_SEQUENCE_HEADER_SIZE + (nElements * nSize) ) ); uno_Sequence * p = (uno_Sequence *)seq.get(); p->nRefCount = 1; p->nElements = nElements; return seq; } System::Object* Bridge::map_uno2cli(uno_Interface * pUnoI, typelib_InterfaceTypeDescription *pTD) const { System::Object* retVal= NULL; // get oid rtl_uString * pOid = 0; (*m_uno_env->getObjectIdentifier)( m_uno_env, &pOid, pUnoI ); OSL_ASSERT( 0 != pOid ); OUString oid(pOid, SAL_NO_ACQUIRE); //see if the interface was already mapped System::Type* ifaceType= mapUnoType(reinterpret_cast(pTD)); System::String* sOid= mapUnoString(oid.pData); System::Threading::Monitor::Enter( CliEnvHolder::g_cli_env ); try { retVal = CliEnvHolder::g_cli_env->getRegisteredInterface(sOid, ifaceType); if (retVal) { // There is already an registered object. It can either be a proxy // for the UNO object or a real cli object. In the first case we // tell the proxy that it shall also represent the current UNO // interface. If it already does that, then it does nothing if (srr::RemotingServices::IsTransparentProxy(retVal)) { UnoInterfaceProxy* p = static_cast( srr::RemotingServices::GetRealProxy(retVal)); p->addUnoInterface(pUnoI, pTD); } } else { retVal = UnoInterfaceProxy::create( (Bridge *) this, pUnoI, pTD, oid ); } } __finally { System::Threading::Monitor::Exit( CliEnvHolder::g_cli_env ); } return retVal; } uno_Interface* Bridge::map_cli2uno(System::Object* cliObj, typelib_TypeDescription *pTD) const { uno_Interface* retIface = NULL; // get oid from dot net environment System::String* ds_oid = CliEnvHolder::g_cli_env->getObjectIdentifier( cliObj); OUString ousOid = mapCliString(ds_oid); // look if interface is already mapped m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData, (typelib_InterfaceTypeDescription*) pTD); if ( ! retIface) { System::Threading::Monitor::Enter(__typeof(Cli_environment)); try { m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData, (typelib_InterfaceTypeDescription*) pTD); if ( ! retIface) { retIface = CliProxy::create((Bridge*)this, cliObj, pTD, ousOid); } } __finally { System::Threading::Monitor::Exit(__typeof(Cli_environment)); } } return retIface; } inline System::Type* loadCliType(rtl_uString * unoName) { return loadCliType(mapUnoTypeName(unoName)); } System::Type* loadCliType(System::String * unoName) { System::Type* retVal= NULL; try { //If unoName denotes a polymorphic type, e.g com.sun.star.beans.Defaulted //then we remove the type list, otherwise the type could not be loaded. bool bIsPolymorphic = false; System::String * loadName = unoName; int index = unoName->IndexOf('<'); if (index != -1) { loadName = unoName->Substring(0, index); bIsPolymorphic = true; } System::AppDomain* currentDomain = System::AppDomain::CurrentDomain; sr::Assembly* assems[] = currentDomain->GetAssemblies(); for (int i = 0; i < assems->Length; i++) { retVal = assems[i]->GetType(loadName, false); if (retVal) break; } if (retVal == NULL) { System::String * msg = new System::String(S"A type could not be loaded: "); msg = System::String::Concat(msg, loadName); throw BridgeRuntimeError(mapCliString(msg)); } if (bIsPolymorphic) { retVal = uno::PolymorphicType::GetType(retVal, unoName); } } catch( System::Exception * e) { rtl::OUString ouMessage(mapCliString(e->get_Message())); throw BridgeRuntimeError(ouMessage); } return retVal; } System::Type* mapUnoType(typelib_TypeDescription const * pTD) { return mapUnoType(pTD->pWeakRef); } System::Type* mapUnoType(typelib_TypeDescriptionReference const * pTD) { System::Type * retVal = 0; switch (pTD->eTypeClass) { case typelib_TypeClass_VOID: retVal= __typeof(void); break; case typelib_TypeClass_CHAR: retVal= __typeof(System::Char); break; case typelib_TypeClass_BOOLEAN: retVal= __typeof(System::Boolean); break; case typelib_TypeClass_BYTE: retVal= __typeof(System::Byte); break; case typelib_TypeClass_SHORT: retVal= __typeof(System::Int16); break; case typelib_TypeClass_UNSIGNED_SHORT: retVal= __typeof(System::UInt16); break; case typelib_TypeClass_LONG: retVal= __typeof(System::Int32); break; case typelib_TypeClass_UNSIGNED_LONG: retVal= __typeof(System::UInt32); break; case typelib_TypeClass_HYPER: retVal= __typeof(System::Int64); break; case typelib_TypeClass_UNSIGNED_HYPER: retVal= __typeof(System::UInt64); break; case typelib_TypeClass_FLOAT: retVal= __typeof(System::Single); break; case typelib_TypeClass_DOUBLE: retVal= __typeof(System::Double); break; case typelib_TypeClass_STRING: retVal= __typeof(System::String); break; case typelib_TypeClass_TYPE: retVal= __typeof(System::Type); break; case typelib_TypeClass_ANY: retVal= __typeof(uno::Any); break; case typelib_TypeClass_ENUM: case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION: retVal= loadCliType(pTD->pTypeName); break; case typelib_TypeClass_INTERFACE: { //special handling for XInterface, since it does not exist in cli. rtl::OUString usXInterface(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XInterface")); if (usXInterface.equals(pTD->pTypeName)) retVal= __typeof(System::Object); else retVal= loadCliType(pTD->pTypeName); break; } case typelib_TypeClass_SEQUENCE: { css::uno::TypeDescription seqType( const_cast(pTD)); typelib_TypeDescriptionReference* pElementTDRef= reinterpret_cast(seqType.get())->pType; switch (pElementTDRef->eTypeClass) { case typelib_TypeClass_CHAR: retVal= System::Type::GetType(const_cast(Constants::sArChar)); break; case typelib_TypeClass_BOOLEAN: retVal= System::Type::GetType(const_cast(Constants::sArBoolean)); break; case typelib_TypeClass_BYTE: retVal= System::Type::GetType(const_cast(Constants::sArByte)); break; case typelib_TypeClass_SHORT: retVal= System::Type::GetType(const_cast(Constants::sArInt16)); break; case typelib_TypeClass_UNSIGNED_SHORT: retVal= System::Type::GetType(const_cast(Constants::sArUInt16)); break; case typelib_TypeClass_LONG: retVal= System::Type::GetType(const_cast(Constants::sArInt32)); break; case typelib_TypeClass_UNSIGNED_LONG: retVal= System::Type::GetType(const_cast(Constants::sArUInt32)); break; case typelib_TypeClass_HYPER: retVal= System::Type::GetType(const_cast(Constants::sArInt64)); break; case typelib_TypeClass_UNSIGNED_HYPER: retVal= System::Type::GetType(const_cast(Constants::sArUInt64)); break; case typelib_TypeClass_FLOAT: retVal= System::Type::GetType(const_cast(Constants::sArSingle)); break; case typelib_TypeClass_DOUBLE: retVal= System::Type::GetType(const_cast(Constants::sArDouble)); break; case typelib_TypeClass_STRING: retVal= System::Type::GetType(const_cast(Constants::sArString)); break; case typelib_TypeClass_TYPE: retVal= System::Type::GetType(const_cast(Constants::sArType)); break; case typelib_TypeClass_ANY: case typelib_TypeClass_ENUM: case typelib_TypeClass_EXCEPTION: case typelib_TypeClass_STRUCT: case typelib_TypeClass_INTERFACE: case typelib_TypeClass_SEQUENCE: { retVal= loadCliType(pTD->pTypeName); break; } default: //All cases should be handled by the case statements above OSL_ASSERT(0); break; } break; } default: OSL_ASSERT(false); break; } return retVal; } /** Returns an acquired td. */ typelib_TypeDescriptionReference* mapCliType(System::Type* cliType) { typelib_TypeDescriptionReference* retVal= NULL; if (cliType == NULL) { retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_VOID ); typelib_typedescriptionreference_acquire( retVal ); return retVal; } //check for Enum first, //because otherwise case System::TypeCode::Int32 applies if (cliType->get_IsEnum()) { OUString usTypeName= mapCliTypeName(cliType->get_FullName()); css::uno::Type unoType(css::uno::TypeClass_ENUM, usTypeName); retVal= unoType.getTypeLibType(); typelib_typedescriptionreference_acquire(retVal); } else { switch (System::Type::GetTypeCode(cliType)) { case System::TypeCode::Boolean: retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_BOOLEAN ); typelib_typedescriptionreference_acquire( retVal ); break; case System::TypeCode::Char: retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_CHAR ); typelib_typedescriptionreference_acquire( retVal ); break; case System::TypeCode::Byte: retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_BYTE ); typelib_typedescriptionreference_acquire( retVal ); break; case System::TypeCode::Int16: retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_SHORT ); typelib_typedescriptionreference_acquire( retVal ); break; case System::TypeCode::Int32: retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_LONG ); typelib_typedescriptionreference_acquire( retVal ); break; case System::TypeCode::Int64: retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_HYPER ); typelib_typedescriptionreference_acquire( retVal ); break; case System::TypeCode::UInt16: retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_UNSIGNED_SHORT ); typelib_typedescriptionreference_acquire( retVal ); break; case System::TypeCode::UInt32: retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_UNSIGNED_LONG ); typelib_typedescriptionreference_acquire( retVal ); break; case System::TypeCode::UInt64: retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_UNSIGNED_HYPER ); typelib_typedescriptionreference_acquire( retVal ); break; case System::TypeCode::Single: retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_FLOAT ); typelib_typedescriptionreference_acquire( retVal ); break; case System::TypeCode::Double: retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_DOUBLE ); typelib_typedescriptionreference_acquire( retVal ); break; case System::TypeCode::String: retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_STRING ); typelib_typedescriptionreference_acquire( retVal ); break; default: break; } } if (retVal == NULL) { System::String* cliTypeName= cliType->get_FullName(); // Void if (const_cast(Constants::sVoid)->Equals( cliTypeName)) { retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_VOID ); typelib_typedescriptionreference_acquire( retVal ); } // Type else if (const_cast(Constants::sType)->Equals( cliTypeName)) { retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_TYPE ); typelib_typedescriptionreference_acquire( retVal ); } // Any else if (const_cast(Constants::sAny)->Equals( cliTypeName)) { retVal = * typelib_static_type_getByTypeClass( typelib_TypeClass_ANY ); typelib_typedescriptionreference_acquire( retVal ); } //struct, interfaces, sequences else { OUString usTypeName; uno::PolymorphicType * poly = dynamic_cast(cliType); if (poly != NULL) usTypeName = mapCliTypeName( poly->PolymorphicName); else usTypeName = mapCliTypeName(cliTypeName); typelib_TypeDescription* td = NULL; typelib_typedescription_getByName(&td, usTypeName.pData); if (td) { retVal = td->pWeakRef; typelib_typedescriptionreference_acquire(retVal); typelib_typedescription_release(td); } } } if (retVal == NULL) { OUStringBuffer buf( 128 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[cli_uno bridge] mapCliType():" "could not map type: ") ); buf.append(mapCliString(cliType->get_FullName())); throw BridgeRuntimeError( buf.makeStringAndClear() ); } return retVal; } /** Otherwise a leading "unoidl." is removed. */ System::String* mapUnoTypeName(rtl_uString const * typeName) { OUString usUnoName( const_cast< rtl_uString * >( typeName ) ); st::StringBuilder* buf= new st::StringBuilder(); //determine if the type is a sequence and its dimensions int dims= 0; if (usUnoName[0] == '[') { sal_Int32 index= 1; while (true) { if (usUnoName[index++] == ']') dims++; if (usUnoName[index++] != '[') break; } usUnoName = usUnoName.copy(index - 1); } System::String * sUnoName = mapUnoString(usUnoName.pData); if (sUnoName->Equals(const_cast(Constants::usBool))) buf->Append(const_cast(Constants::sBoolean)); else if (sUnoName->Equals(const_cast(Constants::usChar))) buf->Append(const_cast(Constants::sChar)); else if (sUnoName->Equals(const_cast(Constants::usByte))) buf->Append(const_cast(Constants::sByte)); else if (sUnoName->Equals(const_cast(Constants::usShort))) buf->Append(const_cast(Constants::sInt16)); else if (sUnoName->Equals(const_cast(Constants::usUShort))) buf->Append(const_cast(Constants::sUInt16)); else if (sUnoName->Equals(const_cast(Constants::usLong))) buf->Append(const_cast(Constants::sInt32)); else if (sUnoName->Equals(const_cast(Constants::usULong))) buf->Append(const_cast(Constants::sUInt32)); else if (sUnoName->Equals(const_cast(Constants::usHyper))) buf->Append(const_cast(Constants::sInt64)); else if (sUnoName->Equals(const_cast(Constants::usUHyper))) buf->Append(const_cast(Constants::sUInt64)); else if (sUnoName->Equals(const_cast(Constants::usFloat))) buf->Append(const_cast(Constants::sSingle)); else if (sUnoName->Equals(const_cast(Constants::usDouble))) buf->Append(const_cast(Constants::sDouble)); else if (sUnoName->Equals(const_cast(Constants::usString))) buf->Append(const_cast(Constants::sString)); else if (sUnoName->Equals(const_cast(Constants::usVoid))) buf->Append(const_cast(Constants::sVoid)); else if (sUnoName->Equals(const_cast(Constants::usType))) buf->Append(const_cast(Constants::sType)); else if (sUnoName->Equals(const_cast(Constants::usXInterface))) buf->Append(const_cast(Constants::sObject)); else if (sUnoName->Equals(const_cast(Constants::usAny))) { buf->Append(const_cast(Constants::sAny)); } else { //put "unoidl." at the beginning buf->Append(const_cast(Constants::sUnoidl)); //for polymorphic struct types remove the brackets, e.g mystruct -> mystruct System::String * sName = mapUnoPolymorphicName(sUnoName); buf->Append(sName); } // apend [] for (;dims--;) buf->Append(const_cast(Constants::sBrackets)); return buf->ToString(); } /** For example, there is a uno type com.sun.star.Foo. The values in the type list are uno types and are replaced by cli types, such as System.Char, System.Int32, etc. The präfix unoidl is not added. */ inline System::String* mapUnoPolymorphicName(System::String* unoName) { return mapPolymorphicName(unoName, false); } /** For example, there is a type name such as com.sun.star.Foo. The values in the type list are CLI types and are replaced by uno types, such as char, long, etc. The präfix unoidl remains. */ inline System::String* mapCliPolymorphicName(System::String* unoName) { return mapPolymorphicName(unoName, true); } System::String* mapPolymorphicName(System::String* unoName, bool bCliToUno) { int index = unoName->IndexOf('<'); if (index == -1) return unoName; System::Text::StringBuilder * builder = new System::Text::StringBuilder(256); builder->Append(unoName->Substring(0, index +1 )); //Find the first occurrence of ',' //If the parameter is a polymorphic struct then we neede to ignore everything //between the brackets because it can also contain commas //get the type list within < and > int endIndex = unoName->Length - 1; index++; int cur = index; int countParams = 0; while (cur <= endIndex) { System::Char c = unoName->Chars[cur]; if (c == ',' || c == '>') { //insert a comma if needed if (countParams != 0) builder->Append(S","); countParams++; System::String * sParam = unoName->Substring(index, cur - index); //skip the comma cur++; //the the index to the beginning of the next param index = cur; if (bCliToUno) { builder->Append( mapCliTypeName(sParam).getStr()); } else { OUString s = mapCliString(sParam); builder->Append(mapUnoTypeName(s.pData)); } } else if (c == '<') { cur++; //continue until the matching '>' int numNested = 0; for (;;cur++) { System::Char curChar = unoName->Chars[cur]; if (curChar == '<') { numNested ++; } else if (curChar == '>') { if (numNested > 0) numNested--; else break; } } } cur++; } builder->Append((System::Char) '>'); return builder->ToString(); } OUString mapCliTypeName(System::String* typeName) { int dims= 0; // Array? determine the "rank" (number of "[]") // move from the rightmost end to the left, for example // unoidl.PolymorphicStruct[] // has only a "dimension" of 1 int cur = typeName->Length - 1; bool bRightBracket = false; while (cur >= 0) { System::Char c = typeName->Chars[cur]; if (c == ']') { bRightBracket = true; } else if (c == '[') { if (!bRightBracket) throw BridgeRuntimeError( OUSTR("Typename is wrong. No matching brackets for sequence. Name is: ") + mapCliString(typeName)); bRightBracket = false; dims ++; } else { if (bRightBracket) throw BridgeRuntimeError( OUSTR("Typename is wrong. No matching brackets for sequence. Name is: ") + mapCliString(typeName)); break; } cur--; } if (bRightBracket || cur < 0) throw BridgeRuntimeError( OUSTR("Typename is wrong. ") + mapCliString(typeName)); typeName = typeName->Substring(0, cur + 1); System::Text::StringBuilder * buf = new System::Text::StringBuilder(512); //Put the "[]" at the beginning of the uno type name for (;dims--;) buf->Append(const_cast(Constants::usBrackets)); if (typeName->Equals(const_cast(Constants::sBoolean))) buf->Append(const_cast(Constants::usBool)); else if (typeName->Equals(const_cast(Constants::sChar))) buf->Append(const_cast(Constants::usChar)); else if (typeName->Equals(const_cast(Constants::sByte))) buf->Append(const_cast(Constants::usByte)); else if (typeName->Equals(const_cast(Constants::sInt16))) buf->Append(const_cast(Constants::usShort)); else if (typeName->Equals(const_cast(Constants::sUInt16))) buf->Append(const_cast(Constants::usUShort)); else if (typeName->Equals(const_cast(Constants::sInt32))) buf->Append(const_cast(Constants::usLong)); else if (typeName->Equals(const_cast(Constants::sUInt32))) buf->Append(const_cast(Constants::usULong)); else if (typeName->Equals(const_cast(Constants::sInt64))) buf->Append(const_cast(Constants::usHyper)); else if (typeName->Equals(const_cast(Constants::sUInt64))) buf->Append(const_cast(Constants::usUHyper)); else if (typeName->Equals(const_cast(Constants::sSingle))) buf->Append(const_cast(Constants::usFloat)); else if (typeName->Equals(const_cast(Constants::sDouble))) buf->Append(const_cast(Constants::usDouble)); else if (typeName->Equals(const_cast(Constants::sString))) buf->Append(const_cast(Constants::usString)); else if (typeName->Equals(const_cast(Constants::sVoid))) buf->Append(const_cast(Constants::usVoid)); else if (typeName->Equals(const_cast(Constants::sType))) buf->Append(const_cast(Constants::usType)); else if (typeName->Equals(const_cast(Constants::sObject))) buf->Append(const_cast(Constants::usXInterface)); else if (typeName->Equals(const_cast(Constants::sAny))) buf->Append(const_cast(Constants::usAny)); else { System::String * sName = mapCliPolymorphicName(typeName); int i= sName->IndexOf(L'.'); buf->Append(sName->Substring(i + 1)); } return mapCliString(buf->ToString()); } /** Maps uno types to dot net types. * If uno_data is null then the type description is converted to System::Type */ inline System::String* mapUnoString( rtl_uString const * data) { OSL_ASSERT(data); return new System::String((__wchar_t*) data->buffer, 0, data->length); } OUString mapCliString(System::String const * data) { if (data != NULL) { OSL_ASSERT(sizeof(wchar_t) == sizeof(sal_Unicode)); wchar_t const __pin * pdata= PtrToStringChars(data); return OUString(pdata, const_cast(data)->get_Length()); } else { return OUString(); } } // ToDo convert cli types to expected types, e.g a long to a short where the uno type // is a sal_Int16. This could be necessary if a scripting language (typeless) is used // @param assign the uno_data has to be destructed (in/out args) void Bridge::map_to_uno(void * uno_data, System::Object* cli_data, typelib_TypeDescriptionReference * type, bool assign) const { try{ switch (type->eTypeClass) { case typelib_TypeClass_VOID: break; case typelib_TypeClass_CHAR: { System::Char aChar= *__try_cast(cli_data); *(sal_Unicode*) uno_data= aChar; break; } case typelib_TypeClass_BOOLEAN: { System::Boolean aBool= *__try_cast(cli_data); *(sal_Bool*)uno_data= aBool == true ? sal_True : sal_False; break; } case typelib_TypeClass_BYTE: { System::Byte aByte= *__try_cast(cli_data); *(sal_Int8*) uno_data= aByte; break; } case typelib_TypeClass_SHORT: { System::Int16 aShort= *__try_cast(cli_data); *(sal_Int16*) uno_data= aShort; break; } case typelib_TypeClass_UNSIGNED_SHORT: { System::UInt16 aUShort= *__try_cast(cli_data); *(sal_uInt16*) uno_data= aUShort; break; } case typelib_TypeClass_LONG: { System::Int32 aLong= *__try_cast(cli_data); *(sal_Int32*) uno_data= aLong; break; } case typelib_TypeClass_UNSIGNED_LONG: { System::UInt32 aULong= *__try_cast(cli_data); *(sal_uInt32*) uno_data= aULong; break; } case typelib_TypeClass_HYPER: { System::Int64 aHyper= *__try_cast(cli_data); *(sal_Int64*) uno_data= aHyper; break; } case typelib_TypeClass_UNSIGNED_HYPER: { System::UInt64 aLong= *__try_cast(cli_data); *(sal_uInt64*) uno_data= aLong; break; } case typelib_TypeClass_FLOAT: { System::Single aFloat= *__try_cast(cli_data); *(float*) uno_data= aFloat; break; } case typelib_TypeClass_DOUBLE: { System::Double aDouble= *__try_cast(cli_data); *(double*) uno_data= aDouble; break; } case typelib_TypeClass_STRING: { if (assign && *(rtl_uString**) uno_data) rtl_uString_release(*(rtl_uString**) uno_data); *(rtl_uString **)uno_data = 0; if (cli_data == NULL) { rtl_uString_new((rtl_uString**) uno_data); } else { System::String *s= __try_cast(cli_data); wchar_t const __pin * pdata= PtrToStringChars(s); rtl_uString_newFromStr_WithLength( (rtl_uString**) uno_data, pdata, s->get_Length() ); } break; } case typelib_TypeClass_TYPE: { typelib_TypeDescriptionReference* td= mapCliType(__try_cast( cli_data)); if (assign) { typelib_typedescriptionreference_release( *(typelib_TypeDescriptionReference **)uno_data ); } *(typelib_TypeDescriptionReference **)uno_data = td; break; } case typelib_TypeClass_ANY: { uno_Any * pAny = (uno_Any *)uno_data; if (cli_data == NULL) // null-ref or uninitialized any maps to empty any { if (assign) uno_any_destruct( pAny, 0 ); uno_any_construct( pAny, 0, 0, 0 ); break; } uno::Any aAny= *__try_cast(cli_data); css::uno::Type value_td( mapCliType(aAny.Type), SAL_NO_ACQUIRE); if (assign) uno_any_destruct( pAny, 0 ); try { switch (value_td.getTypeClass()) { case typelib_TypeClass_VOID: pAny->pData = &pAny->pReserved; break; case typelib_TypeClass_CHAR: pAny->pData = &pAny->pReserved; *(sal_Unicode*) &pAny->pReserved = *__try_cast(aAny.Value); break; case typelib_TypeClass_BOOLEAN: pAny->pData = &pAny->pReserved; *(sal_Bool *) &pAny->pReserved = *__try_cast(aAny.Value); break; case typelib_TypeClass_BYTE: pAny->pData = &pAny->pReserved; *(sal_Int8*) &pAny->pReserved = *__try_cast(aAny.Value); break; case typelib_TypeClass_SHORT: pAny->pData = &pAny->pReserved; *(sal_Int16*) &pAny->pReserved = *__try_cast(aAny.Value); break; case typelib_TypeClass_UNSIGNED_SHORT: pAny->pData = &pAny->pReserved; *(sal_uInt16*) &pAny->pReserved = *__try_cast(aAny.Value); break; case typelib_TypeClass_LONG: pAny->pData = &pAny->pReserved; *(sal_Int32*) &pAny->pReserved = *__try_cast(aAny.Value); break; case typelib_TypeClass_UNSIGNED_LONG: pAny->pData = &pAny->pReserved; *(sal_uInt32*) &pAny->pReserved = *__try_cast(aAny.Value); break; case typelib_TypeClass_HYPER: if (sizeof (sal_Int64) <= sizeof (void *)) { pAny->pData = &pAny->pReserved; *(sal_Int64*) &pAny->pReserved = *__try_cast(aAny.Value); } else { auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_Int64) ) ); *(sal_Int64 *) mem.get()= *__try_cast(aAny.Value); pAny->pData = mem.release(); } break; case typelib_TypeClass_UNSIGNED_HYPER: if (sizeof (sal_uInt64) <= sizeof (void *)) { pAny->pData = &pAny->pReserved; *(sal_uInt64*) &pAny->pReserved = *__try_cast(aAny.Value); } else { auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_uInt64) ) ); *(sal_uInt64 *) mem.get()= *__try_cast(aAny.Value); pAny->pData = mem.release(); } break; case typelib_TypeClass_FLOAT: if (sizeof (float) <= sizeof (void *)) { pAny->pData = &pAny->pReserved; *(float*) &pAny->pReserved = *__try_cast(aAny.Value); } else { auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (float) ) ); *(float*) mem.get() = *__try_cast(aAny.Value); pAny->pData = mem.release(); } break; case typelib_TypeClass_DOUBLE: if (sizeof (double) <= sizeof (void *)) { pAny->pData = &pAny->pReserved; *(double*) &pAny->pReserved= *__try_cast(aAny.Value); } else { auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (double) ) ); *(double*) mem.get()= *__try_cast(aAny.Value); pAny->pData= mem.release(); } break; case typelib_TypeClass_STRING: // anies often contain strings; copy string directly { pAny->pData= &pAny->pReserved; OUString _s = mapCliString(static_cast(aAny.Value)); pAny->pReserved= _s.pData; rtl_uString_acquire(_s.pData); break; } case typelib_TypeClass_TYPE: case typelib_TypeClass_ENUM: //ToDo copy enum direct case typelib_TypeClass_SEQUENCE: case typelib_TypeClass_INTERFACE: pAny->pData = &pAny->pReserved; pAny->pReserved = 0; map_to_uno( &pAny->pReserved, aAny.Value, value_td.getTypeLibType(), false /* no assign */); break; case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION: { css::uno::Type anyType(value_td); typelib_TypeDescription* td= NULL; anyType.getDescription(&td); auto_ptr< rtl_mem > mem(rtl_mem::allocate(td->nSize)); typelib_typedescription_release(td); map_to_uno( mem.get(), aAny.Value, value_td.getTypeLibType(), false /* no assign */); pAny->pData = mem.release(); break; } default: { OUStringBuffer buf( 128 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); buf.append(value_td.getTypeName()); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported value type of any!") ); throw BridgeRuntimeError( buf.makeStringAndClear() ); } } } catch(System::InvalidCastException* ) { // ToDo check this if (assign) uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any OUStringBuffer buf( 256 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():Any") ); buf.append(value_td.getTypeName()); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("]The Any type ")); buf.append(value_td.getTypeName()); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" does not correspont " "to its value type: ") ); if(aAny.Value != NULL) { css::uno::Type td(mapCliType(aAny.Value->GetType()), SAL_NO_ACQUIRE); buf.append(td.getTypeName()); } if (assign) uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any throw BridgeRuntimeError( buf.makeStringAndClear() ); } catch (BridgeRuntimeError& ) { if (assign) uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any throw; } catch (...) { if (assign) uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any throw; } pAny->pType = value_td.getTypeLibType(); typelib_typedescriptionreference_acquire(pAny->pType); break; } case typelib_TypeClass_ENUM: { // InvalidCastException is caught at the end of this method System::Int32 aEnum= System::Convert::ToInt32((cli_data)); *(sal_Int32*) uno_data = aEnum; break; } case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION: { css::uno::TypeDescription td(type); typelib_CompoundTypeDescription * comp_td = (typelib_CompoundTypeDescription*) td.get(); typelib_StructTypeDescription * struct_td = NULL; if (type->eTypeClass == typelib_TypeClass_STRUCT) struct_td = (typelib_StructTypeDescription*) td.get(); if ( ! ((typelib_TypeDescription*) comp_td)->bComplete) ::typelib_typedescription_complete( (typelib_TypeDescription**) & comp_td ); sal_Int32 nMembers = comp_td->nMembers; boolean bException= false; System::Type* cliType = NULL; if (cli_data) cliType = cli_data->GetType(); if (0 != comp_td->pBaseTypeDescription) { map_to_uno( uno_data, cli_data, ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef, assign); } sal_Int32 nPos = 0; try { typelib_TypeDescriptionReference * member_type= NULL; rtl::OUString usUnoException(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Exception")); for (; nPos < nMembers; ++nPos) { member_type= comp_td->ppTypeRefs[nPos]; #if OSL_DEBUG_LEVEL >= 2 System::String* __s; sr::FieldInfo* arFields[]; __s = mapUnoString(comp_td->ppMemberNames[nPos]); arFields = cliType != NULL ? cliType->GetFields() : NULL; #endif System::Object* val= NULL; if (cli_data != NULL) { sr::FieldInfo* aField= cliType->GetField( mapUnoString(comp_td->ppMemberNames[nPos])); // special case for Exception.Message property // The com.sun.star.uno.Exception.Message field is mapped to the // System.Exception property. Type.GetField("Message") returns null if ( ! aField && usUnoException.equals(td.get()->pTypeName)) {// get Exception.Message property rtl::OUString usMessageMember(RTL_CONSTASCII_USTRINGPARAM("Message")); if (usMessageMember.equals(comp_td->ppMemberNames[nPos])) { sr::PropertyInfo* pi= cliType->GetProperty( mapUnoString(comp_td->ppMemberNames[nPos])); val= pi->GetValue(cli_data, NULL); } else { OUStringBuffer buf(512); buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("[map_to_uno(): Member: ")); buf.append(comp_td->ppMemberNames[nPos]); throw BridgeRuntimeError(buf.makeStringAndClear()); } } else { val= aField->GetValue(cli_data); } } void * p = (char *) uno_data + comp_td->pMemberOffsets[ nPos ]; //When using polymorphic structs then the parameterized members can be null. //Then we set a default value. bool bDefault = ((struct_td != NULL && struct_td->pParameterizedTypes != NULL && struct_td->pParameterizedTypes[nPos] == sal_True && val == NULL) || cli_data == NULL) ? true : false; switch (member_type->eTypeClass) { case typelib_TypeClass_CHAR: if (bDefault) *(sal_Unicode*) p = 0; else *(sal_Unicode*) p = *__try_cast(val); break; case typelib_TypeClass_BOOLEAN: if (bDefault) *(sal_Bool*) p = sal_False; else *(sal_Bool*) p = *__try_cast(val); break; case typelib_TypeClass_BYTE: if (bDefault) *(sal_Int8*) p = 0; else *(sal_Int8*) p = *__try_cast(val); break; case typelib_TypeClass_SHORT: if (bDefault) *(sal_Int16*) p = 0; else *(sal_Int16*) p = *__try_cast(val); break; case typelib_TypeClass_UNSIGNED_SHORT: if (bDefault) *(sal_uInt16*) p = 0; else *(sal_uInt16*) p = *__try_cast(val); break; case typelib_TypeClass_LONG: if (bDefault) *(sal_Int32*) p = 0; else *(sal_Int32*) p = *__try_cast(val); break; case typelib_TypeClass_UNSIGNED_LONG: if (bDefault) *(sal_uInt32*) p = 0; else *(sal_uInt32*) p = *__try_cast(val); break; case typelib_TypeClass_HYPER: if (bDefault) *(sal_Int64*) p = 0; else *(sal_Int64*) p = *__try_cast(val); break; case typelib_TypeClass_UNSIGNED_HYPER: if (bDefault) *(sal_uInt64*) p = 0; else *(sal_uInt64*) p= *__try_cast(val); break; case typelib_TypeClass_FLOAT: if (bDefault) *(float*) p = 0.; else *(float*) p = *__try_cast(val); break; case typelib_TypeClass_DOUBLE: if (bDefault) *(double*) p = 0.; else *(double*) p = *__try_cast(val); break; default: { // ToDo enum, should be converted here map_to_uno(p, val, member_type, assign); break; } } } } catch (BridgeRuntimeError& e) { bException= true; OUStringBuffer buf(512); buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("[map_to_uno():")); if (cliType) { buf.append(mapCliString(cliType->get_FullName())); buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(".")); buf.append(comp_td->ppMemberNames[nPos]); buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" ")); } buf.append(e.m_message); throw BridgeRuntimeError(buf.makeStringAndClear()); } catch (System::InvalidCastException* ) { bException= true; OUStringBuffer buf( 256 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); if (cliType) { buf.append(mapCliString(cliType->get_FullName())); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(".")); buf.append(comp_td->ppMemberNames[nPos]); } buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] Value has not the required type.")); throw BridgeRuntimeError(buf.makeStringAndClear()); } catch (...) { OSL_ASSERT(0); bException= true; throw; } __finally { if (bException && !assign) // if assign then caller cleans up { // cleanup the members which we have converted so far for ( sal_Int32 nCleanup = 0; nCleanup < nPos; ++nCleanup ) { uno_type_destructData( uno_data, comp_td->ppTypeRefs[ nCleanup ], 0 ); } if (0 != comp_td->pBaseTypeDescription) { uno_destructData( uno_data, (typelib_TypeDescription *)comp_td->pBaseTypeDescription, 0 ); } } } break; } case typelib_TypeClass_SEQUENCE: { TypeDescr td( type ); typelib_TypeDescriptionReference * element_type = ((typelib_IndirectTypeDescription *)td.get())->pType; auto_ptr< rtl_mem > seq; System::Array* ar = NULL; if (cli_data != NULL) { ar = __try_cast(cli_data); sal_Int32 nElements = ar->GetLength(0); try { switch (element_type->eTypeClass) { case typelib_TypeClass_CHAR: seq = seq_allocate(nElements, sizeof (sal_Unicode)); sri::Marshal::Copy(__try_cast(cli_data), 0, & ((uno_Sequence*) seq.get())->elements, nElements); break; case typelib_TypeClass_BOOLEAN: seq = seq_allocate(nElements, sizeof (sal_Bool)); sri::Marshal::Copy(__try_cast(cli_data), 0, & ((uno_Sequence*) seq.get())->elements, nElements); break; case typelib_TypeClass_BYTE: seq = seq_allocate( nElements, sizeof (sal_Int8) ); sri::Marshal::Copy(__try_cast(cli_data), 0, & ((uno_Sequence*) seq.get())->elements, nElements); break; case typelib_TypeClass_SHORT: seq = seq_allocate(nElements, sizeof (sal_Int16)); sri::Marshal::Copy(__try_cast(cli_data), 0, & ((uno_Sequence*) seq.get())->elements, nElements); break; case typelib_TypeClass_UNSIGNED_SHORT: seq = seq_allocate( nElements, sizeof (sal_uInt16) ); sri::Marshal::Copy(static_cast( __try_cast(cli_data)), 0, & ((uno_Sequence*) seq.get())->elements, nElements); break; case typelib_TypeClass_LONG: seq = seq_allocate(nElements, sizeof (sal_Int32)); sri::Marshal::Copy(__try_cast(cli_data), 0, & ((uno_Sequence*) seq.get())->elements, nElements); break; case typelib_TypeClass_UNSIGNED_LONG: seq = seq_allocate( nElements, sizeof (sal_uInt32) ); sri::Marshal::Copy(static_cast( __try_cast(cli_data)), 0, & ((uno_Sequence*) seq.get())->elements, nElements); break; case typelib_TypeClass_HYPER: seq = seq_allocate(nElements, sizeof (sal_Int64)); sri::Marshal::Copy(__try_cast(cli_data), 0, & ((uno_Sequence*) seq.get())->elements, nElements); break; case typelib_TypeClass_UNSIGNED_HYPER: seq = seq_allocate(nElements, sizeof (sal_uInt64)); sri::Marshal::Copy(static_cast( __try_cast(cli_data)), 0, & ((uno_Sequence*) seq.get())->elements, nElements); break; case typelib_TypeClass_FLOAT: seq = seq_allocate(nElements, sizeof (float)); sri::Marshal::Copy(__try_cast(cli_data), 0, & ((uno_Sequence*) seq.get())->elements, nElements); break; case typelib_TypeClass_DOUBLE: seq = seq_allocate(nElements, sizeof (double)); sri::Marshal::Copy(__try_cast(cli_data), 0, & ((uno_Sequence*) seq.get())->elements, nElements); break; case typelib_TypeClass_STRING: { seq = seq_allocate(nElements, sizeof (rtl_uString*)); System::String* arStr[]= __try_cast(cli_data); for (int i= 0; i < nElements; i++) { wchar_t const __pin * pdata= PtrToStringChars(arStr[i]); rtl_uString** pStr= & ((rtl_uString**) & ((uno_Sequence*) seq.get())->elements)[i]; *pStr= NULL; rtl_uString_newFromStr_WithLength( pStr, pdata, arStr[i]->get_Length()); } break; } case typelib_TypeClass_ENUM: seq = seq_allocate(nElements, sizeof (sal_Int32)); for (int i= 0; i < nElements; i++) { ((sal_Int32*) &((uno_Sequence*) seq.get())->elements)[i]= System::Convert::ToInt32(ar->GetValue(i)); } break; case typelib_TypeClass_TYPE: case typelib_TypeClass_ANY: case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION: case typelib_TypeClass_SEQUENCE: case typelib_TypeClass_INTERFACE: { TypeDescr element_td( element_type ); seq = seq_allocate( nElements, element_td.get()->nSize ); for (sal_Int32 nPos = 0; nPos < nElements; ++nPos) { try { void * p= ((uno_Sequence *) seq.get())->elements + (nPos * element_td.get()->nSize); System::Object* elemData= dynamic_cast(cli_data)->GetValue(nPos); map_to_uno( p, elemData, element_td.get()->pWeakRef, false /* no assign */); } catch (...) { // cleanup for ( sal_Int32 nCleanPos = 0; nCleanPos < nPos; ++nCleanPos ) { void * p = ((uno_Sequence *)seq.get())->elements + (nCleanPos * element_td.get()->nSize); uno_destructData( p, element_td.get(), 0 ); } throw; } } break; } default: { OUStringBuffer buf( 128 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported sequence element type: ") ); buf.append( *reinterpret_cast< OUString const * >( &element_type->pTypeName ) ); throw BridgeRuntimeError( buf.makeStringAndClear() ); } } } catch (BridgeRuntimeError& e) { OUStringBuffer buf( 128 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName )); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] conversion failed\n ")); buf.append(e.m_message); throw BridgeRuntimeError(buf.makeStringAndClear()); } catch (System::InvalidCastException* ) { // Ok, checked OUStringBuffer buf( 128 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName) ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] could not convert sequence element type: ") ); buf.append( *reinterpret_cast< OUString const * >( &element_type->pTypeName ) ); throw BridgeRuntimeError( buf.makeStringAndClear() ); } catch (...) { OSL_ASSERT(0); throw; } __finally { if (assign) uno_destructData( uno_data, td.get(), 0 ); } } else { seq = seq_allocate(0, sizeof (sal_Int32)); } *(uno_Sequence **)uno_data = (uno_Sequence *)seq.release(); break; } case typelib_TypeClass_INTERFACE: { if (assign) { uno_Interface * p = *(uno_Interface **)uno_data; if (0 != p) (*p->release)( p ); } if (0 == cli_data) // null-ref { *(uno_Interface **)uno_data = 0; } else { TypeDescr td( type ); uno_Interface * pUnoI = map_cli2uno(cli_data, td.get()); *(uno_Interface **)uno_data = pUnoI; } break; } default: { //ToDo check OUStringBuffer buf( 128 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported type!") ); throw BridgeRuntimeError( buf.makeStringAndClear() ); } } } // BridgeRuntimeError are allowed to be thrown catch (System::InvalidCastException* ) { //ToDo check OUStringBuffer buf( 128 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] could not convert type!") ); throw BridgeRuntimeError( buf.makeStringAndClear() ); } catch (System::NullReferenceException * e) { OUStringBuffer buf(512); buf.appendAscii(RTL_CONSTASCII_STRINGPARAM( "[map_to_uno()] Illegal null reference passed!\n")); buf.append(mapCliString(e->get_StackTrace())); throw BridgeRuntimeError( buf.makeStringAndClear() ); } catch (BridgeRuntimeError& ) { throw; } catch (...) { OSL_ASSERT(0); throw; } } /** @param info The expected target type. Currently info is provdided when this method is called to convert the in/out and out parameters of a call from cli to uno. Then info is always a byref type, e.g. "System.String&". info is used for Any and Enum conversion. @param bDontCreateObj false - a new object is created which holds the mapped uno value and is assigned to cli_data. true - cli_data already contains the newly constructed object. This is the case if a struct is converted then on the first call to map_to_cli the new object is created. If the struct inherits another struct then this function is called recursivly while the newly created object is passed in cli_data. */ void Bridge::map_to_cli( System::Object* *cli_data, void const * uno_data, typelib_TypeDescriptionReference * type, System::Type* info, bool bDontCreateObj) const { switch (type->eTypeClass) { case typelib_TypeClass_CHAR: *cli_data= __box(*(__wchar_t const*)uno_data); break; case typelib_TypeClass_BOOLEAN: *cli_data = __box((*(bool const*)uno_data) == sal_True ? true : false); break; case typelib_TypeClass_BYTE: *cli_data = __box(*(unsigned char const*) uno_data); break; case typelib_TypeClass_SHORT: *cli_data= __box(*(short const*) uno_data); break; case typelib_TypeClass_UNSIGNED_SHORT: *cli_data= __box(*(unsigned short const*) uno_data); break; case typelib_TypeClass_LONG: *cli_data= __box(*(int const*) uno_data); break; case typelib_TypeClass_UNSIGNED_LONG: *cli_data= __box(*(unsigned int const*) uno_data); break; case typelib_TypeClass_HYPER: *cli_data= __box(*(__int64 const*) uno_data); break; case typelib_TypeClass_UNSIGNED_HYPER: *cli_data= __box(*(unsigned __int64 const*) uno_data); break; case typelib_TypeClass_FLOAT: *cli_data= __box(*(float const*) uno_data); break; case typelib_TypeClass_DOUBLE: *cli_data= __box(*(double const*) uno_data); break; case typelib_TypeClass_STRING: { rtl_uString const* sVal= NULL; sVal= *(rtl_uString* const*) uno_data; *cli_data= new System::String((__wchar_t*) sVal->buffer,0, sVal->length); break; } case typelib_TypeClass_TYPE: { *cli_data= mapUnoType( *(typelib_TypeDescriptionReference * const *)uno_data ); break; } case typelib_TypeClass_ANY: { uno_Any const * pAny = (uno_Any const *)uno_data; if (typelib_TypeClass_VOID != pAny->pType->eTypeClass) { System::Object* objCli= NULL; map_to_cli( &objCli, pAny->pData, pAny->pType, 0, false); uno::Any anyVal(mapUnoType(pAny->pType), objCli); *cli_data= __box(anyVal); } else { // void any *cli_data= __box(uno::Any::VOID); } break; } case typelib_TypeClass_ENUM: { if (info != NULL) { OSL_ASSERT(info->get_IsByRef()); info= info->GetElementType(); *cli_data= System::Enum::ToObject(info, *(System::Int32*) uno_data); } else *cli_data= System::Enum::ToObject( mapUnoType(type), *(System::Int32*) uno_data); break; } case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION: { TypeDescr td( type ); typelib_CompoundTypeDescription * comp_td = (typelib_CompoundTypeDescription *) td.get(); if ( ! ((typelib_TypeDescription*) comp_td)->bComplete) ::typelib_typedescription_complete( (typelib_TypeDescription**) & comp_td ); //create the type System::Type* cliType= loadCliType(td.get()->pTypeName); //detect if we recursivly convert inherited structures //If this point is reached because of a recursive call during convering a //struct then we must not create a new object rather we use the one in // cli_data argument. System::Object* cliObj; if (bDontCreateObj) cliObj = *cli_data; // recursive call else { //Special handling for Exception conversion. We must call constructor System::Exception //to pass the message string if (__typeof(ucss::uno::Exception)->IsAssignableFrom(cliType)) { //We need to get the Message field. Therefore we must obtain the offset from //the typedescription. The base interface of all exceptions is //com::sun::star::uno::Exception which contains the message typelib_CompoundTypeDescription* pCTD = comp_td; while (pCTD->pBaseTypeDescription) pCTD = pCTD->pBaseTypeDescription; int nPos = -1; rtl::OUString usMessageMember(RTL_CONSTASCII_USTRINGPARAM("Message")); for (int i = 0; i < pCTD->nMembers; i ++) { #if OSL_DEBUG_LEVEL >= 2 System::String* sMember; sMember = mapUnoString(pCTD->ppMemberNames[i]); #endif if (usMessageMember.equals(pCTD->ppMemberNames[i])) { nPos = i; break; } } OSL_ASSERT (nPos != -1); int offset = pCTD->pMemberOffsets[nPos]; //With the offset within the exception we can get the message string System::String* sMessage = mapUnoString(*(rtl_uString**) ((char*) uno_data + offset)); //We need to find a constructor for the exception that takes the message string //We assume that the first argument is the message string sr::ConstructorInfo* arCtorInfo[] = cliType->GetConstructors(); sr::ConstructorInfo* ctorInfo = NULL; int numCtors = arCtorInfo->get_Length(); //Constructor must at least have 2 params for the base //unoidl.com.sun.star.uno.Exception (String, Object); sr::ParameterInfo * arParamInfo[]; for (int i = 0; i < numCtors; i++) { arParamInfo = arCtorInfo[i]->GetParameters(); if (arParamInfo->get_Length() < 2) continue; ctorInfo = arCtorInfo[i]; break; } OSL_ASSERT(arParamInfo[0]->get_ParameterType()->Equals(__typeof(System::String)) && arParamInfo[1]->get_ParameterType()->Equals(__typeof(System::Object)) && arParamInfo[0]->get_Position() == 0 && arParamInfo[1]->get_Position() == 1); //Prepare parameters for constructor int numArgs = arParamInfo->get_Length(); System::Object * args[] = new System::Object*[numArgs]; //only initialize the first argument with the message args[0] = sMessage; cliObj = ctorInfo->Invoke(args); } else cliObj = System::Activator::CreateInstance(cliType); } sal_Int32 * pMemberOffsets = comp_td->pMemberOffsets; if (comp_td->pBaseTypeDescription) { //convert inherited struct //cliObj is passed inout (args in_param, out_param are true), hence the passed // cliObj is used by the callee instead of a newly created struct map_to_cli( &cliObj, uno_data, ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef, 0, true); } rtl::OUString usUnoException(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Exception")); for (sal_Int32 nPos = comp_td->nMembers; nPos--; ) { typelib_TypeDescriptionReference * member_type = comp_td->ppTypeRefs[ nPos ]; System::String* sMemberName= mapUnoString(comp_td->ppMemberNames[nPos]); sr::FieldInfo* aField= cliType->GetField(sMemberName); // special case for Exception.Message. The field has already been // set while constructing cli object if ( ! aField && usUnoException.equals(td.get()->pTypeName)) { continue; } void const * p = (char const *)uno_data + pMemberOffsets[ nPos ]; switch (member_type->eTypeClass) { case typelib_TypeClass_CHAR: aField->SetValue(cliObj, __box(*(System::Char*) p)); break; case typelib_TypeClass_BOOLEAN: aField->SetValue(cliObj, __box(*(System::Boolean*) p)); break; case typelib_TypeClass_BYTE: aField->SetValue(cliObj, __box(*(System::Byte*) p)); break; case typelib_TypeClass_SHORT: aField->SetValue(cliObj, __box(*(System::Int16*) p)); break; case typelib_TypeClass_UNSIGNED_SHORT: aField->SetValue(cliObj, __box(*(System::UInt16*) p)); break; case typelib_TypeClass_LONG: aField->SetValue(cliObj, __box(*(System::Int32*) p)); break; case typelib_TypeClass_UNSIGNED_LONG: aField->SetValue(cliObj, __box(*(System::UInt32*) p)); break; case typelib_TypeClass_HYPER: aField->SetValue(cliObj, __box(*(System::Int64*) p)); break; case typelib_TypeClass_UNSIGNED_HYPER: aField->SetValue(cliObj, __box(*(System::UInt64*) p)); break; case typelib_TypeClass_FLOAT: aField->SetValue(cliObj, __box(*(System::Single*) p)); break; case typelib_TypeClass_DOUBLE: aField->SetValue(cliObj, __box(*(System::Double*) p)); break; default: { System::Object* cli_val; map_to_cli( &cli_val, p, member_type, 0, false); aField->SetValue(cliObj, cli_val); break; } } } *cli_data= cliObj; break; } case typelib_TypeClass_SEQUENCE: { sal_Int32 nElements; uno_Sequence const * seq = 0; seq = *(uno_Sequence * const *)uno_data; nElements = seq->nElements; TypeDescr td( type ); typelib_TypeDescriptionReference * element_type = ((typelib_IndirectTypeDescription *)td.get())->pType; switch (element_type->eTypeClass) { case typelib_TypeClass_CHAR: { System::Char arChar[]= new System::Char[nElements]; sri::Marshal::Copy( (void*) &seq->elements, arChar, 0, nElements); *cli_data= arChar; break; } case typelib_TypeClass_BOOLEAN: { System::Boolean arBool[]= new System::Boolean[nElements]; sri::Marshal::Copy( (void*) &seq->elements, arBool, 0, nElements); *cli_data= arBool; break; } case typelib_TypeClass_BYTE: { System::Byte arByte[]= new System::Byte[nElements]; sri::Marshal::Copy( (void*) &seq->elements, arByte, 0, nElements); *cli_data= arByte; break; } case typelib_TypeClass_SHORT: { System::Int16 arShort[]= new System::Int16[nElements]; sri::Marshal::Copy( (void*) &seq->elements, arShort, 0, nElements); *cli_data= arShort; break; } case typelib_TypeClass_UNSIGNED_SHORT: { System::UInt16 arUInt16[]= new System::UInt16[nElements]; sri::Marshal::Copy( (void*) &seq->elements, static_cast(arUInt16), 0, nElements); *cli_data= arUInt16; break; } case typelib_TypeClass_LONG: { System::Int32 arInt32[]= new System::Int32[nElements]; sri::Marshal::Copy( (void*) &seq->elements, arInt32, 0, nElements); *cli_data= arInt32; break; } case typelib_TypeClass_UNSIGNED_LONG: { System::UInt32 arUInt32[]= new System::UInt32[nElements]; sri::Marshal::Copy( (void*) &seq->elements, static_cast(arUInt32), 0, nElements); *cli_data= arUInt32; break; } case typelib_TypeClass_HYPER: { System::Int64 arInt64[]= new System::Int64[nElements]; sri::Marshal::Copy( (void*) &seq->elements, arInt64, 0, nElements); *cli_data= arInt64; break; } case typelib_TypeClass_UNSIGNED_HYPER: { System::UInt64 arUInt64[]= new System::UInt64[nElements]; sri::Marshal::Copy( (void*) &seq->elements, arUInt64, 0, nElements); *cli_data= arUInt64; break; } case typelib_TypeClass_FLOAT: { System::Single arSingle[]= new System::Single[nElements]; sri::Marshal::Copy( (void*) &seq->elements, arSingle, 0, nElements); *cli_data= arSingle; break; } case typelib_TypeClass_DOUBLE: { System::Double arDouble[]= new System::Double[nElements]; sri::Marshal::Copy( (void*) &seq->elements, arDouble, 0, nElements); *cli_data= arDouble; break; } case typelib_TypeClass_STRING: { System::String* arString[]= new System::String*[nElements]; for (int i= 0; i < nElements; i++) { rtl_uString *aStr= ((rtl_uString**)(&seq->elements))[i]; arString[i]= new System::String( (__wchar_t *) &aStr->buffer, 0, aStr->length); } *cli_data= arString; break; } case typelib_TypeClass_TYPE: { System::Type* arType[]= new System::Type*[nElements]; for (int i= 0; i < nElements; i++) { arType[i]= mapUnoType( ((typelib_TypeDescriptionReference**) seq->elements)[i]); } *cli_data= arType; break; } case typelib_TypeClass_ANY: { uno::Any arCli[]= new uno::Any[nElements]; uno_Any const * p = (uno_Any const *)seq->elements; for (sal_Int32 nPos = 0; nPos < nElements; ++nPos ) { System::Object* cli_obj = NULL; map_to_cli( &cli_obj, &p[ nPos ], element_type, 0, false); arCli[nPos]= *__try_cast<__box uno::Any*>(cli_obj); } *cli_data= arCli; break; } case typelib_TypeClass_ENUM: { //get the Enum type System::Type* enumType= NULL; if (info != NULL) { //info is EnumType[]&, remove & OSL_ASSERT(info->IsByRef); enumType = info->GetElementType(); //enumType is EnumType[], remove [] enumType = enumType->GetElementType(); } else enumType= mapUnoType(element_type); System::Array* arEnum = System::Array::CreateInstance( enumType, nElements); for (int i= 0; i < nElements; i++) { arEnum->SetValue(System::Enum::ToObject(enumType, ((sal_Int32*) seq->elements)[i]), i); } *cli_data = arEnum; break; } case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION: { TypeDescr element_td( element_type ); System::Array* ar= System::Array::CreateInstance( mapUnoType(element_type),nElements); if (0 < nElements) { // ToDo check this char * p = (char *) &seq->elements; sal_Int32 nSize = element_td.get()->nSize; for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) { System::Object* val; map_to_cli( &val, p + (nSize * nPos), element_type, 0, false); ar->SetValue(val, nPos); } } *cli_data = ar; break; } // ToDo, verify case typelib_TypeClass_SEQUENCE: { System::Array *ar= System::Array::CreateInstance( mapUnoType(element_type), nElements); if (0 < nElements) { TypeDescr element_td( element_type ); uno_Sequence ** elements = (uno_Sequence**) seq->elements; for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) { System::Object* val; map_to_cli( &val, &elements[nPos], element_type, 0, false); ar->SetValue(val, nPos); } } *cli_data = ar; break; } case typelib_TypeClass_INTERFACE: { TypeDescr element_td( element_type ); System::Type * ifaceType= mapUnoType(element_type); System::Array* ar= System::Array::CreateInstance(ifaceType, nElements); char * p = (char *)seq->elements; sal_Int32 nSize = element_td.get()->nSize; for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) { System::Object* val; map_to_cli( &val, p + (nSize * nPos), element_type, NULL, false); ar->SetValue(val, nPos); } *cli_data= ar; break; } default: { OUStringBuffer buf( 128 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_cli():") ); buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported element type: ") ); buf.append( *reinterpret_cast< OUString const * >( &element_type->pTypeName ) ); throw BridgeRuntimeError( buf.makeStringAndClear() ); } } break; } case typelib_TypeClass_INTERFACE: { uno_Interface * pUnoI = *(uno_Interface * const *)uno_data; if (0 != pUnoI) { TypeDescr td( type ); *cli_data= map_uno2cli( pUnoI, reinterpret_cast< typelib_InterfaceTypeDescription*>(td.get())) ; } else *cli_data= NULL; break; } default: { //ToDo check this exception. The String is probably crippled OUStringBuffer buf( 128 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_cli():") ); buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported type!") ); throw BridgeRuntimeError( buf.makeStringAndClear() ); } } } }