xref: /trunk/main/cli_ure/source/uno_bridge/cli_data.cxx (revision 9d37da743abb7db0a497688391f6e55a19f27c44)
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