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
seq_allocate(sal_Int32 nElements,sal_Int32 nSize)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