1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_cli_ure.hxx" 26 27 #pragma warning(push, 1) 28 #include "windows.h" 29 #pragma warning(pop) 30 31 #include <memory> 32 33 34 #include "rtl/ustring.hxx" 35 #include "rtl/ustrbuf.hxx" 36 #include "uno/sequence2.h" 37 #include "typelib/typedescription.hxx" 38 #include "cli_proxy.h" 39 #include "cli_base.h" 40 #include "cli_bridge.h" 41 42 #using <cli_uretypes.dll> 43 44 45 #undef VOID 46 47 namespace css = com::sun::star; 48 49 namespace sri = System::Runtime::InteropServices; 50 namespace sr = System::Reflection; 51 namespace st = System::Text; 52 namespace ucss = unoidl::com::sun::star; 53 54 using namespace rtl; 55 using namespace std; 56 57 58 namespace cli_uno 59 { 60 System::String ^ mapUnoPolymorphicName(System::String ^ unoName); 61 OUString mapCliTypeName(System::String ^ typeName); 62 System::String ^ mapCliPolymorphicName(System::String ^ unoName); 63 System::String ^ mapPolymorphicName(System::String ^ unoName, bool bCliToUno); 64 65 inline auto_ptr< rtl_mem > seq_allocate( sal_Int32 nElements, sal_Int32 nSize ) 66 { 67 auto_ptr< rtl_mem > seq( 68 rtl_mem::allocate( SAL_SEQUENCE_HEADER_SIZE + (nElements * nSize) ) ); 69 uno_Sequence * p = (uno_Sequence *)seq.get(); 70 p->nRefCount = 1; 71 p->nElements = nElements; 72 return seq; 73 } 74 75 76 System::Object ^ Bridge::map_uno2cli(uno_Interface * pUnoI, typelib_InterfaceTypeDescription *pTD) const 77 { 78 System::Object ^ retVal= nullptr; 79 // get oid 80 rtl_uString * pOid = 0; 81 (*m_uno_env->getObjectIdentifier)( m_uno_env, &pOid, pUnoI ); 82 OSL_ASSERT( 0 != pOid ); 83 OUString oid(pOid, SAL_NO_ACQUIRE); 84 85 //see if the interface was already mapped 86 System::Type ^ ifaceType= mapUnoType(reinterpret_cast<typelib_TypeDescription*>(pTD)); 87 System::String ^ sOid= mapUnoString(oid.pData); 88 89 System::Threading::Monitor::Enter( CliEnvHolder::g_cli_env ); 90 try 91 { 92 retVal = CliEnvHolder::g_cli_env->getRegisteredInterface(sOid, ifaceType); 93 if (retVal) 94 { 95 // There is already an registered object. It can either be a proxy 96 // for the UNO object or a real cli object. In the first case we 97 // tell the proxy that it shall also represent the current UNO 98 // interface. If it already does that, then it does nothing 99 if (srr::RemotingServices::IsTransparentProxy(retVal)) 100 { 101 UnoInterfaceProxy ^ p = static_cast<UnoInterfaceProxy ^>( 102 srr::RemotingServices::GetRealProxy(retVal)); 103 p->addUnoInterface(pUnoI, pTD); 104 } 105 } 106 else 107 { 108 retVal = UnoInterfaceProxy::create( 109 (Bridge *) this, pUnoI, pTD, oid ); 110 } 111 } 112 __finally 113 { 114 System::Threading::Monitor::Exit( CliEnvHolder::g_cli_env ); 115 } 116 117 return retVal; 118 } 119 120 uno_Interface* Bridge::map_cli2uno(System::Object ^ cliObj, typelib_TypeDescription *pTD) const 121 { 122 uno_Interface* retIface = NULL; 123 // get oid from dot net environment 124 System::String ^ ds_oid = CliEnvHolder::g_cli_env->getObjectIdentifier( cliObj); 125 OUString ousOid = mapCliString(ds_oid); 126 // look if interface is already mapped 127 m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData, 128 (typelib_InterfaceTypeDescription*) pTD); 129 if ( ! retIface) 130 { 131 System::Threading::Monitor::Enter(Cli_environment::typeid); 132 try 133 { 134 m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData, 135 (typelib_InterfaceTypeDescription*) pTD); 136 if ( ! retIface) 137 { 138 retIface = CliProxy::create((Bridge*)this, cliObj, pTD, ousOid); 139 } 140 } 141 __finally 142 { 143 System::Threading::Monitor::Exit(Cli_environment::typeid); 144 } 145 } 146 return retIface; 147 } 148 149 inline System::Type ^ loadCliType(rtl_uString * unoName) 150 { 151 return loadCliType(mapUnoTypeName(unoName)); 152 } 153 154 System::Type ^ loadCliType(System::String ^ unoName) 155 { 156 System::Type ^ retVal= nullptr; 157 try 158 { 159 //If unoName denotes a polymorphic type, e.g com.sun.star.beans.Defaulted<System.Char> 160 //then we remove the type list, otherwise the type could not be loaded. 161 bool bIsPolymorphic = false; 162 163 System::String ^ loadName = unoName; 164 int index = unoName->IndexOf('<'); 165 if (index != -1) 166 { 167 loadName = unoName->Substring(0, index); 168 bIsPolymorphic = true; 169 } 170 System::AppDomain ^ currentDomain = System::AppDomain::CurrentDomain; 171 cli::array< sr::Assembly ^ > ^ assems = currentDomain->GetAssemblies(); 172 for (int i = 0; i < assems->Length; i++) 173 { 174 retVal = assems[i]->GetType(loadName, false); 175 if (retVal) 176 break; 177 } 178 179 if (retVal == nullptr) 180 { 181 System::String ^ msg = gcnew System::String("A type could not be loaded: "); 182 msg = System::String::Concat(msg, loadName); 183 throw BridgeRuntimeError(mapCliString(msg)); 184 } 185 186 if (bIsPolymorphic) 187 { 188 retVal = uno::PolymorphicType::GetType(retVal, unoName); 189 } 190 } 191 catch( System::Exception ^ e) 192 { 193 rtl::OUString ouMessage(mapCliString(e->Message)); 194 throw BridgeRuntimeError(ouMessage); 195 } 196 return retVal; 197 } 198 199 200 System::Type ^ mapUnoType(typelib_TypeDescription const * pTD) 201 { 202 return mapUnoType(pTD->pWeakRef); 203 } 204 205 System::Type ^ mapUnoType(typelib_TypeDescriptionReference const * pTD) 206 { 207 System::Type ^ retVal = nullptr; 208 switch (pTD->eTypeClass) 209 { 210 case typelib_TypeClass_VOID: 211 retVal= void::typeid; break; 212 case typelib_TypeClass_CHAR: 213 retVal= System::Char::typeid; break; 214 case typelib_TypeClass_BOOLEAN: 215 retVal= System::Boolean::typeid; break; 216 case typelib_TypeClass_BYTE: 217 retVal= System::Byte::typeid; break; 218 case typelib_TypeClass_SHORT: 219 retVal= System::Int16::typeid; break; 220 case typelib_TypeClass_UNSIGNED_SHORT: 221 retVal= System::UInt16::typeid; break; 222 case typelib_TypeClass_LONG: 223 retVal= System::Int32::typeid; break; 224 case typelib_TypeClass_UNSIGNED_LONG: 225 retVal= System::UInt32::typeid; break; 226 case typelib_TypeClass_HYPER: 227 retVal= System::Int64::typeid; break; 228 case typelib_TypeClass_UNSIGNED_HYPER: 229 retVal= System::UInt64::typeid; break; 230 case typelib_TypeClass_FLOAT: 231 retVal= System::Single::typeid; break; 232 case typelib_TypeClass_DOUBLE: 233 retVal= System::Double::typeid; break; 234 case typelib_TypeClass_STRING: 235 retVal= System::String::typeid; break; 236 case typelib_TypeClass_TYPE: 237 retVal= System::Type::typeid; break; 238 case typelib_TypeClass_ANY: 239 retVal= uno::Any::typeid; break; 240 case typelib_TypeClass_ENUM: 241 case typelib_TypeClass_STRUCT: 242 case typelib_TypeClass_EXCEPTION: 243 retVal= loadCliType(pTD->pTypeName); break; 244 case typelib_TypeClass_INTERFACE: 245 { 246 //special handling for XInterface, since it does not exist in cli. 247 rtl::OUString usXInterface(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XInterface")); 248 if (usXInterface.equals(pTD->pTypeName)) 249 retVal= System::Object::typeid; 250 else 251 retVal= loadCliType(pTD->pTypeName); 252 break; 253 } 254 case typelib_TypeClass_SEQUENCE: 255 { 256 css::uno::TypeDescription seqType( 257 const_cast<typelib_TypeDescriptionReference*>(pTD)); 258 typelib_TypeDescriptionReference* pElementTDRef= 259 reinterpret_cast<typelib_IndirectTypeDescription*>(seqType.get())->pType; 260 switch (pElementTDRef->eTypeClass) 261 { 262 case typelib_TypeClass_CHAR: 263 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArChar)); break; 264 case typelib_TypeClass_BOOLEAN: 265 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArBoolean)); 266 break; 267 case typelib_TypeClass_BYTE: 268 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArByte)); 269 break; 270 case typelib_TypeClass_SHORT: 271 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArInt16)); 272 break; 273 case typelib_TypeClass_UNSIGNED_SHORT: 274 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArUInt16)); 275 break; 276 case typelib_TypeClass_LONG: 277 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArInt32)); 278 break; 279 case typelib_TypeClass_UNSIGNED_LONG: 280 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArUInt32)); 281 break; 282 case typelib_TypeClass_HYPER: 283 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArInt64)); 284 break; 285 case typelib_TypeClass_UNSIGNED_HYPER: 286 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArUInt64)); 287 break; 288 case typelib_TypeClass_FLOAT: 289 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArSingle)); 290 break; 291 case typelib_TypeClass_DOUBLE: 292 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArDouble)); 293 break; 294 case typelib_TypeClass_STRING: 295 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArString)); 296 break; 297 case typelib_TypeClass_TYPE: 298 retVal= System::Type::GetType(const_cast<System::String ^>(Constants::sArType)); 299 break; 300 case typelib_TypeClass_ANY: 301 case typelib_TypeClass_ENUM: 302 case typelib_TypeClass_EXCEPTION: 303 case typelib_TypeClass_STRUCT: 304 case typelib_TypeClass_INTERFACE: 305 case typelib_TypeClass_SEQUENCE: 306 { 307 retVal= loadCliType(pTD->pTypeName); 308 break; 309 } 310 default: 311 //All cases should be handled by the case statements above 312 OSL_ASSERT(0); 313 break; 314 } 315 break; 316 } 317 default: 318 OSL_ASSERT(false); 319 break; 320 } 321 return retVal; 322 } 323 324 /** Returns an acquired td. 325 */ 326 typelib_TypeDescriptionReference* mapCliType(System::Type ^ cliType) 327 { 328 typelib_TypeDescriptionReference* retVal= NULL; 329 // Kept for the error message: "could not map type: X" alone does not say 330 // which UNO name was looked up, and for a polymorphic struct that name is 331 // the whole question. 332 OUString usTypeName; 333 if (cliType == nullptr) 334 { 335 retVal = * typelib_static_type_getByTypeClass( 336 typelib_TypeClass_VOID ); 337 typelib_typedescriptionreference_acquire( retVal ); 338 return retVal; 339 } 340 //check for Enum first, 341 //because otherwise case System::TypeCode::Int32 applies 342 if (cliType->IsEnum) 343 { 344 OUString usTypeName= mapCliTypeName(cliType->FullName); 345 css::uno::Type unoType(css::uno::TypeClass_ENUM, usTypeName); 346 retVal= unoType.getTypeLibType(); 347 typelib_typedescriptionreference_acquire(retVal); 348 } 349 else 350 { 351 switch (System::Type::GetTypeCode(cliType)) 352 { 353 case System::TypeCode::Boolean: 354 retVal = * typelib_static_type_getByTypeClass( 355 typelib_TypeClass_BOOLEAN ); 356 typelib_typedescriptionreference_acquire( retVal ); 357 break; 358 case System::TypeCode::Char: 359 retVal = * typelib_static_type_getByTypeClass( 360 typelib_TypeClass_CHAR ); 361 typelib_typedescriptionreference_acquire( retVal ); 362 break; 363 case System::TypeCode::Byte: 364 retVal = * typelib_static_type_getByTypeClass( 365 typelib_TypeClass_BYTE ); 366 typelib_typedescriptionreference_acquire( retVal ); 367 break; 368 case System::TypeCode::Int16: 369 retVal = * typelib_static_type_getByTypeClass( 370 typelib_TypeClass_SHORT ); 371 typelib_typedescriptionreference_acquire( retVal ); 372 break; 373 case System::TypeCode::Int32: 374 retVal = * typelib_static_type_getByTypeClass( 375 typelib_TypeClass_LONG ); 376 typelib_typedescriptionreference_acquire( retVal ); 377 break; 378 case System::TypeCode::Int64: 379 retVal = * typelib_static_type_getByTypeClass( 380 typelib_TypeClass_HYPER ); 381 typelib_typedescriptionreference_acquire( retVal ); 382 break; 383 case System::TypeCode::UInt16: 384 retVal = * typelib_static_type_getByTypeClass( 385 typelib_TypeClass_UNSIGNED_SHORT ); 386 typelib_typedescriptionreference_acquire( retVal ); 387 break; 388 case System::TypeCode::UInt32: 389 retVal = * typelib_static_type_getByTypeClass( 390 typelib_TypeClass_UNSIGNED_LONG ); 391 typelib_typedescriptionreference_acquire( retVal ); 392 break; 393 case System::TypeCode::UInt64: 394 retVal = * typelib_static_type_getByTypeClass( 395 typelib_TypeClass_UNSIGNED_HYPER ); 396 typelib_typedescriptionreference_acquire( retVal ); 397 break; 398 case System::TypeCode::Single: 399 retVal = * typelib_static_type_getByTypeClass( 400 typelib_TypeClass_FLOAT ); 401 typelib_typedescriptionreference_acquire( retVal ); 402 break; 403 case System::TypeCode::Double: 404 retVal = * typelib_static_type_getByTypeClass( 405 typelib_TypeClass_DOUBLE ); 406 typelib_typedescriptionreference_acquire( retVal ); 407 break; 408 case System::TypeCode::String: 409 retVal = * typelib_static_type_getByTypeClass( 410 typelib_TypeClass_STRING ); 411 typelib_typedescriptionreference_acquire( retVal ); 412 break; 413 default: 414 break; 415 } 416 } 417 if (retVal == nullptr) 418 { 419 System::String ^ cliTypeName= cliType->FullName; 420 // Void 421 if (const_cast<System::String ^>(Constants::sVoid)->Equals( 422 cliTypeName)) 423 { 424 retVal = * typelib_static_type_getByTypeClass( 425 typelib_TypeClass_VOID ); 426 typelib_typedescriptionreference_acquire( retVal ); 427 } 428 // Type 429 else if (const_cast<System::String ^>(Constants::sType)->Equals( 430 cliTypeName)) 431 { 432 retVal = * typelib_static_type_getByTypeClass( 433 typelib_TypeClass_TYPE ); 434 typelib_typedescriptionreference_acquire( retVal ); 435 } 436 // Any 437 else if (const_cast<System::String ^>(Constants::sAny)->Equals( 438 cliTypeName)) 439 { 440 retVal = * typelib_static_type_getByTypeClass( 441 typelib_TypeClass_ANY ); 442 typelib_typedescriptionreference_acquire( retVal ); 443 } 444 //struct, interfaces, sequences 445 else 446 { 447 uno::PolymorphicType ^ poly = dynamic_cast<uno::PolymorphicType ^>(cliType); 448 if (poly != nullptr) 449 usTypeName = mapCliTypeName( poly->PolymorphicName); 450 else 451 usTypeName = mapCliTypeName(cliTypeName); 452 typelib_TypeDescription* td = NULL; 453 typelib_typedescription_getByName(&td, usTypeName.pData); 454 if (td) 455 { 456 retVal = td->pWeakRef; 457 typelib_typedescriptionreference_acquire(retVal); 458 typelib_typedescription_release(td); 459 } 460 } 461 } 462 if (retVal == nullptr) 463 { 464 OUStringBuffer buf( 128 ); 465 buf.appendAscii( 466 RTL_CONSTASCII_STRINGPARAM("[cli_uno bridge] mapCliType():" 467 "could not map type: ") ); 468 buf.append(mapCliString(cliType->FullName)); 469 if (usTypeName.getLength()) 470 { 471 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (looked up UNO name: ") ); 472 buf.append(usTypeName); 473 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(")") ); 474 } 475 throw BridgeRuntimeError( buf.makeStringAndClear() ); 476 } 477 return retVal; 478 } 479 480 /** 481 Otherwise a leading "unoidl." is removed. 482 */ 483 System::String ^ mapUnoTypeName(rtl_uString const * typeName) 484 { 485 OUString usUnoName( const_cast< rtl_uString * >( typeName ) ); 486 st::StringBuilder ^ buf= gcnew st::StringBuilder(); 487 //determine if the type is a sequence and its dimensions 488 int dims= 0; 489 if (usUnoName[0] == '[') 490 { 491 sal_Int32 index= 1; 492 while (true) 493 { 494 if (usUnoName[index++] == ']') 495 dims++; 496 if (usUnoName[index++] != '[') 497 break; 498 } 499 usUnoName = usUnoName.copy(index - 1); 500 } 501 System::String ^ sUnoName = mapUnoString(usUnoName.pData); 502 if (sUnoName->Equals(const_cast<System::String ^>(Constants::usBool))) 503 buf->Append(const_cast<System::String ^>(Constants::sBoolean)); 504 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usChar))) 505 buf->Append(const_cast<System::String ^>(Constants::sChar)); 506 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usByte))) 507 buf->Append(const_cast<System::String ^>(Constants::sByte)); 508 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usShort))) 509 buf->Append(const_cast<System::String ^>(Constants::sInt16)); 510 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usUShort))) 511 buf->Append(const_cast<System::String ^>(Constants::sUInt16)); 512 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usLong))) 513 buf->Append(const_cast<System::String ^>(Constants::sInt32)); 514 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usULong))) 515 buf->Append(const_cast<System::String ^>(Constants::sUInt32)); 516 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usHyper))) 517 buf->Append(const_cast<System::String ^>(Constants::sInt64)); 518 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usUHyper))) 519 buf->Append(const_cast<System::String ^>(Constants::sUInt64)); 520 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usFloat))) 521 buf->Append(const_cast<System::String ^>(Constants::sSingle)); 522 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usDouble))) 523 buf->Append(const_cast<System::String ^>(Constants::sDouble)); 524 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usString))) 525 buf->Append(const_cast<System::String ^>(Constants::sString)); 526 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usVoid))) 527 buf->Append(const_cast<System::String ^>(Constants::sVoid)); 528 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usType))) 529 buf->Append(const_cast<System::String ^>(Constants::sType)); 530 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usXInterface))) 531 buf->Append(const_cast<System::String ^>(Constants::sObject)); 532 else if (sUnoName->Equals(const_cast<System::String ^>(Constants::usAny))) 533 { 534 buf->Append(const_cast<System::String ^>(Constants::sAny)); 535 } 536 else 537 { 538 //put "unoidl." at the beginning 539 buf->Append(const_cast<System::String ^>(Constants::sUnoidl)); 540 //for polymorphic struct types remove the brackets, e.g mystruct<bool> -> mystruct 541 System::String ^ sName = mapUnoPolymorphicName(sUnoName); 542 buf->Append(sName); 543 } 544 // apend [] 545 for (;dims--;) 546 buf->Append(const_cast<System::String ^>(Constants::sBrackets)); 547 548 return buf->ToString(); 549 } 550 551 552 553 554 /** For example, there is a uno type 555 com.sun.star.Foo<char, long>. 556 The values in the type list 557 are uno types and are replaced by cli types, such as System.Char, 558 System.Int32, etc. 559 The pr�fix unoidl is not added. 560 */ 561 inline System::String ^ mapUnoPolymorphicName(System::String ^ unoName) 562 { 563 return mapPolymorphicName(unoName, false); 564 } 565 /** For example, there is a type name such as 566 com.sun.star.Foo<System.Char, System.Int32>. 567 The values in the type list 568 are CLI types and are replaced by uno types, such as char, 569 long, etc. 570 The pr�fix unoidl remains. 571 */ 572 inline System::String ^ mapCliPolymorphicName(System::String ^ unoName) 573 { 574 return mapPolymorphicName(unoName, true); 575 } 576 577 System::String ^ mapPolymorphicName(System::String ^ unoName, bool bCliToUno) 578 { 579 int index = unoName->IndexOf('<'); 580 if (index == -1) 581 return unoName; 582 583 System::Text::StringBuilder ^ builder = gcnew System::Text::StringBuilder(256); 584 builder->Append(unoName->Substring(0, index +1 )); 585 586 //Find the first occurrence of ',' 587 //If the parameter is a polymorphic struct then we neede to ignore everything 588 //between the brackets because it can also contain commas 589 //get the type list within < and > 590 int endIndex = unoName->Length - 1; 591 index++; 592 int cur = index; 593 int countParams = 0; 594 while (cur <= endIndex) 595 { 596 System::Char c = unoName[cur]; 597 if (c == ',' || c == '>') 598 { 599 //insert a comma if needed 600 if (countParams != 0) 601 builder->Append(","); 602 countParams++; 603 System::String ^ sParam = unoName->Substring(index, cur - index); 604 //skip the comma 605 cur++; 606 //the index to the beginning of the next param 607 index = cur; 608 if (bCliToUno) 609 { 610 // NOT Append(OUString::getStr()). getStr() hands back a 611 // sal_Unicode const*, and the only Append overload a 612 // "unsigned short const*" converts to is Append(bool) -- via 613 // the ordinary pointer-to-bool conversion. The type 614 // parameter then comes out as the text "True" and the 615 // resulting UNO name matches nothing: 616 // []test.testtools.bridgetest.TestPolyStruct<True> 617 builder->Append( mapUnoString( mapCliTypeName(sParam).pData ) ); 618 } 619 else 620 { 621 OUString s = mapCliString(sParam); 622 builder->Append(mapUnoTypeName(s.pData)); 623 } 624 } 625 else if (c == '<') 626 { 627 cur++; 628 //continue until the matching '>' 629 int numNested = 0; 630 for (;;cur++) 631 { 632 System::Char curChar = unoName[cur]; 633 if (curChar == '<') 634 { 635 numNested ++; 636 } 637 else if (curChar == '>') 638 { 639 if (numNested > 0) 640 numNested--; 641 else 642 break; 643 } 644 } 645 } 646 cur++; 647 } 648 649 builder->Append((System::Char) '>'); 650 return builder->ToString(); 651 } 652 653 OUString mapCliTypeName(System::String ^ typeName) 654 { 655 int dims= 0; 656 // Array? determine the "rank" (number of "[]") 657 // move from the rightmost end to the left, for example 658 // unoidl.PolymorphicStruct<System.Char[]>[] 659 // has only a "dimension" of 1 660 int cur = typeName->Length - 1; 661 bool bRightBracket = false; 662 while (cur >= 0) 663 { 664 System::Char c = typeName[cur]; 665 if (c == ']') 666 { 667 bRightBracket = true; 668 } 669 else if (c == '[') 670 { 671 if (!bRightBracket) 672 throw BridgeRuntimeError( 673 OUSTR("Typename is wrong. No matching brackets for sequence. Name is: ") + 674 mapCliString(typeName)); 675 bRightBracket = false; 676 dims ++; 677 } 678 else 679 { 680 if (bRightBracket) 681 throw BridgeRuntimeError( 682 OUSTR("Typename is wrong. No matching brackets for sequence. Name is: ") + 683 mapCliString(typeName)); 684 break; 685 } 686 cur--; 687 } 688 689 if (bRightBracket || cur < 0) 690 throw BridgeRuntimeError( 691 OUSTR("Typename is wrong. ") + 692 mapCliString(typeName)); 693 694 typeName = typeName->Substring(0, cur + 1); 695 696 System::Text::StringBuilder ^ buf = gcnew System::Text::StringBuilder(512); 697 698 //Put the "[]" at the beginning of the uno type name 699 for (;dims--;) 700 buf->Append(const_cast<System::String ^>(Constants::usBrackets)); 701 702 if (typeName->Equals(const_cast<System::String ^>(Constants::sBoolean))) 703 buf->Append(const_cast<System::String ^>(Constants::usBool)); 704 else if (typeName->Equals(const_cast<System::String ^>(Constants::sChar))) 705 buf->Append(const_cast<System::String ^>(Constants::usChar)); 706 else if (typeName->Equals(const_cast<System::String ^>(Constants::sByte))) 707 buf->Append(const_cast<System::String ^>(Constants::usByte)); 708 else if (typeName->Equals(const_cast<System::String ^>(Constants::sInt16))) 709 buf->Append(const_cast<System::String ^>(Constants::usShort)); 710 else if (typeName->Equals(const_cast<System::String ^>(Constants::sUInt16))) 711 buf->Append(const_cast<System::String ^>(Constants::usUShort)); 712 else if (typeName->Equals(const_cast<System::String ^>(Constants::sInt32))) 713 buf->Append(const_cast<System::String ^>(Constants::usLong)); 714 else if (typeName->Equals(const_cast<System::String ^>(Constants::sUInt32))) 715 buf->Append(const_cast<System::String ^>(Constants::usULong)); 716 else if (typeName->Equals(const_cast<System::String ^>(Constants::sInt64))) 717 buf->Append(const_cast<System::String ^>(Constants::usHyper)); 718 else if (typeName->Equals(const_cast<System::String ^>(Constants::sUInt64))) 719 buf->Append(const_cast<System::String ^>(Constants::usUHyper)); 720 else if (typeName->Equals(const_cast<System::String ^>(Constants::sSingle))) 721 buf->Append(const_cast<System::String ^>(Constants::usFloat)); 722 else if (typeName->Equals(const_cast<System::String ^>(Constants::sDouble))) 723 buf->Append(const_cast<System::String ^>(Constants::usDouble)); 724 else if (typeName->Equals(const_cast<System::String ^>(Constants::sString))) 725 buf->Append(const_cast<System::String ^>(Constants::usString)); 726 else if (typeName->Equals(const_cast<System::String ^>(Constants::sVoid))) 727 buf->Append(const_cast<System::String ^>(Constants::usVoid)); 728 else if (typeName->Equals(const_cast<System::String ^>(Constants::sType))) 729 buf->Append(const_cast<System::String ^>(Constants::usType)); 730 else if (typeName->Equals(const_cast<System::String ^>(Constants::sObject))) 731 buf->Append(const_cast<System::String ^>(Constants::usXInterface)); 732 else if (typeName->Equals(const_cast<System::String ^>(Constants::sAny))) 733 buf->Append(const_cast<System::String ^>(Constants::usAny)); 734 else 735 { 736 System::String ^ sName = mapCliPolymorphicName(typeName); 737 int i= sName->IndexOf(L'.'); 738 buf->Append(sName->Substring(i + 1)); 739 } 740 return mapCliString(buf->ToString()); 741 } 742 /** Maps uno types to dot net types. 743 * If uno_data is null then the type description is converted to System::Type 744 */ 745 inline System::String ^ mapUnoString( rtl_uString const * data) 746 { 747 OSL_ASSERT(data); 748 return gcnew System::String((__wchar_t*) data->buffer, 0, data->length); 749 } 750 751 OUString mapCliString(System::String ^ data) 752 { 753 754 if (data != nullptr) 755 { 756 OSL_ASSERT(sizeof(wchar_t) == sizeof(sal_Unicode)); 757 pin_ptr< wchar_t const > pdata= PtrToStringChars(data); 758 return OUString(pdata, const_cast<System::String ^>(data)->Length); 759 } 760 else 761 { 762 return OUString(); 763 } 764 } 765 766 // ToDo convert cli types to expected types, e.g a long to a short where the uno type 767 // is a sal_Int16. This could be necessary if a scripting language (typeless) is used 768 // @param assign the uno_data has to be destructed (in/out args) 769 void Bridge::map_to_uno(void * uno_data, System::Object ^ cli_data, 770 typelib_TypeDescriptionReference * type, 771 bool assign) const 772 { 773 try{ 774 switch (type->eTypeClass) 775 { 776 case typelib_TypeClass_VOID: 777 break; 778 case typelib_TypeClass_CHAR: 779 { 780 System::Char aChar= safe_cast< System::Char >(cli_data); 781 *(sal_Unicode*) uno_data= aChar; 782 break; 783 } 784 case typelib_TypeClass_BOOLEAN: 785 { 786 System::Boolean aBool= safe_cast< System::Boolean >(cli_data); 787 *(sal_Bool*)uno_data= aBool == true ? sal_True : sal_False; 788 break; 789 } 790 case typelib_TypeClass_BYTE: 791 { 792 System::Byte aByte= safe_cast< System::Byte >(cli_data); 793 *(sal_Int8*) uno_data= aByte; 794 break; 795 } 796 case typelib_TypeClass_SHORT: 797 { 798 System::Int16 aShort= safe_cast< System::Int16 >(cli_data); 799 *(sal_Int16*) uno_data= aShort; 800 break; 801 } 802 case typelib_TypeClass_UNSIGNED_SHORT: 803 { 804 System::UInt16 aUShort= safe_cast< System::UInt16 >(cli_data); 805 *(sal_uInt16*) uno_data= aUShort; 806 break; 807 } 808 case typelib_TypeClass_LONG: 809 { 810 System::Int32 aLong= safe_cast< System::Int32 >(cli_data); 811 *(sal_Int32*) uno_data= aLong; 812 break; 813 } 814 case typelib_TypeClass_UNSIGNED_LONG: 815 { 816 System::UInt32 aULong= safe_cast< System::UInt32 >(cli_data); 817 *(sal_uInt32*) uno_data= aULong; 818 break; 819 } 820 case typelib_TypeClass_HYPER: 821 { 822 System::Int64 aHyper= safe_cast< System::Int64 >(cli_data); 823 *(sal_Int64*) uno_data= aHyper; 824 break; 825 } 826 case typelib_TypeClass_UNSIGNED_HYPER: 827 { 828 System::UInt64 aLong= safe_cast< System::UInt64 >(cli_data); 829 *(sal_uInt64*) uno_data= aLong; 830 break; 831 } 832 case typelib_TypeClass_FLOAT: 833 { 834 System::Single aFloat= safe_cast< System::Single >(cli_data); 835 *(float*) uno_data= aFloat; 836 break; 837 } 838 case typelib_TypeClass_DOUBLE: 839 { 840 System::Double aDouble= safe_cast< System::Double >(cli_data); 841 *(double*) uno_data= aDouble; 842 break; 843 } 844 case typelib_TypeClass_STRING: 845 { 846 if (assign && *(rtl_uString**) uno_data) 847 rtl_uString_release(*(rtl_uString**) uno_data); 848 849 *(rtl_uString **)uno_data = 0; 850 if (cli_data == nullptr) 851 { 852 rtl_uString_new((rtl_uString**) uno_data); 853 } 854 else 855 { 856 System::String ^s= safe_cast< System::String ^ >(cli_data); 857 pin_ptr< wchar_t const > pdata= PtrToStringChars(s); 858 rtl_uString_newFromStr_WithLength( (rtl_uString**) uno_data, 859 pdata, s->Length ); 860 } 861 break; 862 } 863 case typelib_TypeClass_TYPE: 864 { 865 typelib_TypeDescriptionReference* td= mapCliType(safe_cast< System::Type ^ >( 866 cli_data)); 867 if (assign) 868 { 869 typelib_typedescriptionreference_release( 870 *(typelib_TypeDescriptionReference **)uno_data ); 871 } 872 *(typelib_TypeDescriptionReference **)uno_data = td; 873 break; 874 } 875 case typelib_TypeClass_ANY: 876 { 877 uno_Any * pAny = (uno_Any *)uno_data; 878 if (cli_data == nullptr) // null-ref or uninitialized any maps to empty any 879 { 880 if (assign) 881 uno_any_destruct( pAny, 0 ); 882 uno_any_construct( pAny, 0, 0, 0 ); 883 break; 884 } 885 uno::Any aAny= safe_cast< uno::Any >(cli_data); 886 css::uno::Type value_td( mapCliType(aAny.Type), SAL_NO_ACQUIRE); 887 888 if (assign) 889 uno_any_destruct( pAny, 0 ); 890 891 try 892 { 893 switch (value_td.getTypeClass()) 894 { 895 case typelib_TypeClass_VOID: 896 pAny->pData = &pAny->pReserved; 897 break; 898 case typelib_TypeClass_CHAR: 899 pAny->pData = &pAny->pReserved; 900 *(sal_Unicode*) &pAny->pReserved = safe_cast< System::Char >(aAny.Value); 901 break; 902 case typelib_TypeClass_BOOLEAN: 903 pAny->pData = &pAny->pReserved; 904 *(sal_Bool *) &pAny->pReserved = safe_cast< System::Boolean >(aAny.Value); 905 break; 906 case typelib_TypeClass_BYTE: 907 pAny->pData = &pAny->pReserved; 908 *(sal_Int8*) &pAny->pReserved = safe_cast< System::Byte >(aAny.Value); 909 break; 910 case typelib_TypeClass_SHORT: 911 pAny->pData = &pAny->pReserved; 912 *(sal_Int16*) &pAny->pReserved = safe_cast< System::Int16 >(aAny.Value); 913 break; 914 case typelib_TypeClass_UNSIGNED_SHORT: 915 pAny->pData = &pAny->pReserved; 916 *(sal_uInt16*) &pAny->pReserved = safe_cast< System::UInt16 >(aAny.Value); 917 break; 918 case typelib_TypeClass_LONG: 919 pAny->pData = &pAny->pReserved; 920 *(sal_Int32*) &pAny->pReserved = safe_cast< System::Int32 >(aAny.Value); 921 break; 922 case typelib_TypeClass_UNSIGNED_LONG: 923 pAny->pData = &pAny->pReserved; 924 *(sal_uInt32*) &pAny->pReserved = safe_cast< System::UInt32 >(aAny.Value); 925 break; 926 case typelib_TypeClass_HYPER: 927 if (sizeof (sal_Int64) <= sizeof (void *)) 928 { 929 pAny->pData = &pAny->pReserved; 930 *(sal_Int64*) &pAny->pReserved = safe_cast< System::Int64 >(aAny.Value); 931 } 932 else 933 { 934 auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_Int64) ) ); 935 *(sal_Int64 *) mem.get()= safe_cast< System::Int64 >(aAny.Value); 936 pAny->pData = mem.release(); 937 } 938 break; 939 case typelib_TypeClass_UNSIGNED_HYPER: 940 if (sizeof (sal_uInt64) <= sizeof (void *)) 941 { 942 pAny->pData = &pAny->pReserved; 943 *(sal_uInt64*) &pAny->pReserved = safe_cast< System::UInt64 >(aAny.Value); 944 } 945 else 946 { 947 auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_uInt64) ) ); 948 *(sal_uInt64 *) mem.get()= safe_cast< System::UInt64 >(aAny.Value); 949 pAny->pData = mem.release(); 950 } 951 break; 952 case typelib_TypeClass_FLOAT: 953 if (sizeof (float) <= sizeof (void *)) 954 { 955 pAny->pData = &pAny->pReserved; 956 *(float*) &pAny->pReserved = safe_cast< System::Single >(aAny.Value); 957 } 958 else 959 { 960 auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (float) ) ); 961 *(float*) mem.get() = safe_cast< System::Single >(aAny.Value); 962 pAny->pData = mem.release(); 963 } 964 break; 965 case typelib_TypeClass_DOUBLE: 966 if (sizeof (double) <= sizeof (void *)) 967 { 968 pAny->pData = &pAny->pReserved; 969 *(double*) &pAny->pReserved= safe_cast< System::Double >(aAny.Value); 970 } 971 else 972 { 973 auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (double) ) ); 974 *(double*) mem.get()= safe_cast< System::Double >(aAny.Value); 975 pAny->pData= mem.release(); 976 } 977 break; 978 case typelib_TypeClass_STRING: // anies often contain strings; copy string directly 979 { 980 pAny->pData= &pAny->pReserved; 981 OUString _s = mapCliString(static_cast<System::String ^>(aAny.Value)); 982 pAny->pReserved= _s.pData; 983 rtl_uString_acquire(_s.pData); 984 break; 985 } 986 case typelib_TypeClass_TYPE: 987 case typelib_TypeClass_ENUM: //ToDo copy enum direct 988 case typelib_TypeClass_SEQUENCE: 989 case typelib_TypeClass_INTERFACE: 990 pAny->pData = &pAny->pReserved; 991 pAny->pReserved = 0; 992 map_to_uno( 993 &pAny->pReserved, aAny.Value, value_td.getTypeLibType(), 994 false /* no assign */); 995 break; 996 case typelib_TypeClass_STRUCT: 997 case typelib_TypeClass_EXCEPTION: 998 { 999 css::uno::Type anyType(value_td); 1000 typelib_TypeDescription* td= NULL; 1001 anyType.getDescription(&td); 1002 auto_ptr< rtl_mem > mem(rtl_mem::allocate(td->nSize)); 1003 typelib_typedescription_release(td); 1004 map_to_uno( 1005 mem.get(), aAny.Value, value_td.getTypeLibType(), 1006 false /* no assign */); 1007 pAny->pData = mem.release(); 1008 break; 1009 } 1010 default: 1011 { 1012 OUStringBuffer buf( 128 ); 1013 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); 1014 buf.append(value_td.getTypeName()); 1015 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported value type of any!") ); 1016 throw BridgeRuntimeError( buf.makeStringAndClear() ); 1017 } 1018 } 1019 } 1020 catch(System::InvalidCastException ^ ) 1021 { 1022 // ToDo check this 1023 if (assign) 1024 uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any 1025 OUStringBuffer buf( 256 ); 1026 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():Any") ); 1027 buf.append(value_td.getTypeName()); 1028 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("]The Any type ")); 1029 buf.append(value_td.getTypeName()); 1030 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" does not correspont " 1031 "to its value type: ") ); 1032 if(aAny.Value != NULL) 1033 { 1034 css::uno::Type td(mapCliType(aAny.Value->GetType()), SAL_NO_ACQUIRE); 1035 buf.append(td.getTypeName()); 1036 } 1037 if (assign) 1038 uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any 1039 throw BridgeRuntimeError( buf.makeStringAndClear() ); 1040 } 1041 catch (BridgeRuntimeError& ) 1042 { 1043 if (assign) 1044 uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any 1045 throw; 1046 } 1047 catch (...) 1048 { 1049 if (assign) 1050 uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any 1051 throw; 1052 } 1053 1054 pAny->pType = value_td.getTypeLibType(); 1055 typelib_typedescriptionreference_acquire(pAny->pType); 1056 break; 1057 } 1058 case typelib_TypeClass_ENUM: 1059 { 1060 // InvalidCastException is caught at the end of this method 1061 System::Int32 aEnum= System::Convert::ToInt32((cli_data)); 1062 *(sal_Int32*) uno_data = aEnum; 1063 break; 1064 } 1065 case typelib_TypeClass_STRUCT: 1066 case typelib_TypeClass_EXCEPTION: 1067 { 1068 css::uno::TypeDescription td(type); 1069 typelib_CompoundTypeDescription * comp_td = 1070 (typelib_CompoundTypeDescription*) td.get(); 1071 1072 typelib_StructTypeDescription * struct_td = NULL; 1073 if (type->eTypeClass == typelib_TypeClass_STRUCT) 1074 struct_td = (typelib_StructTypeDescription*) td.get(); 1075 1076 if ( ! ((typelib_TypeDescription*) comp_td)->bComplete) 1077 ::typelib_typedescription_complete( 1078 (typelib_TypeDescription**) & comp_td ); 1079 1080 sal_Int32 nMembers = comp_td->nMembers; 1081 boolean bException= false; 1082 System::Type ^ cliType = nullptr; 1083 if (cli_data) 1084 cliType = cli_data->GetType(); 1085 1086 if (0 != comp_td->pBaseTypeDescription) 1087 { 1088 map_to_uno( 1089 uno_data, cli_data, 1090 ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef, 1091 assign); 1092 } 1093 sal_Int32 nPos = 0; 1094 try 1095 { 1096 typelib_TypeDescriptionReference * member_type= NULL; 1097 1098 rtl::OUString usUnoException(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Exception")); 1099 for (; nPos < nMembers; ++nPos) 1100 { 1101 member_type= comp_td->ppTypeRefs[nPos]; 1102 #if OSL_DEBUG_LEVEL >= 2 1103 System::String ^ __s; 1104 cli::array< sr::FieldInfo ^ > ^ arFields; 1105 __s = mapUnoString(comp_td->ppMemberNames[nPos]); 1106 arFields = cliType != nullptr ? cliType->GetFields() : NULL; 1107 #endif 1108 System::Object ^ val= nullptr; 1109 if (cli_data != nullptr) 1110 { 1111 sr::FieldInfo ^ aField= cliType->GetField( 1112 mapUnoString(comp_td->ppMemberNames[nPos])); 1113 // special case for Exception.Message property 1114 // The com.sun.star.uno.Exception.Message field is mapped to the 1115 // System.Exception property. Type.GetField("Message") returns null 1116 if ( ! aField && usUnoException.equals(td.get()->pTypeName)) 1117 {// get Exception.Message property 1118 rtl::OUString usMessageMember(RTL_CONSTASCII_USTRINGPARAM("Message")); 1119 if (usMessageMember.equals(comp_td->ppMemberNames[nPos])) 1120 { 1121 sr::PropertyInfo ^ pi= cliType->GetProperty( 1122 mapUnoString(comp_td->ppMemberNames[nPos])); 1123 val= pi->GetValue(cli_data, nullptr); 1124 } 1125 else 1126 { 1127 OUStringBuffer buf(512); 1128 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("[map_to_uno(): Member: ")); 1129 buf.append(comp_td->ppMemberNames[nPos]); 1130 throw BridgeRuntimeError(buf.makeStringAndClear()); 1131 } 1132 } 1133 else 1134 { 1135 val= aField->GetValue(cli_data); 1136 } 1137 } 1138 void * p = (char *) uno_data + comp_td->pMemberOffsets[ nPos ]; 1139 //When using polymorphic structs then the parameterized members can be null. 1140 //Then we set a default value. 1141 bool bDefault = ((struct_td != NULL 1142 && struct_td->pParameterizedTypes != NULL 1143 && struct_td->pParameterizedTypes[nPos] == sal_True 1144 && val == nullptr) 1145 || cli_data == nullptr) ? true : false; 1146 switch (member_type->eTypeClass) 1147 { 1148 case typelib_TypeClass_CHAR: 1149 if (bDefault) 1150 *(sal_Unicode*) p = 0; 1151 else 1152 *(sal_Unicode*) p = safe_cast< System::Char >(val); 1153 break; 1154 case typelib_TypeClass_BOOLEAN: 1155 if (bDefault) 1156 *(sal_Bool*) p = sal_False; 1157 else 1158 *(sal_Bool*) p = safe_cast< System::Boolean >(val); 1159 break; 1160 case typelib_TypeClass_BYTE: 1161 if (bDefault) 1162 *(sal_Int8*) p = 0; 1163 else 1164 *(sal_Int8*) p = safe_cast< System::Byte >(val); 1165 break; 1166 case typelib_TypeClass_SHORT: 1167 if (bDefault) 1168 *(sal_Int16*) p = 0; 1169 else 1170 *(sal_Int16*) p = safe_cast< System::Int16 >(val); 1171 break; 1172 case typelib_TypeClass_UNSIGNED_SHORT: 1173 if (bDefault) 1174 *(sal_uInt16*) p = 0; 1175 else 1176 *(sal_uInt16*) p = safe_cast< System::UInt16 >(val); 1177 break; 1178 case typelib_TypeClass_LONG: 1179 if (bDefault) 1180 *(sal_Int32*) p = 0; 1181 else 1182 *(sal_Int32*) p = safe_cast< System::Int32 >(val); 1183 break; 1184 case typelib_TypeClass_UNSIGNED_LONG: 1185 if (bDefault) 1186 *(sal_uInt32*) p = 0; 1187 else 1188 *(sal_uInt32*) p = safe_cast< System::UInt32 >(val); 1189 break; 1190 case typelib_TypeClass_HYPER: 1191 if (bDefault) 1192 *(sal_Int64*) p = 0; 1193 else 1194 *(sal_Int64*) p = safe_cast< System::Int64 >(val); 1195 break; 1196 case typelib_TypeClass_UNSIGNED_HYPER: 1197 if (bDefault) 1198 *(sal_uInt64*) p = 0; 1199 else 1200 *(sal_uInt64*) p= safe_cast< System::UInt64 >(val); 1201 break; 1202 case typelib_TypeClass_FLOAT: 1203 if (bDefault) 1204 *(float*) p = 0.; 1205 else 1206 *(float*) p = safe_cast< System::Single >(val); 1207 break; 1208 case typelib_TypeClass_DOUBLE: 1209 if (bDefault) 1210 *(double*) p = 0.; 1211 else 1212 *(double*) p = safe_cast< System::Double >(val); 1213 break; 1214 default: 1215 { // ToDo enum, should be converted here 1216 map_to_uno(p, val, member_type, assign); 1217 break; 1218 } 1219 } 1220 } 1221 } 1222 catch (BridgeRuntimeError& e) 1223 { 1224 bException= true; 1225 OUStringBuffer buf(512); 1226 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("[map_to_uno():")); 1227 if (cliType) 1228 { 1229 buf.append(mapCliString(cliType->FullName)); 1230 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(".")); 1231 buf.append(comp_td->ppMemberNames[nPos]); 1232 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" ")); 1233 } 1234 buf.append(e.m_message); 1235 throw BridgeRuntimeError(buf.makeStringAndClear()); 1236 } 1237 catch (System::InvalidCastException ^ ) 1238 { 1239 bException= true; 1240 OUStringBuffer buf( 256 ); 1241 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); 1242 if (cliType) 1243 { 1244 buf.append(mapCliString(cliType->FullName)); 1245 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(".")); 1246 buf.append(comp_td->ppMemberNames[nPos]); 1247 } 1248 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] Value has not the required type.")); 1249 throw BridgeRuntimeError(buf.makeStringAndClear()); 1250 } 1251 catch (...) 1252 { 1253 OSL_ASSERT(0); 1254 bException= true; 1255 throw; 1256 } 1257 __finally 1258 { 1259 if (bException && !assign) // if assign then caller cleans up 1260 { 1261 // cleanup the members which we have converted so far 1262 for ( sal_Int32 nCleanup = 0; nCleanup < nPos; ++nCleanup ) 1263 { 1264 uno_type_destructData( 1265 uno_data, comp_td->ppTypeRefs[ nCleanup ], 0 ); 1266 } 1267 if (0 != comp_td->pBaseTypeDescription) 1268 { 1269 uno_destructData( 1270 uno_data, (typelib_TypeDescription *)comp_td->pBaseTypeDescription, 0 ); 1271 } 1272 } 1273 } 1274 break; 1275 } 1276 case typelib_TypeClass_SEQUENCE: 1277 { 1278 TypeDescr td( type ); 1279 typelib_TypeDescriptionReference * element_type = 1280 ((typelib_IndirectTypeDescription *)td.get())->pType; 1281 1282 auto_ptr< rtl_mem > seq; 1283 1284 System::Array ^ ar = nullptr; 1285 if (cli_data != nullptr) 1286 { 1287 ar = safe_cast< System::Array ^ >(cli_data); 1288 sal_Int32 nElements = ar->GetLength(0); 1289 1290 try 1291 { 1292 switch (element_type->eTypeClass) 1293 { 1294 case typelib_TypeClass_CHAR: 1295 seq = seq_allocate(nElements, sizeof (sal_Unicode)); 1296 sri::Marshal::Copy(safe_cast< cli::array< System::Char > ^ >(cli_data), 0, 1297 System::IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements); 1298 break; 1299 case typelib_TypeClass_BOOLEAN: 1300 { 1301 // Marshal::Copy has no Boolean[] overload. MC++ got 1302 // away with handing it one because it would implicitly 1303 // convert an array of bool to an array of byte; 1304 // C++/CLI will not, and a safe_cast to Byte[] throws, 1305 // because bool[] and byte[] are not castclass 1306 // compatible the way int16[] and uint16[] are. Copy 1307 // the elements instead. 1308 seq = seq_allocate(nElements, sizeof (sal_Bool)); 1309 cli::array< System::Boolean > ^ arBool = 1310 safe_cast< cli::array< System::Boolean > ^ >(cli_data); 1311 sal_Bool * pDest = (sal_Bool *) 1312 & ((uno_Sequence*) seq.get())->elements; 1313 for (sal_Int32 i = 0; i < nElements; i++) 1314 pDest[i] = arBool[i] ? sal_True : sal_False; 1315 break; 1316 } 1317 case typelib_TypeClass_BYTE: 1318 seq = seq_allocate( nElements, sizeof (sal_Int8) ); 1319 sri::Marshal::Copy(safe_cast< cli::array< System::Byte > ^ >(cli_data), 0, 1320 System::IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements); 1321 break; 1322 case typelib_TypeClass_SHORT: 1323 seq = seq_allocate(nElements, sizeof (sal_Int16)); 1324 sri::Marshal::Copy(safe_cast< cli::array< System::Int16 > ^ >(cli_data), 0, 1325 System::IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements); 1326 break; 1327 case typelib_TypeClass_UNSIGNED_SHORT: 1328 seq = seq_allocate( nElements, sizeof (sal_uInt16) ); 1329 sri::Marshal::Copy(safe_cast< cli::array< System::Int16 > ^ >(cli_data), 0, 1330 System::IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements); 1331 break; 1332 case typelib_TypeClass_LONG: 1333 seq = seq_allocate(nElements, sizeof (sal_Int32)); 1334 sri::Marshal::Copy(safe_cast< cli::array< System::Int32 > ^ >(cli_data), 0, 1335 System::IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements); 1336 break; 1337 case typelib_TypeClass_UNSIGNED_LONG: 1338 seq = seq_allocate( nElements, sizeof (sal_uInt32) ); 1339 sri::Marshal::Copy(safe_cast< cli::array< System::Int32 > ^ >(cli_data), 0, 1340 System::IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements); 1341 break; 1342 case typelib_TypeClass_HYPER: 1343 seq = seq_allocate(nElements, sizeof (sal_Int64)); 1344 sri::Marshal::Copy(safe_cast< cli::array< System::Int64 > ^ >(cli_data), 0, 1345 System::IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements); 1346 break; 1347 case typelib_TypeClass_UNSIGNED_HYPER: 1348 seq = seq_allocate(nElements, sizeof (sal_uInt64)); 1349 sri::Marshal::Copy(safe_cast< cli::array< System::Int64 > ^ >(cli_data), 0, 1350 System::IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements); 1351 break; 1352 case typelib_TypeClass_FLOAT: 1353 seq = seq_allocate(nElements, sizeof (float)); 1354 sri::Marshal::Copy(safe_cast< cli::array< System::Single > ^ >(cli_data), 0, 1355 System::IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements); 1356 break; 1357 case typelib_TypeClass_DOUBLE: 1358 seq = seq_allocate(nElements, sizeof (double)); 1359 sri::Marshal::Copy(safe_cast< cli::array< System::Double > ^ >(cli_data), 0, 1360 System::IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements); 1361 break; 1362 case typelib_TypeClass_STRING: 1363 { 1364 seq = seq_allocate(nElements, sizeof (rtl_uString*)); 1365 cli::array< System::String ^ > ^ arStr= safe_cast< cli::array< System::String ^ > ^ >(cli_data); 1366 for (int i= 0; i < nElements; i++) 1367 { 1368 pin_ptr< wchar_t const > pdata= PtrToStringChars(arStr[i]); 1369 rtl_uString** pStr= & ((rtl_uString**) & 1370 ((uno_Sequence*) seq.get())->elements)[i]; 1371 *pStr= NULL; 1372 rtl_uString_newFromStr_WithLength( pStr, pdata, 1373 arStr[i]->Length); 1374 } 1375 break; 1376 } 1377 case typelib_TypeClass_ENUM: 1378 seq = seq_allocate(nElements, sizeof (sal_Int32)); 1379 for (int i= 0; i < nElements; i++) 1380 { 1381 ((sal_Int32*) &((uno_Sequence*) seq.get())->elements)[i]= 1382 System::Convert::ToInt32(ar->GetValue(i)); 1383 } 1384 break; 1385 case typelib_TypeClass_TYPE: 1386 case typelib_TypeClass_ANY: 1387 case typelib_TypeClass_STRUCT: 1388 case typelib_TypeClass_EXCEPTION: 1389 case typelib_TypeClass_SEQUENCE: 1390 case typelib_TypeClass_INTERFACE: 1391 { 1392 TypeDescr element_td( element_type ); 1393 seq = seq_allocate( nElements, element_td.get()->nSize ); 1394 1395 for (sal_Int32 nPos = 0; nPos < nElements; ++nPos) 1396 { 1397 try 1398 { 1399 void * p= ((uno_Sequence *) seq.get())->elements + 1400 (nPos * element_td.get()->nSize); 1401 System::Object ^ elemData= dynamic_cast<System::Array ^>(cli_data)->GetValue(nPos); 1402 map_to_uno( 1403 p, elemData, element_td.get()->pWeakRef, 1404 false /* no assign */); 1405 } 1406 catch (...) 1407 { 1408 // cleanup 1409 for ( sal_Int32 nCleanPos = 0; nCleanPos < nPos; ++nCleanPos ) 1410 { 1411 void * p = 1412 ((uno_Sequence *)seq.get())->elements + 1413 (nCleanPos * element_td.get()->nSize); 1414 uno_destructData( p, element_td.get(), 0 ); 1415 } 1416 throw; 1417 } 1418 } 1419 break; 1420 } 1421 default: 1422 { 1423 OUStringBuffer buf( 128 ); 1424 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); 1425 buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) ); 1426 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported sequence element type: ") ); 1427 buf.append( *reinterpret_cast< OUString const * >( &element_type->pTypeName ) ); 1428 throw BridgeRuntimeError( buf.makeStringAndClear() ); 1429 } 1430 } 1431 } 1432 catch (BridgeRuntimeError& e) 1433 { 1434 OUStringBuffer buf( 128 ); 1435 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); 1436 buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName )); 1437 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] conversion failed\n ")); 1438 buf.append(e.m_message); 1439 throw BridgeRuntimeError(buf.makeStringAndClear()); 1440 } 1441 catch (System::InvalidCastException ^ ) 1442 { 1443 // Ok, checked 1444 OUStringBuffer buf( 128 ); 1445 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); 1446 buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName) ); 1447 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] could not convert sequence element type: ") ); 1448 buf.append( *reinterpret_cast< OUString const * >( &element_type->pTypeName ) ); 1449 throw BridgeRuntimeError( buf.makeStringAndClear() ); 1450 } 1451 catch (...) 1452 { 1453 OSL_ASSERT(0); 1454 throw; 1455 } 1456 __finally 1457 { 1458 if (assign) 1459 uno_destructData( uno_data, td.get(), 0 ); 1460 } 1461 } 1462 else 1463 { 1464 seq = seq_allocate(0, sizeof (sal_Int32)); 1465 } 1466 *(uno_Sequence **)uno_data = (uno_Sequence *)seq.release(); 1467 break; 1468 } 1469 case typelib_TypeClass_INTERFACE: 1470 { 1471 if (assign) 1472 { 1473 uno_Interface * p = *(uno_Interface **)uno_data; 1474 if (nullptr != p) 1475 (*p->release)( p ); 1476 } 1477 if (nullptr == cli_data) // null-ref 1478 { 1479 *(uno_Interface **)uno_data = 0; 1480 } 1481 else 1482 { 1483 TypeDescr td( type ); 1484 uno_Interface * pUnoI = map_cli2uno(cli_data, td.get()); 1485 *(uno_Interface **)uno_data = pUnoI; 1486 } 1487 break; 1488 } 1489 default: 1490 { 1491 //ToDo check 1492 OUStringBuffer buf( 128 ); 1493 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); 1494 buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) ); 1495 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported type!") ); 1496 throw BridgeRuntimeError( buf.makeStringAndClear() ); 1497 } 1498 } 1499 } 1500 // BridgeRuntimeError are allowed to be thrown 1501 catch (System::InvalidCastException ^ ) 1502 { 1503 //ToDo check 1504 OUStringBuffer buf( 128 ); 1505 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") ); 1506 buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) ); 1507 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] could not convert type!") ); 1508 throw BridgeRuntimeError( buf.makeStringAndClear() ); 1509 } 1510 catch (System::NullReferenceException ^ e) 1511 { 1512 OUStringBuffer buf(512); 1513 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM( 1514 "[map_to_uno()] Illegal null reference passed!\n")); 1515 buf.append(mapCliString(e->StackTrace)); 1516 throw BridgeRuntimeError( buf.makeStringAndClear() ); 1517 } 1518 catch (BridgeRuntimeError& ) 1519 { 1520 throw; 1521 } 1522 catch (...) 1523 { 1524 OSL_ASSERT(0); 1525 throw; 1526 } 1527 1528 } 1529 1530 /** 1531 @param info 1532 The expected target type. Currently info is provdided when this method is called 1533 to convert the in/out and out parameters of a call from cli to uno. Then info 1534 is always a byref type, e.g. "System.String&". info is used for Any and Enum conversion. 1535 @param bDontCreateObj 1536 false - a new object is created which holds the mapped uno value and is assigned to 1537 cli_data. 1538 true - cli_data already contains the newly constructed object. This is the case if 1539 a struct is converted then on the first call to map_to_cli the new object is created. 1540 If the struct inherits another struct then this function is called recursivly while the 1541 newly created object is passed in cli_data. 1542 */ 1543 void Bridge::map_to_cli( 1544 System::Object ^ *cli_data, void const * uno_data, 1545 typelib_TypeDescriptionReference * type, System::Type ^ info, 1546 bool bDontCreateObj) const 1547 { 1548 switch (type->eTypeClass) 1549 { 1550 case typelib_TypeClass_CHAR: 1551 *cli_data= (::System::Object ^)(*(__wchar_t const*)uno_data); 1552 break; 1553 case typelib_TypeClass_BOOLEAN: 1554 *cli_data = (::System::Object ^)((*(bool const*)uno_data) == sal_True ? true : false); 1555 break; 1556 case typelib_TypeClass_BYTE: 1557 *cli_data = (::System::Object ^)(*(unsigned char const*) uno_data); 1558 break; 1559 case typelib_TypeClass_SHORT: 1560 *cli_data= (::System::Object ^)(*(short const*) uno_data); 1561 break; 1562 case typelib_TypeClass_UNSIGNED_SHORT: 1563 *cli_data= (::System::Object ^)(*(unsigned short const*) uno_data); 1564 break; 1565 case typelib_TypeClass_LONG: 1566 *cli_data= (::System::Object ^)(*(int const*) uno_data); 1567 break; 1568 case typelib_TypeClass_UNSIGNED_LONG: 1569 *cli_data= (::System::Object ^)(*(unsigned int const*) uno_data); 1570 break; 1571 case typelib_TypeClass_HYPER: 1572 *cli_data= (::System::Object ^)(*(__int64 const*) uno_data); 1573 break; 1574 case typelib_TypeClass_UNSIGNED_HYPER: 1575 *cli_data= (::System::Object ^)(*(unsigned __int64 const*) uno_data); 1576 break; 1577 case typelib_TypeClass_FLOAT: 1578 *cli_data= (::System::Object ^)(*(float const*) uno_data); 1579 break; 1580 case typelib_TypeClass_DOUBLE: 1581 *cli_data= (::System::Object ^)(*(double const*) uno_data); 1582 break; 1583 case typelib_TypeClass_STRING: 1584 { 1585 rtl_uString const* sVal= NULL; 1586 sVal= *(rtl_uString* const*) uno_data; 1587 *cli_data= gcnew System::String((__wchar_t*) sVal->buffer,0, sVal->length); 1588 break; 1589 } 1590 case typelib_TypeClass_TYPE: 1591 { 1592 *cli_data= mapUnoType( *(typelib_TypeDescriptionReference * const *)uno_data ); 1593 break; 1594 } 1595 case typelib_TypeClass_ANY: 1596 { 1597 uno_Any const * pAny = (uno_Any const *)uno_data; 1598 if (typelib_TypeClass_VOID != pAny->pType->eTypeClass) 1599 { 1600 System::Object ^ objCli= nullptr; 1601 map_to_cli( 1602 &objCli, pAny->pData, pAny->pType, nullptr, 1603 false); 1604 1605 uno::Any anyVal(mapUnoType(pAny->pType), objCli); 1606 *cli_data= (::System::Object ^)(anyVal); 1607 } 1608 else 1609 { // void any 1610 *cli_data= (::System::Object ^)(uno::Any::VOID); 1611 } 1612 break; 1613 } 1614 case typelib_TypeClass_ENUM: 1615 { 1616 if (info != nullptr) 1617 { 1618 OSL_ASSERT(info->IsByRef); 1619 info= info->GetElementType(); 1620 *cli_data= System::Enum::ToObject(info, *(System::Int32 *) uno_data); 1621 } 1622 else 1623 *cli_data= System::Enum::ToObject( 1624 mapUnoType(type), *(System::Int32 *) uno_data); 1625 break; 1626 } 1627 case typelib_TypeClass_STRUCT: 1628 case typelib_TypeClass_EXCEPTION: 1629 { 1630 TypeDescr td( type ); 1631 typelib_CompoundTypeDescription * comp_td = 1632 (typelib_CompoundTypeDescription *) td.get(); 1633 if ( ! ((typelib_TypeDescription*) comp_td)->bComplete) 1634 ::typelib_typedescription_complete( 1635 (typelib_TypeDescription**) & comp_td ); 1636 1637 1638 //create the type 1639 System::Type ^ cliType= loadCliType(td.get()->pTypeName); 1640 //detect if we recursivly convert inherited structures 1641 //If this point is reached because of a recursive call during convering a 1642 //struct then we must not create a new object rather we use the one in 1643 // cli_data argument. 1644 System::Object ^ cliObj; 1645 if (bDontCreateObj) 1646 cliObj = *cli_data; // recursive call 1647 else 1648 { 1649 //Special handling for Exception conversion. We must call constructor System::Exception 1650 //to pass the message string 1651 if (ucss::uno::Exception::typeid->IsAssignableFrom(cliType)) 1652 { 1653 //We need to get the Message field. Therefore we must obtain the offset from 1654 //the typedescription. The base interface of all exceptions is 1655 //com::sun::star::uno::Exception which contains the message 1656 typelib_CompoundTypeDescription* pCTD = comp_td; 1657 while (pCTD->pBaseTypeDescription) 1658 pCTD = pCTD->pBaseTypeDescription; 1659 int nPos = -1; 1660 1661 rtl::OUString usMessageMember(RTL_CONSTASCII_USTRINGPARAM("Message")); 1662 for (int i = 0; i < pCTD->nMembers; i ++) 1663 { 1664 #if OSL_DEBUG_LEVEL >= 2 1665 System::String ^ sMember; 1666 sMember = mapUnoString(pCTD->ppMemberNames[i]); 1667 #endif 1668 if (usMessageMember.equals(pCTD->ppMemberNames[i])) 1669 { 1670 nPos = i; 1671 break; 1672 } 1673 } 1674 OSL_ASSERT (nPos != -1); 1675 int offset = pCTD->pMemberOffsets[nPos]; 1676 //With the offset within the exception we can get the message string 1677 System::String ^ sMessage = mapUnoString(*(rtl_uString**) 1678 ((char*) uno_data + offset)); 1679 //We need to find a constructor for the exception that takes the message string 1680 //We assume that the first argument is the message string 1681 cli::array< sr::ConstructorInfo ^ > ^ arCtorInfo = cliType->GetConstructors(); 1682 sr::ConstructorInfo ^ ctorInfo = nullptr; 1683 int numCtors = arCtorInfo->Length; 1684 //Constructor must at least have 2 params for the base 1685 //unoidl.com.sun.star.uno.Exception (String, Object); 1686 cli::array< sr::ParameterInfo ^ > ^ arParamInfo; 1687 for (int i = 0; i < numCtors; i++) 1688 { 1689 arParamInfo = arCtorInfo[i]->GetParameters(); 1690 if (arParamInfo->Length < 2) 1691 continue; 1692 ctorInfo = arCtorInfo[i]; 1693 break; 1694 } 1695 OSL_ASSERT(arParamInfo[0]->ParameterType->Equals(System::String::typeid) 1696 && arParamInfo[1]->ParameterType->Equals(System::Object::typeid) 1697 && arParamInfo[0]->Position == 0 1698 && arParamInfo[1]->Position == 1); 1699 //Prepare parameters for constructor 1700 int numArgs = arParamInfo->Length; 1701 cli::array< System::Object ^ > ^ args = gcnew cli::array< System::Object ^ >( numArgs ); 1702 //only initialize the first argument with the message 1703 args[0] = sMessage; 1704 cliObj = ctorInfo->Invoke(args); 1705 } 1706 else 1707 cliObj = System::Activator::CreateInstance(cliType); 1708 } 1709 sal_Int32 * pMemberOffsets = comp_td->pMemberOffsets; 1710 1711 if (comp_td->pBaseTypeDescription) 1712 { 1713 //convert inherited struct 1714 //cliObj is passed inout (args in_param, out_param are true), hence the passed 1715 // cliObj is used by the callee instead of a newly created struct 1716 map_to_cli( 1717 &cliObj, uno_data, 1718 ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef, nullptr, 1719 true); 1720 } 1721 rtl::OUString usUnoException(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Exception")); 1722 for (sal_Int32 nPos = comp_td->nMembers; nPos--; ) 1723 { 1724 typelib_TypeDescriptionReference * member_type = comp_td->ppTypeRefs[ nPos ]; 1725 System::String ^ sMemberName= mapUnoString(comp_td->ppMemberNames[nPos]); 1726 sr::FieldInfo ^ aField= cliType->GetField(sMemberName); 1727 // special case for Exception.Message. The field has already been 1728 // set while constructing cli object 1729 if ( ! aField && usUnoException.equals(td.get()->pTypeName)) 1730 { 1731 continue; 1732 } 1733 void const * p = (char const *)uno_data + pMemberOffsets[ nPos ]; 1734 switch (member_type->eTypeClass) 1735 { 1736 case typelib_TypeClass_CHAR: 1737 aField->SetValue(cliObj, (::System::Object ^)(*(System::Char *) p)); 1738 break; 1739 case typelib_TypeClass_BOOLEAN: 1740 aField->SetValue(cliObj, (::System::Object ^)(*(System::Boolean *) p)); 1741 break; 1742 case typelib_TypeClass_BYTE: 1743 aField->SetValue(cliObj, (::System::Object ^)(*(System::Byte *) p)); 1744 break; 1745 case typelib_TypeClass_SHORT: 1746 aField->SetValue(cliObj, (::System::Object ^)(*(System::Int16 *) p)); 1747 break; 1748 case typelib_TypeClass_UNSIGNED_SHORT: 1749 aField->SetValue(cliObj, (::System::Object ^)(*(System::UInt16 *) p)); 1750 break; 1751 case typelib_TypeClass_LONG: 1752 aField->SetValue(cliObj, (::System::Object ^)(*(System::Int32 *) p)); 1753 break; 1754 case typelib_TypeClass_UNSIGNED_LONG: 1755 aField->SetValue(cliObj, (::System::Object ^)(*(System::UInt32 *) p)); 1756 break; 1757 case typelib_TypeClass_HYPER: 1758 aField->SetValue(cliObj, (::System::Object ^)(*(System::Int64 *) p)); 1759 break; 1760 case typelib_TypeClass_UNSIGNED_HYPER: 1761 aField->SetValue(cliObj, (::System::Object ^)(*(System::UInt64 *) p)); 1762 break; 1763 case typelib_TypeClass_FLOAT: 1764 aField->SetValue(cliObj, (::System::Object ^)(*(System::Single *) p)); 1765 break; 1766 case typelib_TypeClass_DOUBLE: 1767 aField->SetValue(cliObj, (::System::Object ^)(*(System::Double *) p)); 1768 break; 1769 default: 1770 { 1771 System::Object ^ cli_val; 1772 map_to_cli( 1773 &cli_val, p, member_type, nullptr, 1774 false); 1775 aField->SetValue(cliObj, cli_val); 1776 break; 1777 } 1778 } 1779 } 1780 *cli_data= cliObj; 1781 break; 1782 } 1783 case typelib_TypeClass_SEQUENCE: 1784 { 1785 sal_Int32 nElements; 1786 uno_Sequence const * seq = 0; 1787 seq = *(uno_Sequence * const *)uno_data; 1788 nElements = seq->nElements; 1789 1790 TypeDescr td( type ); 1791 typelib_TypeDescriptionReference * element_type = 1792 ((typelib_IndirectTypeDescription *)td.get())->pType; 1793 1794 switch (element_type->eTypeClass) 1795 { 1796 case typelib_TypeClass_CHAR: 1797 { 1798 cli::array< System::Char > ^ arChar = gcnew cli::array< System::Char >( nElements ); 1799 sri::Marshal::Copy( System::IntPtr( (void*) &seq->elements ), arChar, 0, nElements); 1800 *cli_data= arChar; 1801 break; 1802 } 1803 case typelib_TypeClass_BOOLEAN: 1804 { 1805 // The element type has to be Boolean -- the caller gets a bool[]. 1806 // Marshal::Copy cannot fill one (see the other direction), so copy 1807 // the elements. 1808 cli::array< System::Boolean > ^ arBool = 1809 gcnew cli::array< System::Boolean >( nElements ); 1810 sal_Bool const * pSrc = (sal_Bool const *) &seq->elements; 1811 for (sal_Int32 i = 0; i < nElements; i++) 1812 arBool[i] = (pSrc[i] != sal_False); 1813 *cli_data= arBool; 1814 break; 1815 } 1816 case typelib_TypeClass_BYTE: 1817 { 1818 cli::array< System::Byte > ^ arByte = gcnew cli::array< System::Byte >( nElements ); 1819 sri::Marshal::Copy( System::IntPtr( (void*) &seq->elements ), arByte, 0, nElements); 1820 *cli_data= arByte; 1821 break; 1822 } 1823 case typelib_TypeClass_SHORT: 1824 { 1825 cli::array< System::Int16 > ^ arShort = gcnew cli::array< System::Int16 >( nElements ); 1826 sri::Marshal::Copy( System::IntPtr( (void*) &seq->elements ), arShort, 0, nElements); 1827 *cli_data= arShort; 1828 break; 1829 } 1830 case typelib_TypeClass_UNSIGNED_SHORT: 1831 { 1832 // The caller gets an unsigned array -- allocate THAT, and cast 1833 // only for the Copy call, which has no unsigned overload. An 1834 // array of unsigned and one of signed of the same size are 1835 // castclass compatible, so the cast is a no-op at runtime. 1836 cli::array< System::UInt16 > ^ arUInt16 = 1837 gcnew cli::array< System::UInt16 >( nElements ); 1838 sri::Marshal::Copy( System::IntPtr( (void*) &seq->elements ), 1839 safe_cast< cli::array< System::Int16 > ^ >( 1840 (System::Object ^) arUInt16 ), 1841 0, nElements); 1842 *cli_data= arUInt16; 1843 break; 1844 } 1845 case typelib_TypeClass_LONG: 1846 { 1847 cli::array< System::Int32 > ^ arInt32 = gcnew cli::array< System::Int32 >( nElements ); 1848 sri::Marshal::Copy( System::IntPtr( (void*) &seq->elements ), arInt32, 0, nElements); 1849 *cli_data= arInt32; 1850 break; 1851 } 1852 case typelib_TypeClass_UNSIGNED_LONG: 1853 { 1854 // The caller gets an unsigned array -- allocate THAT, and cast 1855 // only for the Copy call, which has no unsigned overload. An 1856 // array of unsigned and one of signed of the same size are 1857 // castclass compatible, so the cast is a no-op at runtime. 1858 cli::array< System::UInt32 > ^ arUInt32 = 1859 gcnew cli::array< System::UInt32 >( nElements ); 1860 sri::Marshal::Copy( System::IntPtr( (void*) &seq->elements ), 1861 safe_cast< cli::array< System::Int32 > ^ >( 1862 (System::Object ^) arUInt32 ), 1863 0, nElements); 1864 *cli_data= arUInt32; 1865 break; 1866 } 1867 case typelib_TypeClass_HYPER: 1868 { 1869 cli::array< System::Int64 > ^ arInt64 = gcnew cli::array< System::Int64 >( nElements ); 1870 sri::Marshal::Copy( System::IntPtr( (void*) &seq->elements ), arInt64, 0, nElements); 1871 *cli_data= arInt64; 1872 break; 1873 } 1874 case typelib_TypeClass_UNSIGNED_HYPER: 1875 { 1876 // The caller gets an unsigned array -- allocate THAT, and cast 1877 // only for the Copy call, which has no unsigned overload. An 1878 // array of unsigned and one of signed of the same size are 1879 // castclass compatible, so the cast is a no-op at runtime. 1880 cli::array< System::UInt64 > ^ arUInt64 = 1881 gcnew cli::array< System::UInt64 >( nElements ); 1882 sri::Marshal::Copy( System::IntPtr( (void*) &seq->elements ), 1883 safe_cast< cli::array< System::Int64 > ^ >( 1884 (System::Object ^) arUInt64 ), 1885 0, nElements); 1886 *cli_data= arUInt64; 1887 break; 1888 } 1889 case typelib_TypeClass_FLOAT: 1890 { 1891 cli::array< System::Single > ^ arSingle = gcnew cli::array< System::Single >( nElements ); 1892 sri::Marshal::Copy( System::IntPtr( (void*) &seq->elements ), arSingle, 0, nElements); 1893 *cli_data= arSingle; 1894 break; 1895 } 1896 case typelib_TypeClass_DOUBLE: 1897 { 1898 cli::array< System::Double > ^ arDouble = gcnew cli::array< System::Double >( nElements ); 1899 sri::Marshal::Copy( System::IntPtr( (void*) &seq->elements ), arDouble, 0, nElements); 1900 *cli_data= arDouble; 1901 break; 1902 } 1903 case typelib_TypeClass_STRING: 1904 { 1905 cli::array< System::String ^ > ^ arString= gcnew cli::array< System::String ^ >( nElements ); 1906 for (int i= 0; i < nElements; i++) 1907 { 1908 rtl_uString *aStr= ((rtl_uString**)(&seq->elements))[i]; 1909 arString[i]= gcnew System::String( (__wchar_t *) &aStr->buffer, 0, aStr->length); 1910 } 1911 *cli_data= arString; 1912 break; 1913 } 1914 case typelib_TypeClass_TYPE: 1915 { 1916 cli::array< System::Type ^ > ^ arType= gcnew cli::array< System::Type ^ >( nElements ); 1917 for (int i= 0; i < nElements; i++) 1918 { 1919 arType[i]= 1920 mapUnoType( ((typelib_TypeDescriptionReference**) seq->elements)[i]); 1921 } 1922 *cli_data= arType; 1923 break; 1924 } 1925 case typelib_TypeClass_ANY: 1926 { 1927 cli::array< uno::Any > ^ arCli= gcnew cli::array< uno::Any >( nElements ); 1928 uno_Any const * p = (uno_Any const *)seq->elements; 1929 for (sal_Int32 nPos = 0; nPos < nElements; ++nPos ) 1930 { 1931 System::Object ^ cli_obj = nullptr; 1932 map_to_cli( 1933 &cli_obj, &p[ nPos ], element_type, nullptr, false); 1934 arCli[nPos]= safe_cast< uno::Any >(cli_obj); 1935 } 1936 *cli_data= arCli; 1937 break; 1938 } 1939 case typelib_TypeClass_ENUM: 1940 { 1941 //get the Enum type 1942 System::Type ^ enumType= nullptr; 1943 if (info != nullptr) 1944 { 1945 //info is EnumType[]&, remove & 1946 OSL_ASSERT(info->IsByRef); 1947 enumType = info->GetElementType(); 1948 //enumType is EnumType[], remove [] 1949 enumType = enumType->GetElementType(); 1950 } 1951 else 1952 enumType= mapUnoType(element_type); 1953 1954 System::Array ^ arEnum = System::Array::CreateInstance( 1955 enumType, nElements); 1956 for (int i= 0; i < nElements; i++) 1957 { 1958 arEnum->SetValue(System::Enum::ToObject(enumType, 1959 ((sal_Int32*) seq->elements)[i]), i); 1960 } 1961 *cli_data = arEnum; 1962 break; 1963 } 1964 case typelib_TypeClass_STRUCT: 1965 case typelib_TypeClass_EXCEPTION: 1966 { 1967 TypeDescr element_td( element_type ); 1968 System::Array ^ ar= System::Array::CreateInstance( 1969 mapUnoType(element_type),nElements); 1970 if (0 < nElements) 1971 { 1972 // ToDo check this 1973 char * p = (char *) &seq->elements; 1974 sal_Int32 nSize = element_td.get()->nSize; 1975 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) 1976 { 1977 System::Object ^ val; 1978 map_to_cli( 1979 &val, p + (nSize * nPos), element_type, nullptr, false); 1980 ar->SetValue(val, nPos); 1981 } 1982 } 1983 *cli_data = ar; 1984 break; 1985 } 1986 // ToDo, verify 1987 case typelib_TypeClass_SEQUENCE: 1988 { 1989 System::Array ^ar= System::Array::CreateInstance( 1990 mapUnoType(element_type), nElements); 1991 if (0 < nElements) 1992 { 1993 TypeDescr element_td( element_type ); 1994 uno_Sequence ** elements = (uno_Sequence**) seq->elements; 1995 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) 1996 { 1997 System::Object ^ val; 1998 map_to_cli( 1999 &val, &elements[nPos], element_type, nullptr, false); 2000 ar->SetValue(val, nPos); 2001 } 2002 } 2003 *cli_data = ar; 2004 break; 2005 } 2006 case typelib_TypeClass_INTERFACE: 2007 { 2008 TypeDescr element_td( element_type ); 2009 System::Type ^ ifaceType= mapUnoType(element_type); 2010 System::Array ^ ar= System::Array::CreateInstance(ifaceType, nElements); 2011 2012 char * p = (char *)seq->elements; 2013 sal_Int32 nSize = element_td.get()->nSize; 2014 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) 2015 { 2016 System::Object ^ val; 2017 map_to_cli( 2018 &val, p + (nSize * nPos), element_type, nullptr, false); 2019 2020 ar->SetValue(val, nPos); 2021 } 2022 *cli_data= ar; 2023 break; 2024 } 2025 default: 2026 { 2027 OUStringBuffer buf( 128 ); 2028 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_cli():") ); 2029 buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) ); 2030 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported element type: ") ); 2031 buf.append( *reinterpret_cast< OUString const * >( &element_type->pTypeName ) ); 2032 throw BridgeRuntimeError( buf.makeStringAndClear() ); 2033 } 2034 } 2035 break; 2036 } 2037 case typelib_TypeClass_INTERFACE: 2038 { 2039 uno_Interface * pUnoI = *(uno_Interface * const *)uno_data; 2040 if (0 != pUnoI) 2041 { 2042 TypeDescr td( type ); 2043 *cli_data= map_uno2cli( pUnoI, reinterpret_cast< 2044 typelib_InterfaceTypeDescription*>(td.get())) ; 2045 } 2046 else 2047 // NOT NULL. *cli_data is a System::Object^, and assigning the 2048 // literal 0 to one BOXES it into an Int32 rather than storing a 2049 // null reference. The caller then holds a boxed integer where the 2050 // signature says an interface; mapping it back builds a proxy FOR 2051 // THAT INTEGER, so a null interface returns non-null. 2052 *cli_data= nullptr; 2053 break; 2054 } 2055 default: 2056 { 2057 //ToDo check this exception. The String is probably crippled 2058 OUStringBuffer buf( 128 ); 2059 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_cli():") ); 2060 buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) ); 2061 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported type!") ); 2062 throw BridgeRuntimeError( buf.makeStringAndClear() ); 2063 } 2064 } 2065 } 2066 } 2067