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= NULL;
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(__typeof(Cli_environment));
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(__typeof(Cli_environment));
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= NULL;
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         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 == NULL)
180 		{
181             System::String * msg = new System::String(S"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->get_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 = 0;
208     switch (pTD->eTypeClass)
209     {
210     case typelib_TypeClass_VOID:
211         retVal= __typeof(void); break;
212     case typelib_TypeClass_CHAR:
213         retVal= __typeof(System::Char); break;
214     case typelib_TypeClass_BOOLEAN:
215         retVal= __typeof(System::Boolean); break;
216     case typelib_TypeClass_BYTE:
217         retVal= __typeof(System::Byte); break;
218     case typelib_TypeClass_SHORT:
219         retVal= __typeof(System::Int16); break;
220     case typelib_TypeClass_UNSIGNED_SHORT:
221         retVal= __typeof(System::UInt16); break;
222     case typelib_TypeClass_LONG:
223         retVal= __typeof(System::Int32); break;
224     case typelib_TypeClass_UNSIGNED_LONG:
225         retVal= __typeof(System::UInt32); break;
226     case typelib_TypeClass_HYPER:
227         retVal= __typeof(System::Int64); break;
228     case typelib_TypeClass_UNSIGNED_HYPER:
229         retVal= __typeof(System::UInt64); break;
230     case typelib_TypeClass_FLOAT:
231         retVal= __typeof(System::Single); break;
232     case typelib_TypeClass_DOUBLE:
233         retVal= __typeof(System::Double); break;
234     case typelib_TypeClass_STRING:
235         retVal= __typeof(System::String); break;
236     case typelib_TypeClass_TYPE:
237         retVal= __typeof(System::Type); break;
238     case typelib_TypeClass_ANY:
239         retVal= __typeof(uno::Any); 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= __typeof(System::Object);
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     if (cliType == NULL)
330     {
331         retVal = * typelib_static_type_getByTypeClass(
332             typelib_TypeClass_VOID );
333         typelib_typedescriptionreference_acquire( retVal );
334         return retVal;
335     }
336     //check for Enum first,
337     //because otherwise case System::TypeCode::Int32 applies
338     if (cliType->get_IsEnum())
339     {
340         OUString usTypeName= mapCliTypeName(cliType->get_FullName());
341         css::uno::Type unoType(css::uno::TypeClass_ENUM, usTypeName);
342         retVal= unoType.getTypeLibType();
343         typelib_typedescriptionreference_acquire(retVal);
344     }
345     else
346     {
347         switch (System::Type::GetTypeCode(cliType))
348         {
349         case System::TypeCode::Boolean:
350             retVal = * typelib_static_type_getByTypeClass(
351                 typelib_TypeClass_BOOLEAN );
352             typelib_typedescriptionreference_acquire( retVal );
353             break;
354         case System::TypeCode::Char:
355             retVal = * typelib_static_type_getByTypeClass(
356                 typelib_TypeClass_CHAR );
357             typelib_typedescriptionreference_acquire( retVal );
358             break;
359         case System::TypeCode::Byte:
360             retVal = * typelib_static_type_getByTypeClass(
361                 typelib_TypeClass_BYTE );
362             typelib_typedescriptionreference_acquire( retVal );
363             break;
364         case System::TypeCode::Int16:
365             retVal = * typelib_static_type_getByTypeClass(
366                 typelib_TypeClass_SHORT );
367             typelib_typedescriptionreference_acquire( retVal );
368             break;
369         case System::TypeCode::Int32:
370             retVal = * typelib_static_type_getByTypeClass(
371                 typelib_TypeClass_LONG );
372             typelib_typedescriptionreference_acquire( retVal );
373             break;
374         case System::TypeCode::Int64:
375             retVal = * typelib_static_type_getByTypeClass(
376                 typelib_TypeClass_HYPER );
377             typelib_typedescriptionreference_acquire( retVal );
378             break;
379         case System::TypeCode::UInt16:
380             retVal = * typelib_static_type_getByTypeClass(
381                 typelib_TypeClass_UNSIGNED_SHORT );
382             typelib_typedescriptionreference_acquire( retVal );
383             break;
384         case System::TypeCode::UInt32:
385             retVal = * typelib_static_type_getByTypeClass(
386                 typelib_TypeClass_UNSIGNED_LONG );
387             typelib_typedescriptionreference_acquire( retVal );
388             break;
389         case System::TypeCode::UInt64:
390             retVal = * typelib_static_type_getByTypeClass(
391                 typelib_TypeClass_UNSIGNED_HYPER );
392             typelib_typedescriptionreference_acquire( retVal );
393             break;
394         case System::TypeCode::Single:
395             retVal = * typelib_static_type_getByTypeClass(
396                 typelib_TypeClass_FLOAT );
397             typelib_typedescriptionreference_acquire( retVal );
398             break;
399         case System::TypeCode::Double:
400             retVal = * typelib_static_type_getByTypeClass(
401                 typelib_TypeClass_DOUBLE );
402             typelib_typedescriptionreference_acquire( retVal );
403             break;
404         case System::TypeCode::String:
405             retVal = * typelib_static_type_getByTypeClass(
406                 typelib_TypeClass_STRING );
407             typelib_typedescriptionreference_acquire( retVal );
408             break;
409         default:
410             break;
411         }
412     }
413     if (retVal == NULL)
414     {
415         System::String* cliTypeName= cliType->get_FullName();
416         // Void
417         if (const_cast<System::String*>(Constants::sVoid)->Equals(
418                 cliTypeName))
419         {
420             retVal = * typelib_static_type_getByTypeClass(
421                 typelib_TypeClass_VOID );
422             typelib_typedescriptionreference_acquire( retVal );
423         }
424         // Type
425         else if (const_cast<System::String*>(Constants::sType)->Equals(
426                      cliTypeName))
427         {
428             retVal = * typelib_static_type_getByTypeClass(
429                 typelib_TypeClass_TYPE );
430             typelib_typedescriptionreference_acquire( retVal );
431         }
432         // Any
433         else if (const_cast<System::String*>(Constants::sAny)->Equals(
434                      cliTypeName))
435         {
436             retVal = * typelib_static_type_getByTypeClass(
437                 typelib_TypeClass_ANY );
438             typelib_typedescriptionreference_acquire( retVal );
439         }
440         //struct, interfaces, sequences
441         else
442         {
443             OUString usTypeName;
444             uno::PolymorphicType * poly = dynamic_cast<uno::PolymorphicType*>(cliType);
445             if (poly != NULL)
446                 usTypeName = mapCliTypeName( poly->PolymorphicName);
447             else
448                 usTypeName = mapCliTypeName(cliTypeName);
449             typelib_TypeDescription* td = NULL;
450             typelib_typedescription_getByName(&td, usTypeName.pData);
451             if (td)
452             {
453                 retVal = td->pWeakRef;
454                 typelib_typedescriptionreference_acquire(retVal);
455                 typelib_typedescription_release(td);
456             }
457         }
458     }
459     if (retVal == NULL)
460     {
461         OUStringBuffer buf( 128 );
462         buf.appendAscii(
463             RTL_CONSTASCII_STRINGPARAM("[cli_uno bridge] mapCliType():"
464                                        "could not map type: ") );
465         buf.append(mapCliString(cliType->get_FullName()));
466         throw BridgeRuntimeError( buf.makeStringAndClear() );
467     }
468     return retVal;
469 }
470 
471 /**
472     Otherwise a leading "unoidl." is removed.
473  */
474 System::String* mapUnoTypeName(rtl_uString const * typeName)
475 {
476     OUString usUnoName( const_cast< rtl_uString * >( typeName ) );
477     st::StringBuilder* buf= new st::StringBuilder();
478     //determine if the type is a sequence and its dimensions
479     int dims= 0;
480     if (usUnoName[0] == '[')
481     {
482         sal_Int32 index= 1;
483         while (true)
484         {
485             if (usUnoName[index++] == ']')
486                 dims++;
487             if (usUnoName[index++] != '[')
488                 break;
489         }
490         usUnoName = usUnoName.copy(index - 1);
491     }
492 	System::String * sUnoName = mapUnoString(usUnoName.pData);
493 	if (sUnoName->Equals(const_cast<System::String*>(Constants::usBool)))
494         buf->Append(const_cast<System::String*>(Constants::sBoolean));
495     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usChar)))
496         buf->Append(const_cast<System::String*>(Constants::sChar));
497     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usByte)))
498         buf->Append(const_cast<System::String*>(Constants::sByte));
499     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usShort)))
500         buf->Append(const_cast<System::String*>(Constants::sInt16));
501     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usUShort)))
502         buf->Append(const_cast<System::String*>(Constants::sUInt16));
503     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usLong)))
504         buf->Append(const_cast<System::String*>(Constants::sInt32));
505     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usULong)))
506         buf->Append(const_cast<System::String*>(Constants::sUInt32));
507     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usHyper)))
508         buf->Append(const_cast<System::String*>(Constants::sInt64));
509     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usUHyper)))
510         buf->Append(const_cast<System::String*>(Constants::sUInt64));
511     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usFloat)))
512         buf->Append(const_cast<System::String*>(Constants::sSingle));
513     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usDouble)))
514         buf->Append(const_cast<System::String*>(Constants::sDouble));
515     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usString)))
516         buf->Append(const_cast<System::String*>(Constants::sString));
517     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usVoid)))
518         buf->Append(const_cast<System::String*>(Constants::sVoid));
519     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usType)))
520         buf->Append(const_cast<System::String*>(Constants::sType));
521     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usXInterface)))
522         buf->Append(const_cast<System::String*>(Constants::sObject));
523     else if (sUnoName->Equals(const_cast<System::String*>(Constants::usAny)))
524     {
525         buf->Append(const_cast<System::String*>(Constants::sAny));
526     }
527     else
528     {
529         //put "unoidl." at the beginning
530         buf->Append(const_cast<System::String*>(Constants::sUnoidl));
531         //for polymorphic struct types remove the brackets, e.g mystruct<bool> -> mystruct
532 		System::String * sName = mapUnoPolymorphicName(sUnoName);
533         buf->Append(sName);
534     }
535     // apend []
536     for (;dims--;)
537         buf->Append(const_cast<System::String*>(Constants::sBrackets));
538 
539     return buf->ToString();
540 }
541 
542 
543 
544 
545 /** For example, there is a uno type
546     com.sun.star.Foo<char, long>.
547     The values in the type list
548     are uno types and are replaced by cli types, such as System.Char,
549     System.Int32, etc.
550     The pr�fix unoidl is not added.
551  */
552 inline System::String* mapUnoPolymorphicName(System::String* unoName)
553 {
554        return mapPolymorphicName(unoName, false);
555 }
556 /** For example, there is a type name such as
557     com.sun.star.Foo<System.Char, System.Int32>.
558     The values in the type list
559     are CLI types and are replaced by uno types, such as char,
560     long, etc.
561     The pr�fix unoidl remains.
562  */
563 inline System::String* mapCliPolymorphicName(System::String* unoName)
564 {
565     return mapPolymorphicName(unoName, true);
566 }
567 
568 System::String* mapPolymorphicName(System::String* unoName, bool bCliToUno)
569 {
570     int index = unoName->IndexOf('<');
571     if (index == -1)
572         return unoName;
573 
574     System::Text::StringBuilder * builder = new System::Text::StringBuilder(256);
575     builder->Append(unoName->Substring(0, index +1 ));
576 
577 	//Find the first occurrence of ','
578 	//If the parameter is a polymorphic struct then we neede to ignore everything
579 	//between the brackets because it can also contain commas
580     //get the type list within < and >
581 	int endIndex = unoName->Length - 1;
582 	index++;
583 	int cur = index;
584 	int countParams = 0;
585 	while (cur <= endIndex)
586 	{
587 		System::Char c = unoName->Chars[cur];
588 		if (c == ',' || c == '>')
589 		{
590 			//insert a comma if needed
591 			if (countParams != 0)
592 				builder->Append(S",");
593 			countParams++;
594 			System::String * sParam = unoName->Substring(index, cur - index);
595 			//skip the comma
596 			cur++;
597 			//the the index to the beginning of the next param
598 			index = cur;
599             if (bCliToUno)
600             {
601                 builder->Append( mapCliTypeName(sParam).getStr());
602             }
603             else
604             {
605                 OUString s = mapCliString(sParam);
606                 builder->Append(mapUnoTypeName(s.pData));
607             }
608 		}
609 		else if (c == '<')
610 		{
611 			cur++;
612 			//continue until the matching '>'
613 			int numNested = 0;
614 			for (;;cur++)
615 			{
616 				System::Char curChar = unoName->Chars[cur];
617 				if (curChar == '<')
618 				{
619 					numNested ++;
620 				}
621 				else if (curChar == '>')
622 				{
623 					if (numNested > 0)
624 						numNested--;
625 					else
626 						break;
627 				}
628 			}
629 		}
630 		cur++;
631 	}
632 
633     builder->Append((System::Char) '>');
634     return builder->ToString();
635 }
636 
637 OUString mapCliTypeName(System::String* typeName)
638 {
639     int dims= 0;
640     // Array? determine the "rank" (number of "[]")
641     // move from the rightmost end to the left, for example
642     // unoidl.PolymorphicStruct<System.Char[]>[]
643     // has only a "dimension" of 1
644 	int cur = typeName->Length - 1;
645     bool bRightBracket = false;
646 	while (cur >= 0)
647 	{
648 		System::Char c = typeName->Chars[cur];
649 		if (c == ']')
650 		{
651             bRightBracket = true;
652 		}
653         else if (c == '[')
654         {
655             if (!bRightBracket)
656                 throw BridgeRuntimeError(
657                     OUSTR("Typename is wrong. No matching brackets for sequence. Name is: ") +
658                     mapCliString(typeName));
659             bRightBracket = false;
660             dims ++;
661         }
662         else
663         {
664             if (bRightBracket)
665                 throw BridgeRuntimeError(
666                     OUSTR("Typename is wrong. No matching brackets for sequence. Name is: ") +
667                     mapCliString(typeName));
668             break;
669         }
670         cur--;
671 	}
672 
673     if (bRightBracket || cur < 0)
674         throw BridgeRuntimeError(
675             OUSTR("Typename is wrong. ") +
676             mapCliString(typeName));
677 
678     typeName = typeName->Substring(0, cur + 1);
679 
680 	System::Text::StringBuilder * buf = new System::Text::StringBuilder(512);
681 
682     //Put the "[]" at the beginning of the uno type name
683     for (;dims--;)
684 		buf->Append(const_cast<System::String*>(Constants::usBrackets));
685 
686     if (typeName->Equals(const_cast<System::String*>(Constants::sBoolean)))
687         buf->Append(const_cast<System::String*>(Constants::usBool));
688     else if (typeName->Equals(const_cast<System::String*>(Constants::sChar)))
689         buf->Append(const_cast<System::String*>(Constants::usChar));
690     else if (typeName->Equals(const_cast<System::String*>(Constants::sByte)))
691         buf->Append(const_cast<System::String*>(Constants::usByte));
692     else if (typeName->Equals(const_cast<System::String*>(Constants::sInt16)))
693         buf->Append(const_cast<System::String*>(Constants::usShort));
694     else if (typeName->Equals(const_cast<System::String*>(Constants::sUInt16)))
695         buf->Append(const_cast<System::String*>(Constants::usUShort));
696     else if (typeName->Equals(const_cast<System::String*>(Constants::sInt32)))
697         buf->Append(const_cast<System::String*>(Constants::usLong));
698     else if (typeName->Equals(const_cast<System::String*>(Constants::sUInt32)))
699         buf->Append(const_cast<System::String*>(Constants::usULong));
700     else if (typeName->Equals(const_cast<System::String*>(Constants::sInt64)))
701         buf->Append(const_cast<System::String*>(Constants::usHyper));
702     else if (typeName->Equals(const_cast<System::String*>(Constants::sUInt64)))
703         buf->Append(const_cast<System::String*>(Constants::usUHyper));
704     else if (typeName->Equals(const_cast<System::String*>(Constants::sSingle)))
705         buf->Append(const_cast<System::String*>(Constants::usFloat));
706     else if (typeName->Equals(const_cast<System::String*>(Constants::sDouble)))
707         buf->Append(const_cast<System::String*>(Constants::usDouble));
708     else if (typeName->Equals(const_cast<System::String*>(Constants::sString)))
709         buf->Append(const_cast<System::String*>(Constants::usString));
710     else if (typeName->Equals(const_cast<System::String*>(Constants::sVoid)))
711         buf->Append(const_cast<System::String*>(Constants::usVoid));
712     else if (typeName->Equals(const_cast<System::String*>(Constants::sType)))
713         buf->Append(const_cast<System::String*>(Constants::usType));
714     else if (typeName->Equals(const_cast<System::String*>(Constants::sObject)))
715         buf->Append(const_cast<System::String*>(Constants::usXInterface));
716     else if (typeName->Equals(const_cast<System::String*>(Constants::sAny)))
717         buf->Append(const_cast<System::String*>(Constants::usAny));
718     else
719     {
720         System::String * sName = mapCliPolymorphicName(typeName);
721         int i= sName->IndexOf(L'.');
722         buf->Append(sName->Substring(i + 1));
723     }
724     return mapCliString(buf->ToString());
725 }
726 /** Maps uno types to dot net types.
727  *  If uno_data is null then the type description is converted to System::Type
728  */
729 inline System::String* mapUnoString( rtl_uString const * data)
730 {
731     OSL_ASSERT(data);
732     return new System::String((__wchar_t*) data->buffer, 0, data->length);
733 }
734 
735 OUString mapCliString(System::String const * data)
736 {
737 
738     if (data != NULL)
739     {
740         OSL_ASSERT(sizeof(wchar_t) == sizeof(sal_Unicode));
741         wchar_t const __pin * pdata= PtrToStringChars(data);
742         return OUString(pdata, const_cast<System::String*>(data)->get_Length());
743     }
744     else
745     {
746         return OUString();
747     }
748 }
749 
750 // ToDo convert cli types to expected types, e.g a long to a short where the uno type
751 // is a sal_Int16. This could be necessary if a scripting language (typeless) is used
752 // @param assign the uno_data has to be destructed (in/out args)
753 void Bridge::map_to_uno(void * uno_data, System::Object* cli_data,
754                         typelib_TypeDescriptionReference * type,
755                         bool assign) const
756 {
757     try{
758         switch (type->eTypeClass)
759         {
760         case typelib_TypeClass_VOID:
761             break;
762         case typelib_TypeClass_CHAR:
763         {
764             System::Char aChar= *__try_cast<System::Char*>(cli_data);
765             *(sal_Unicode*) uno_data= aChar;
766             break;
767         }
768         case typelib_TypeClass_BOOLEAN:
769         {
770             System::Boolean aBool= *__try_cast<System::Boolean*>(cli_data);
771             *(sal_Bool*)uno_data= aBool == true ? sal_True : sal_False;
772             break;
773         }
774         case typelib_TypeClass_BYTE:
775         {
776             System::Byte aByte= *__try_cast<System::Byte*>(cli_data);
777             *(sal_Int8*) uno_data= aByte;
778             break;
779         }
780         case typelib_TypeClass_SHORT:
781         {
782             System::Int16 aShort= *__try_cast<System::Int16*>(cli_data);
783             *(sal_Int16*) uno_data= aShort;
784             break;
785         }
786         case typelib_TypeClass_UNSIGNED_SHORT:
787         {
788             System::UInt16 aUShort= *__try_cast<System::UInt16*>(cli_data);
789             *(sal_uInt16*) uno_data= aUShort;
790             break;
791         }
792         case typelib_TypeClass_LONG:
793         {
794             System::Int32 aLong= *__try_cast<System::Int32*>(cli_data);
795             *(sal_Int32*) uno_data= aLong;
796             break;
797         }
798         case typelib_TypeClass_UNSIGNED_LONG:
799         {
800             System::UInt32 aULong= *__try_cast<System::UInt32*>(cli_data);
801             *(sal_uInt32*) uno_data= aULong;
802             break;
803         }
804         case typelib_TypeClass_HYPER:
805         {
806             System::Int64 aHyper= *__try_cast<System::Int64*>(cli_data);
807             *(sal_Int64*) uno_data= aHyper;
808             break;
809         }
810         case typelib_TypeClass_UNSIGNED_HYPER:
811         {
812             System::UInt64 aLong= *__try_cast<System::UInt64*>(cli_data);
813             *(sal_uInt64*) uno_data= aLong;
814             break;
815         }
816         case typelib_TypeClass_FLOAT:
817         {
818             System::Single aFloat= *__try_cast<System::Single*>(cli_data);
819             *(float*) uno_data= aFloat;
820             break;
821         }
822         case typelib_TypeClass_DOUBLE:
823         {
824             System::Double aDouble= *__try_cast<System::Double*>(cli_data);
825             *(double*) uno_data= aDouble;
826             break;
827         }
828         case typelib_TypeClass_STRING:
829         {
830             if (assign && *(rtl_uString**) uno_data)
831                 rtl_uString_release(*(rtl_uString**) uno_data);
832 
833             *(rtl_uString **)uno_data = 0;
834             if (cli_data == NULL)
835             {
836                  rtl_uString_new((rtl_uString**) uno_data);
837             }
838             else
839             {
840                 System::String *s= __try_cast<System::String*>(cli_data);
841                 wchar_t const __pin * pdata= PtrToStringChars(s);
842                 rtl_uString_newFromStr_WithLength( (rtl_uString**) uno_data,
843                                                   pdata, s->get_Length() );
844             }
845             break;
846         }
847         case typelib_TypeClass_TYPE:
848         {
849             typelib_TypeDescriptionReference* td= mapCliType(__try_cast<System::Type*>(
850                                                                     cli_data));
851             if (assign)
852             {
853                 typelib_typedescriptionreference_release(
854                     *(typelib_TypeDescriptionReference **)uno_data );
855             }
856             *(typelib_TypeDescriptionReference **)uno_data = td;
857             break;
858         }
859         case typelib_TypeClass_ANY:
860         {
861             uno_Any * pAny = (uno_Any *)uno_data;
862             if (cli_data == NULL) // null-ref or uninitialized any maps to empty any
863             {
864                 if (assign)
865                     uno_any_destruct( pAny, 0 );
866                 uno_any_construct( pAny, 0, 0, 0 );
867                 break;
868             }
869             uno::Any aAny= *__try_cast<uno::Any*>(cli_data);
870             css::uno::Type  value_td( mapCliType(aAny.Type), SAL_NO_ACQUIRE);
871 
872             if (assign)
873                 uno_any_destruct( pAny, 0 );
874 
875             try
876             {
877                 switch (value_td.getTypeClass())
878                 {
879                 case typelib_TypeClass_VOID:
880                     pAny->pData = &pAny->pReserved;
881                     break;
882                 case typelib_TypeClass_CHAR:
883                     pAny->pData = &pAny->pReserved;
884                     *(sal_Unicode*) &pAny->pReserved = *__try_cast<System::Char*>(aAny.Value);
885                     break;
886                 case typelib_TypeClass_BOOLEAN:
887                     pAny->pData = &pAny->pReserved;
888                     *(sal_Bool *) &pAny->pReserved = *__try_cast<System::Boolean*>(aAny.Value);
889                     break;
890                 case typelib_TypeClass_BYTE:
891                     pAny->pData = &pAny->pReserved;
892                     *(sal_Int8*) &pAny->pReserved =  *__try_cast<System::Byte*>(aAny.Value);
893                     break;
894                 case typelib_TypeClass_SHORT:
895                     pAny->pData = &pAny->pReserved;
896                     *(sal_Int16*) &pAny->pReserved =  *__try_cast<System::Int16*>(aAny.Value);
897                     break;
898                 case typelib_TypeClass_UNSIGNED_SHORT:
899                     pAny->pData = &pAny->pReserved;
900                     *(sal_uInt16*) &pAny->pReserved =  *__try_cast<System::UInt16*>(aAny.Value);
901                     break;
902                 case typelib_TypeClass_LONG:
903                     pAny->pData = &pAny->pReserved;
904                     *(sal_Int32*) &pAny->pReserved =  *__try_cast<System::Int32*>(aAny.Value);
905                     break;
906                 case typelib_TypeClass_UNSIGNED_LONG:
907                     pAny->pData = &pAny->pReserved;
908                     *(sal_uInt32*) &pAny->pReserved =  *__try_cast<System::UInt32*>(aAny.Value);
909                     break;
910                 case typelib_TypeClass_HYPER:
911                     if (sizeof (sal_Int64) <= sizeof (void *))
912                     {
913                         pAny->pData = &pAny->pReserved;
914                         *(sal_Int64*) &pAny->pReserved = *__try_cast<System::Int64*>(aAny.Value);
915                     }
916                     else
917                     {
918                         auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_Int64) ) );
919                         *(sal_Int64 *) mem.get()=  *__try_cast<System::Int64*>(aAny.Value);
920                         pAny->pData = mem.release();
921                     }
922                     break;
923                 case typelib_TypeClass_UNSIGNED_HYPER:
924                     if (sizeof (sal_uInt64) <= sizeof (void *))
925                     {
926                         pAny->pData = &pAny->pReserved;
927                         *(sal_uInt64*) &pAny->pReserved = *__try_cast<System::UInt64*>(aAny.Value);
928                     }
929                     else
930                     {
931                         auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_uInt64) ) );
932                         *(sal_uInt64 *) mem.get()=  *__try_cast<System::UInt64*>(aAny.Value);
933                         pAny->pData = mem.release();
934                     }
935                     break;
936                 case typelib_TypeClass_FLOAT:
937                     if (sizeof (float) <= sizeof (void *))
938                     {
939                         pAny->pData = &pAny->pReserved;
940                         *(float*) &pAny->pReserved = *__try_cast<System::Single*>(aAny.Value);
941                     }
942                     else
943                     {
944                         auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (float) ) );
945                         *(float*) mem.get() = *__try_cast<System::Single*>(aAny.Value);
946                         pAny->pData = mem.release();
947                     }
948                     break;
949                 case typelib_TypeClass_DOUBLE:
950                     if (sizeof (double) <= sizeof (void *))
951                     {
952                         pAny->pData = &pAny->pReserved;
953                         *(double*) &pAny->pReserved= *__try_cast<System::Double*>(aAny.Value);
954                     }
955                     else
956                     {
957                         auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (double) ) );
958                         *(double*) mem.get()= *__try_cast<System::Double*>(aAny.Value);
959                         pAny->pData= mem.release();
960                     }
961                     break;
962                 case typelib_TypeClass_STRING: // anies often contain strings; copy string directly
963                 {
964                     pAny->pData= &pAny->pReserved;
965                     OUString _s = mapCliString(static_cast<System::String*>(aAny.Value));
966                     pAny->pReserved= _s.pData;
967                     rtl_uString_acquire(_s.pData);
968                     break;
969                 }
970                 case typelib_TypeClass_TYPE:
971                 case typelib_TypeClass_ENUM:  //ToDo copy enum direct
972                 case typelib_TypeClass_SEQUENCE:
973                 case typelib_TypeClass_INTERFACE:
974                     pAny->pData = &pAny->pReserved;
975                     pAny->pReserved = 0;
976                     map_to_uno(
977                         &pAny->pReserved, aAny.Value, value_td.getTypeLibType(),
978                                                   false /* no assign */);
979                     break;
980                 case typelib_TypeClass_STRUCT:
981                 case typelib_TypeClass_EXCEPTION:
982                 {
983                     css::uno::Type anyType(value_td);
984                     typelib_TypeDescription* td= NULL;
985                     anyType.getDescription(&td);
986                     auto_ptr< rtl_mem > mem(rtl_mem::allocate(td->nSize));
987                     typelib_typedescription_release(td);
988                     map_to_uno(
989                         mem.get(), aAny.Value, value_td.getTypeLibType(),
990                         false /* no assign */);
991                     pAny->pData = mem.release();
992                     break;
993                 }
994                 default:
995                 {
996                     OUStringBuffer buf( 128 );
997                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
998                     buf.append(value_td.getTypeName());
999                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported value type of any!") );
1000                     throw BridgeRuntimeError( buf.makeStringAndClear() );
1001                 }
1002                 }
1003             }
1004             catch(System::InvalidCastException* )
1005             {
1006 // ToDo check this
1007                 if (assign)
1008                     uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
1009                 OUStringBuffer buf( 256 );
1010                 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():Any") );
1011                 buf.append(value_td.getTypeName());
1012                 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("]The Any type "));
1013                 buf.append(value_td.getTypeName());
1014                 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" does not correspont  "
1015                                                             "to its value type: ") );
1016                 if(aAny.Value != NULL)
1017                 {
1018                     css::uno::Type td(mapCliType(aAny.Value->GetType()), SAL_NO_ACQUIRE);
1019                     buf.append(td.getTypeName());
1020                 }
1021                 if (assign)
1022                     uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
1023                 throw BridgeRuntimeError( buf.makeStringAndClear() );
1024             }
1025             catch (BridgeRuntimeError& )
1026             {
1027                 if (assign)
1028                     uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
1029                 throw;
1030             }
1031             catch (...)
1032             {
1033                 if (assign)
1034                     uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
1035                 throw;
1036             }
1037 
1038             pAny->pType = value_td.getTypeLibType();
1039             typelib_typedescriptionreference_acquire(pAny->pType);
1040             break;
1041         }
1042         case typelib_TypeClass_ENUM:
1043         {
1044             // InvalidCastException is caught at the end of this method
1045             System::Int32 aEnum= System::Convert::ToInt32((cli_data));
1046             *(sal_Int32*) uno_data = aEnum;
1047             break;
1048         }
1049         case typelib_TypeClass_STRUCT:
1050         case typelib_TypeClass_EXCEPTION:
1051         {
1052             css::uno::TypeDescription td(type);
1053             typelib_CompoundTypeDescription * comp_td =
1054                 (typelib_CompoundTypeDescription*) td.get();
1055 
1056             typelib_StructTypeDescription * struct_td = NULL;
1057             if (type->eTypeClass == typelib_TypeClass_STRUCT)
1058                 struct_td = (typelib_StructTypeDescription*) td.get();
1059 
1060             if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
1061                 ::typelib_typedescription_complete(
1062                     (typelib_TypeDescription**) & comp_td );
1063 
1064             sal_Int32 nMembers = comp_td->nMembers;
1065             boolean bException= false;
1066             System::Type* cliType = NULL;
1067             if (cli_data)
1068                 cliType = cli_data->GetType();
1069 
1070             if (0 != comp_td->pBaseTypeDescription)
1071             {
1072                 map_to_uno(
1073                     uno_data, cli_data,
1074                     ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef,
1075                     assign);
1076             }
1077             sal_Int32 nPos = 0;
1078             try
1079             {
1080                 typelib_TypeDescriptionReference * member_type= NULL;
1081 
1082 				rtl::OUString usUnoException(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Exception"));
1083                 for (; nPos < nMembers; ++nPos)
1084                 {
1085                     member_type= comp_td->ppTypeRefs[nPos];
1086 #if OSL_DEBUG_LEVEL >= 2
1087                     System::String* __s;
1088                     sr::FieldInfo* arFields[];
1089                     __s = mapUnoString(comp_td->ppMemberNames[nPos]);
1090                     arFields = cliType != NULL ? cliType->GetFields() : NULL;
1091 #endif
1092                     System::Object* val= NULL;
1093                     if (cli_data != NULL)
1094                     {
1095                         sr::FieldInfo* aField= cliType->GetField(
1096                             mapUnoString(comp_td->ppMemberNames[nPos]));
1097                         // special case for Exception.Message property
1098                         // The com.sun.star.uno.Exception.Message field is mapped to the
1099                         // System.Exception property. Type.GetField("Message") returns null
1100                         if ( ! aField && usUnoException.equals(td.get()->pTypeName))
1101                         {// get Exception.Message property
1102 							rtl::OUString usMessageMember(RTL_CONSTASCII_USTRINGPARAM("Message"));
1103                             if (usMessageMember.equals(comp_td->ppMemberNames[nPos]))
1104                             {
1105                                 sr::PropertyInfo* pi= cliType->GetProperty(
1106                                     mapUnoString(comp_td->ppMemberNames[nPos]));
1107                                 val= pi->GetValue(cli_data, NULL);
1108                             }
1109                             else
1110                             {
1111                                 OUStringBuffer buf(512);
1112                                 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("[map_to_uno(): Member: "));
1113                                 buf.append(comp_td->ppMemberNames[nPos]);
1114                                 throw BridgeRuntimeError(buf.makeStringAndClear());
1115                             }
1116                         }
1117                         else
1118                         {
1119                             val= aField->GetValue(cli_data);
1120                         }
1121                     }
1122                     void * p = (char *) uno_data + comp_td->pMemberOffsets[ nPos ];
1123                     //When using polymorphic structs then the parameterized members can be null.
1124                     //Then we set a default value.
1125                     bool bDefault = ((struct_td != NULL
1126                                      && struct_td->pParameterizedTypes != NULL
1127                                      && struct_td->pParameterizedTypes[nPos] == sal_True
1128                                       && val == NULL)
1129                                      || cli_data == NULL) ? true : false;
1130                     switch (member_type->eTypeClass)
1131                     {
1132                     case typelib_TypeClass_CHAR:
1133                         if (bDefault)
1134                             *(sal_Unicode*) p = 0;
1135                         else
1136                             *(sal_Unicode*) p = *__try_cast<System::Char*>(val);
1137                         break;
1138                     case typelib_TypeClass_BOOLEAN:
1139                         if (bDefault)
1140                             *(sal_Bool*) p = sal_False;
1141                         else
1142                             *(sal_Bool*) p = *__try_cast<System::Boolean*>(val);
1143                         break;
1144                     case typelib_TypeClass_BYTE:
1145                         if (bDefault)
1146                             *(sal_Int8*) p = 0;
1147                         else
1148                             *(sal_Int8*) p = *__try_cast<System::Byte*>(val);
1149                         break;
1150                     case typelib_TypeClass_SHORT:
1151                         if (bDefault)
1152                             *(sal_Int16*) p = 0;
1153                         else
1154                             *(sal_Int16*) p = *__try_cast<System::Int16*>(val);
1155                         break;
1156                     case typelib_TypeClass_UNSIGNED_SHORT:
1157                         if (bDefault)
1158                             *(sal_uInt16*) p = 0;
1159                         else
1160                             *(sal_uInt16*) p = *__try_cast<System::UInt16*>(val);
1161                         break;
1162                     case typelib_TypeClass_LONG:
1163                         if (bDefault)
1164                             *(sal_Int32*) p = 0;
1165                         else
1166                             *(sal_Int32*) p = *__try_cast<System::Int32*>(val);
1167                         break;
1168                     case typelib_TypeClass_UNSIGNED_LONG:
1169                         if (bDefault)
1170                             *(sal_uInt32*) p = 0;
1171                         else
1172                             *(sal_uInt32*) p = *__try_cast<System::UInt32*>(val);
1173                         break;
1174                     case typelib_TypeClass_HYPER:
1175                         if (bDefault)
1176                             *(sal_Int64*) p = 0;
1177                         else
1178                             *(sal_Int64*) p = *__try_cast<System::Int64*>(val);
1179                         break;
1180                     case typelib_TypeClass_UNSIGNED_HYPER:
1181                         if (bDefault)
1182                             *(sal_uInt64*) p = 0;
1183                         else
1184                             *(sal_uInt64*) p= *__try_cast<System::UInt64*>(val);
1185                         break;
1186                     case typelib_TypeClass_FLOAT:
1187                         if (bDefault)
1188                             *(float*) p = 0.;
1189                         else
1190                             *(float*) p = *__try_cast<System::Single*>(val);
1191                         break;
1192                     case typelib_TypeClass_DOUBLE:
1193                         if (bDefault)
1194                             *(double*) p = 0.;
1195                         else
1196                             *(double*) p = *__try_cast<System::Double*>(val);
1197                         break;
1198                     default:
1199                     {   // ToDo enum, should be converted here
1200                          map_to_uno(p, val, member_type, assign);
1201                         break;
1202                     }
1203                     }
1204                 }
1205             }
1206             catch (BridgeRuntimeError& e)
1207             {
1208                 bException= true;
1209                 OUStringBuffer buf(512);
1210                 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("[map_to_uno():"));
1211                 if (cliType)
1212                 {
1213                     buf.append(mapCliString(cliType->get_FullName()));
1214                     buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("."));
1215                     buf.append(comp_td->ppMemberNames[nPos]);
1216                     buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" "));
1217                 }
1218                 buf.append(e.m_message);
1219                 throw BridgeRuntimeError(buf.makeStringAndClear());
1220             }
1221             catch (System::InvalidCastException* )
1222             {
1223                 bException= true;
1224                 OUStringBuffer buf( 256 );
1225                 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
1226                 if (cliType)
1227                 {
1228                     buf.append(mapCliString(cliType->get_FullName()));
1229                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("."));
1230                     buf.append(comp_td->ppMemberNames[nPos]);
1231                 }
1232                 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] Value has not the required type."));
1233                 throw BridgeRuntimeError(buf.makeStringAndClear());
1234             }
1235             catch (...)
1236             {
1237                 OSL_ASSERT(0);
1238                 bException= true;
1239                 throw;
1240             }
1241             __finally
1242             {
1243                 if (bException && !assign) // if assign then caller cleans up
1244                 {
1245                     // cleanup the members which we have converted so far
1246                     for ( sal_Int32 nCleanup = 0; nCleanup < nPos; ++nCleanup )
1247                     {
1248                         uno_type_destructData(
1249                             uno_data, comp_td->ppTypeRefs[ nCleanup ], 0 );
1250                     }
1251                     if (0 != comp_td->pBaseTypeDescription)
1252                     {
1253                         uno_destructData(
1254                             uno_data, (typelib_TypeDescription *)comp_td->pBaseTypeDescription, 0 );
1255                     }
1256                 }
1257             }
1258             break;
1259         }
1260         case typelib_TypeClass_SEQUENCE:
1261         {
1262             TypeDescr td( type );
1263             typelib_TypeDescriptionReference * element_type =
1264                 ((typelib_IndirectTypeDescription *)td.get())->pType;
1265 
1266             auto_ptr< rtl_mem > seq;
1267 
1268             System::Array* ar = NULL;
1269             if (cli_data != NULL)
1270             {
1271                 ar = __try_cast<System::Array*>(cli_data);
1272                 sal_Int32 nElements = ar->GetLength(0);
1273 
1274                 try
1275                 {
1276                     switch (element_type->eTypeClass)
1277                     {
1278                     case typelib_TypeClass_CHAR:
1279                         seq = seq_allocate(nElements, sizeof (sal_Unicode));
1280                         sri::Marshal::Copy(__try_cast<System::Char[]>(cli_data), 0,
1281                                            & ((uno_Sequence*) seq.get())->elements, nElements);
1282                         break;
1283                     case typelib_TypeClass_BOOLEAN:
1284                         seq = seq_allocate(nElements, sizeof (sal_Bool));
1285                         sri::Marshal::Copy(__try_cast<System::Boolean[]>(cli_data), 0,
1286                                            & ((uno_Sequence*) seq.get())->elements, nElements);
1287                         break;
1288                     case typelib_TypeClass_BYTE:
1289                         seq = seq_allocate( nElements, sizeof (sal_Int8) );
1290                     sri::Marshal::Copy(__try_cast<System::Byte[]>(cli_data), 0,
1291                                        & ((uno_Sequence*) seq.get())->elements, nElements);
1292                     break;
1293                     case typelib_TypeClass_SHORT:
1294                         seq = seq_allocate(nElements, sizeof (sal_Int16));
1295                         sri::Marshal::Copy(__try_cast<System::Int16[]>(cli_data), 0,
1296                                            & ((uno_Sequence*) seq.get())->elements, nElements);
1297                         break;
1298                     case typelib_TypeClass_UNSIGNED_SHORT:
1299                         seq = seq_allocate( nElements, sizeof (sal_uInt16) );
1300                         sri::Marshal::Copy(static_cast<System::Int16[]>(
1301                                                __try_cast<System::UInt16[]>(cli_data)), 0,
1302                                            & ((uno_Sequence*) seq.get())->elements, nElements);
1303                         break;
1304                     case typelib_TypeClass_LONG:
1305                         seq = seq_allocate(nElements, sizeof (sal_Int32));
1306                         sri::Marshal::Copy(__try_cast<System::Int32[]>(cli_data), 0,
1307                                            & ((uno_Sequence*) seq.get())->elements, nElements);
1308                         break;
1309                     case typelib_TypeClass_UNSIGNED_LONG:
1310                         seq = seq_allocate( nElements, sizeof (sal_uInt32) );
1311                         sri::Marshal::Copy(static_cast<System::Int32[]>(
1312                                                __try_cast<System::UInt32[]>(cli_data)), 0,
1313                                            & ((uno_Sequence*) seq.get())->elements, nElements);
1314                         break;
1315                     case typelib_TypeClass_HYPER:
1316                         seq = seq_allocate(nElements, sizeof (sal_Int64));
1317                         sri::Marshal::Copy(__try_cast<System::Int64[]>(cli_data), 0,
1318                                            & ((uno_Sequence*) seq.get())->elements, nElements);
1319                         break;
1320                     case typelib_TypeClass_UNSIGNED_HYPER:
1321                         seq = seq_allocate(nElements, sizeof (sal_uInt64));
1322                         sri::Marshal::Copy(static_cast<System::Int64[]>(
1323                                                __try_cast<System::UInt64[]>(cli_data)), 0,
1324                                            & ((uno_Sequence*) seq.get())->elements, nElements);
1325                         break;
1326                     case typelib_TypeClass_FLOAT:
1327                         seq = seq_allocate(nElements, sizeof (float));
1328                         sri::Marshal::Copy(__try_cast<System::Single[]>(cli_data), 0,
1329                                            & ((uno_Sequence*) seq.get())->elements, nElements);
1330                         break;
1331                     case typelib_TypeClass_DOUBLE:
1332                         seq = seq_allocate(nElements, sizeof (double));
1333                         sri::Marshal::Copy(__try_cast<System::Double[]>(cli_data), 0,
1334                                            & ((uno_Sequence*) seq.get())->elements, nElements);
1335                         break;
1336                     case typelib_TypeClass_STRING:
1337                     {
1338                         seq = seq_allocate(nElements, sizeof (rtl_uString*));
1339                         System::String* arStr[]= __try_cast<System::String*[]>(cli_data);
1340                         for (int i= 0; i < nElements; i++)
1341                         {
1342                             wchar_t const __pin * pdata= PtrToStringChars(arStr[i]);
1343                             rtl_uString** pStr=  & ((rtl_uString**) &
1344                                                     ((uno_Sequence*) seq.get())->elements)[i];
1345                             *pStr= NULL;
1346                             rtl_uString_newFromStr_WithLength( pStr, pdata,
1347                                                                arStr[i]->get_Length());
1348                         }
1349                         break;
1350                     }
1351                     case typelib_TypeClass_ENUM:
1352                         seq = seq_allocate(nElements, sizeof (sal_Int32));
1353                         for (int i= 0; i < nElements; i++)
1354                         {
1355                             ((sal_Int32*) &((uno_Sequence*) seq.get())->elements)[i]=
1356                                 System::Convert::ToInt32(ar->GetValue(i));
1357                         }
1358                         break;
1359                     case typelib_TypeClass_TYPE:
1360                     case typelib_TypeClass_ANY:
1361                     case typelib_TypeClass_STRUCT:
1362                     case typelib_TypeClass_EXCEPTION:
1363                     case typelib_TypeClass_SEQUENCE:
1364                     case typelib_TypeClass_INTERFACE:
1365                     {
1366                         TypeDescr element_td( element_type );
1367                         seq = seq_allocate( nElements, element_td.get()->nSize );
1368 
1369                         for (sal_Int32 nPos = 0; nPos < nElements; ++nPos)
1370                         {
1371                             try
1372                             {
1373                                 void * p= ((uno_Sequence *) seq.get())->elements +
1374                                     (nPos * element_td.get()->nSize);
1375                                 System::Object* elemData= dynamic_cast<System::Array*>(cli_data)->GetValue(nPos);
1376                                 map_to_uno(
1377                                     p, elemData, element_td.get()->pWeakRef,
1378                                     false /* no assign */);
1379                             }
1380                             catch (...)
1381                             {
1382                                 // cleanup
1383                                 for ( sal_Int32 nCleanPos = 0; nCleanPos < nPos; ++nCleanPos )
1384                                 {
1385                                     void * p =
1386                                         ((uno_Sequence *)seq.get())->elements +
1387                                         (nCleanPos * element_td.get()->nSize);
1388                                     uno_destructData( p, element_td.get(), 0 );
1389                                 }
1390                                 throw;
1391                             }
1392                         }
1393                         break;
1394                     }
1395                     default:
1396                     {
1397                         OUStringBuffer buf( 128 );
1398                         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
1399                         buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) );
1400                         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported sequence element type: ") );
1401                         buf.append( *reinterpret_cast< OUString const * >( &element_type->pTypeName ) );
1402                         throw BridgeRuntimeError( buf.makeStringAndClear() );
1403                     }
1404                     }
1405                 }
1406                 catch (BridgeRuntimeError& e)
1407                 {
1408                     OUStringBuffer buf( 128 );
1409                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
1410                     buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ));
1411                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] conversion failed\n "));
1412                     buf.append(e.m_message);
1413                     throw BridgeRuntimeError(buf.makeStringAndClear());
1414                 }
1415                 catch (System::InvalidCastException* )
1416                 {
1417                     // Ok, checked
1418                     OUStringBuffer buf( 128 );
1419                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
1420                     buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName) );
1421                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] could not convert sequence element type: ") );
1422                     buf.append( *reinterpret_cast< OUString const * >( &element_type->pTypeName ) );
1423                     throw BridgeRuntimeError( buf.makeStringAndClear() );
1424                 }
1425                 catch (...)
1426                 {
1427                     OSL_ASSERT(0);
1428                     throw;
1429                 }
1430                 __finally
1431                     {
1432                         if (assign)
1433                             uno_destructData( uno_data, td.get(), 0 );
1434                     }
1435             }
1436             else
1437             {
1438                 seq = seq_allocate(0, sizeof (sal_Int32));
1439             }
1440             *(uno_Sequence **)uno_data = (uno_Sequence *)seq.release();
1441             break;
1442         }
1443         case typelib_TypeClass_INTERFACE:
1444         {
1445             if (assign)
1446             {
1447                 uno_Interface * p = *(uno_Interface **)uno_data;
1448                 if (0 != p)
1449                     (*p->release)( p );
1450             }
1451             if (0 == cli_data) // null-ref
1452             {
1453                 *(uno_Interface **)uno_data = 0;
1454             }
1455             else
1456             {
1457                 TypeDescr td( type );
1458                 uno_Interface * pUnoI = map_cli2uno(cli_data, td.get());
1459                 *(uno_Interface **)uno_data = pUnoI;
1460             }
1461             break;
1462         }
1463         default:
1464         {
1465             //ToDo check
1466             OUStringBuffer buf( 128 );
1467             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
1468             buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) );
1469             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported type!") );
1470             throw BridgeRuntimeError( buf.makeStringAndClear() );
1471         }
1472         }
1473     }
1474     // BridgeRuntimeError are allowed to be thrown
1475     catch (System::InvalidCastException* )
1476     {
1477         //ToDo check
1478         OUStringBuffer buf( 128 );
1479         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
1480         buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) );
1481         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] could not convert type!") );
1482         throw BridgeRuntimeError( buf.makeStringAndClear() );
1483     }
1484     catch (System::NullReferenceException * e)
1485     {
1486         OUStringBuffer buf(512);
1487         buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(
1488                              "[map_to_uno()] Illegal null reference passed!\n"));
1489         buf.append(mapCliString(e->get_StackTrace()));
1490         throw BridgeRuntimeError( buf.makeStringAndClear() );
1491     }
1492     catch (BridgeRuntimeError& )
1493     {
1494         throw;
1495     }
1496     catch (...)
1497     {
1498         OSL_ASSERT(0);
1499         throw;
1500     }
1501 
1502 }
1503 
1504 /**
1505    @param info
1506        The expected target type. Currently info is provdided when this method is called
1507        to convert the in/out and out parameters of a call from cli to uno. Then info
1508        is always a byref type, e.g. "System.String&". info is used for Any and Enum conversion.
1509    @param bDontCreateObj
1510        false - a new object is created which holds the mapped uno value and is assigned to
1511        cli_data.
1512        true - cli_data already contains the newly constructed object. This is the case if
1513        a struct is converted then on the first call to map_to_cli the new object is created.
1514        If the struct inherits another struct then this function is called recursivly while the
1515        newly created object is passed in cli_data.
1516  */
1517 void Bridge::map_to_cli(
1518     System::Object* *cli_data, void const * uno_data,
1519     typelib_TypeDescriptionReference * type, System::Type* info,
1520     bool bDontCreateObj) const
1521 {
1522     switch (type->eTypeClass)
1523     {
1524     case typelib_TypeClass_CHAR:
1525         *cli_data= __box(*(__wchar_t const*)uno_data);
1526         break;
1527     case typelib_TypeClass_BOOLEAN:
1528         *cli_data = __box((*(bool const*)uno_data) == sal_True ? true : false);
1529         break;
1530     case typelib_TypeClass_BYTE:
1531         *cli_data = __box(*(unsigned char const*) uno_data);
1532         break;
1533     case typelib_TypeClass_SHORT:
1534         *cli_data= __box(*(short const*) uno_data);
1535         break;
1536     case typelib_TypeClass_UNSIGNED_SHORT:
1537         *cli_data= __box(*(unsigned short const*) uno_data);
1538         break;
1539     case typelib_TypeClass_LONG:
1540         *cli_data= __box(*(int const*) uno_data);
1541         break;
1542     case typelib_TypeClass_UNSIGNED_LONG:
1543         *cli_data= __box(*(unsigned int const*) uno_data);
1544         break;
1545     case typelib_TypeClass_HYPER:
1546         *cli_data= __box(*(__int64 const*) uno_data);
1547         break;
1548     case typelib_TypeClass_UNSIGNED_HYPER:
1549         *cli_data= __box(*(unsigned __int64 const*) uno_data);
1550         break;
1551     case typelib_TypeClass_FLOAT:
1552         *cli_data= __box(*(float const*) uno_data);
1553         break;
1554     case typelib_TypeClass_DOUBLE:
1555         *cli_data= __box(*(double const*) uno_data);
1556         break;
1557     case typelib_TypeClass_STRING:
1558     {
1559         rtl_uString const* sVal= NULL;
1560         sVal= *(rtl_uString* const*) uno_data;
1561         *cli_data= new System::String((__wchar_t*) sVal->buffer,0, sVal->length);
1562         break;
1563     }
1564     case typelib_TypeClass_TYPE:
1565      {
1566          *cli_data= mapUnoType( *(typelib_TypeDescriptionReference * const *)uno_data );
1567          break;
1568      }
1569     case typelib_TypeClass_ANY:
1570     {
1571         uno_Any const * pAny = (uno_Any const *)uno_data;
1572         if (typelib_TypeClass_VOID != pAny->pType->eTypeClass)
1573         {
1574             System::Object* objCli= NULL;
1575             map_to_cli(
1576                 &objCli, pAny->pData, pAny->pType, 0,
1577                 false);
1578 
1579             uno::Any anyVal(mapUnoType(pAny->pType), objCli);
1580             *cli_data= __box(anyVal);
1581         }
1582         else
1583         { // void any
1584             *cli_data= __box(uno::Any::VOID);
1585         }
1586         break;
1587     }
1588     case typelib_TypeClass_ENUM:
1589      {
1590          if (info != NULL)
1591          {
1592              OSL_ASSERT(info->get_IsByRef());
1593              info= info->GetElementType();
1594              *cli_data= System::Enum::ToObject(info, *(System::Int32*) uno_data);
1595          }
1596          else
1597              *cli_data= System::Enum::ToObject(
1598                  mapUnoType(type), *(System::Int32*) uno_data);
1599         break;
1600     }
1601     case typelib_TypeClass_STRUCT:
1602     case typelib_TypeClass_EXCEPTION:
1603     {
1604         TypeDescr td( type );
1605         typelib_CompoundTypeDescription * comp_td =
1606             (typelib_CompoundTypeDescription *) td.get();
1607         if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
1608                 ::typelib_typedescription_complete(
1609                     (typelib_TypeDescription**) & comp_td );
1610 
1611 
1612         //create the type
1613         System::Type* cliType= loadCliType(td.get()->pTypeName);
1614         //detect if we recursivly convert inherited structures
1615         //If this point is reached because of a recursive call during convering a
1616         //struct then we must not create a new object rather we use the one in
1617         // cli_data argument.
1618         System::Object* cliObj;
1619         if (bDontCreateObj)
1620             cliObj = *cli_data; // recursive call
1621         else
1622         {
1623             //Special handling for Exception conversion. We must call constructor System::Exception
1624             //to pass the message string
1625             if (__typeof(ucss::uno::Exception)->IsAssignableFrom(cliType))
1626             {
1627                 //We need to get the Message field. Therefore we must obtain the offset from
1628                 //the typedescription. The base interface of all exceptions is
1629                 //com::sun::star::uno::Exception which contains the message
1630                 typelib_CompoundTypeDescription* pCTD = comp_td;
1631                 while (pCTD->pBaseTypeDescription)
1632                     pCTD = pCTD->pBaseTypeDescription;
1633                 int nPos = -1;
1634 
1635 				rtl::OUString usMessageMember(RTL_CONSTASCII_USTRINGPARAM("Message"));
1636                 for (int i = 0; i < pCTD->nMembers; i ++)
1637                 {
1638 #if OSL_DEBUG_LEVEL >= 2
1639                     System::String* sMember;
1640                     sMember = mapUnoString(pCTD->ppMemberNames[i]);
1641 #endif
1642                     if (usMessageMember.equals(pCTD->ppMemberNames[i]))
1643                     {
1644                         nPos = i;
1645                         break;
1646                     }
1647                 }
1648                 OSL_ASSERT (nPos != -1);
1649                 int offset = pCTD->pMemberOffsets[nPos];
1650                 //With the offset within the exception we can get the message string
1651                 System::String* sMessage = mapUnoString(*(rtl_uString**)
1652                                                         ((char*) uno_data + offset));
1653                 //We need to find a constructor for the exception that takes the message string
1654                 //We assume that the first argument is the message string
1655                 sr::ConstructorInfo* arCtorInfo[] = cliType->GetConstructors();
1656                 sr::ConstructorInfo* ctorInfo = NULL;
1657                 int numCtors = arCtorInfo->get_Length();
1658                 //Constructor must at least have 2 params for the base
1659                 //unoidl.com.sun.star.uno.Exception (String, Object);
1660                 sr::ParameterInfo * arParamInfo[];
1661                 for (int i = 0; i < numCtors; i++)
1662                 {
1663                     arParamInfo = arCtorInfo[i]->GetParameters();
1664                     if (arParamInfo->get_Length() < 2)
1665                         continue;
1666                     ctorInfo = arCtorInfo[i];
1667                     break;
1668                 }
1669                 OSL_ASSERT(arParamInfo[0]->get_ParameterType()->Equals(__typeof(System::String))
1670                     && arParamInfo[1]->get_ParameterType()->Equals(__typeof(System::Object))
1671                     && arParamInfo[0]->get_Position() == 0
1672                     && arParamInfo[1]->get_Position() == 1);
1673                 //Prepare parameters for constructor
1674                 int numArgs = arParamInfo->get_Length();
1675                 System::Object * args[] = new System::Object*[numArgs];
1676                 //only initialize the first argument with the message
1677                 args[0] = sMessage;
1678                 cliObj = ctorInfo->Invoke(args);
1679             }
1680             else
1681                 cliObj = System::Activator::CreateInstance(cliType);
1682         }
1683         sal_Int32 * pMemberOffsets = comp_td->pMemberOffsets;
1684 
1685         if (comp_td->pBaseTypeDescription)
1686         {
1687             //convert inherited struct
1688             //cliObj is passed inout (args in_param, out_param are true), hence the passed
1689             // cliObj is used by the callee instead of a newly created struct
1690             map_to_cli(
1691                 &cliObj, uno_data,
1692                 ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef, 0,
1693                 true);
1694         }
1695 		rtl::OUString usUnoException(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Exception"));
1696         for (sal_Int32 nPos = comp_td->nMembers; nPos--; )
1697         {
1698             typelib_TypeDescriptionReference * member_type = comp_td->ppTypeRefs[ nPos ];
1699             System::String* sMemberName= mapUnoString(comp_td->ppMemberNames[nPos]);
1700             sr::FieldInfo* aField= cliType->GetField(sMemberName);
1701             // special case for Exception.Message. The field has already been
1702             // set while constructing cli object
1703             if ( ! aField && usUnoException.equals(td.get()->pTypeName))
1704             {
1705                 continue;
1706             }
1707             void const * p = (char const *)uno_data + pMemberOffsets[ nPos ];
1708             switch (member_type->eTypeClass)
1709             {
1710             case typelib_TypeClass_CHAR:
1711                 aField->SetValue(cliObj, __box(*(System::Char*) p));
1712                 break;
1713             case typelib_TypeClass_BOOLEAN:
1714                 aField->SetValue(cliObj, __box(*(System::Boolean*) p));
1715                 break;
1716             case typelib_TypeClass_BYTE:
1717                 aField->SetValue(cliObj, __box(*(System::Byte*) p));
1718                 break;
1719             case typelib_TypeClass_SHORT:
1720                 aField->SetValue(cliObj, __box(*(System::Int16*) p));
1721                 break;
1722             case typelib_TypeClass_UNSIGNED_SHORT:
1723                 aField->SetValue(cliObj, __box(*(System::UInt16*) p));
1724                 break;
1725             case typelib_TypeClass_LONG:
1726                 aField->SetValue(cliObj, __box(*(System::Int32*) p));
1727                 break;
1728             case typelib_TypeClass_UNSIGNED_LONG:
1729                 aField->SetValue(cliObj, __box(*(System::UInt32*) p));
1730                 break;
1731             case typelib_TypeClass_HYPER:
1732                 aField->SetValue(cliObj, __box(*(System::Int64*) p));
1733                 break;
1734             case typelib_TypeClass_UNSIGNED_HYPER:
1735                 aField->SetValue(cliObj, __box(*(System::UInt64*) p));
1736                 break;
1737             case typelib_TypeClass_FLOAT:
1738                 aField->SetValue(cliObj, __box(*(System::Single*) p));
1739                 break;
1740             case typelib_TypeClass_DOUBLE:
1741                 aField->SetValue(cliObj, __box(*(System::Double*) p));
1742                 break;
1743             default:
1744             {
1745                 System::Object* cli_val;
1746                 map_to_cli(
1747                     &cli_val, p, member_type, 0,
1748                     false);
1749                 aField->SetValue(cliObj, cli_val);
1750                 break;
1751             }
1752             }
1753         }
1754         *cli_data= cliObj;
1755         break;
1756     }
1757     case typelib_TypeClass_SEQUENCE:
1758     {
1759         sal_Int32 nElements;
1760         uno_Sequence const * seq = 0;
1761         seq = *(uno_Sequence * const *)uno_data;
1762         nElements = seq->nElements;
1763 
1764         TypeDescr td( type );
1765         typelib_TypeDescriptionReference * element_type =
1766             ((typelib_IndirectTypeDescription *)td.get())->pType;
1767 
1768         switch (element_type->eTypeClass)
1769         {
1770         case typelib_TypeClass_CHAR:
1771         {
1772             System::Char arChar[]= new System::Char[nElements];
1773             sri::Marshal::Copy( (void*) &seq->elements, arChar, 0, nElements);
1774             *cli_data= arChar;
1775             break;
1776         }
1777         case typelib_TypeClass_BOOLEAN:
1778         {
1779             System::Boolean arBool[]= new System::Boolean[nElements];
1780             sri::Marshal::Copy( (void*) &seq->elements, arBool, 0, nElements);
1781             *cli_data= arBool;
1782             break;
1783         }
1784         case typelib_TypeClass_BYTE:
1785         {
1786             System::Byte arByte[]= new System::Byte[nElements];
1787             sri::Marshal::Copy( (void*) &seq->elements, arByte, 0, nElements);
1788             *cli_data= arByte;
1789             break;
1790         }
1791         case typelib_TypeClass_SHORT:
1792         {
1793             System::Int16 arShort[]= new System::Int16[nElements];
1794             sri::Marshal::Copy( (void*) &seq->elements, arShort, 0, nElements);
1795             *cli_data= arShort;
1796             break;
1797         }
1798         case typelib_TypeClass_UNSIGNED_SHORT:
1799         {
1800             System::UInt16 arUInt16[]= new System::UInt16[nElements];
1801             sri::Marshal::Copy( (void*) &seq->elements, static_cast<System::Int16[]>(arUInt16),
1802                                 0, nElements);
1803             *cli_data= arUInt16;
1804             break;
1805         }
1806         case typelib_TypeClass_LONG:
1807         {
1808             System::Int32 arInt32[]= new System::Int32[nElements];
1809             sri::Marshal::Copy( (void*) &seq->elements, arInt32, 0, nElements);
1810             *cli_data= arInt32;
1811             break;
1812         }
1813         case typelib_TypeClass_UNSIGNED_LONG:
1814         {
1815             System::UInt32 arUInt32[]= new System::UInt32[nElements];
1816             sri::Marshal::Copy( (void*) &seq->elements, static_cast<System::Int32[]>(arUInt32),
1817                                 0, nElements);
1818             *cli_data= arUInt32;
1819             break;
1820         }
1821         case typelib_TypeClass_HYPER:
1822         {
1823             System::Int64 arInt64[]= new System::Int64[nElements];
1824             sri::Marshal::Copy( (void*) &seq->elements, arInt64, 0, nElements);
1825             *cli_data= arInt64;
1826             break;
1827         }
1828         case typelib_TypeClass_UNSIGNED_HYPER:
1829         {
1830             System::UInt64 arUInt64[]= new System::UInt64[nElements];
1831             sri::Marshal::Copy( (void*) &seq->elements, arUInt64, 0, nElements);
1832             *cli_data= arUInt64;
1833             break;
1834         }
1835         case typelib_TypeClass_FLOAT:
1836         {
1837             System::Single arSingle[]= new System::Single[nElements];
1838             sri::Marshal::Copy( (void*) &seq->elements, arSingle, 0, nElements);
1839             *cli_data= arSingle;
1840             break;
1841         }
1842         case typelib_TypeClass_DOUBLE:
1843         {
1844             System::Double arDouble[]= new System::Double[nElements];
1845             sri::Marshal::Copy( (void*) &seq->elements, arDouble, 0, nElements);
1846             *cli_data= arDouble;
1847             break;
1848         }
1849         case typelib_TypeClass_STRING:
1850         {
1851             System::String* arString[]= new System::String*[nElements];
1852             for (int i= 0; i < nElements; i++)
1853             {
1854                 rtl_uString *aStr= ((rtl_uString**)(&seq->elements))[i];
1855                 arString[i]= new System::String( (__wchar_t *) &aStr->buffer, 0, aStr->length);
1856             }
1857             *cli_data= arString;
1858             break;
1859         }
1860         case typelib_TypeClass_TYPE:
1861         {
1862             System::Type* arType[]= new System::Type*[nElements];
1863             for (int i= 0; i < nElements; i++)
1864             {
1865                 arType[i]=
1866                     mapUnoType( ((typelib_TypeDescriptionReference**) seq->elements)[i]);
1867             }
1868             *cli_data= arType;
1869             break;
1870         }
1871         case typelib_TypeClass_ANY:
1872         {
1873             uno::Any arCli[]= new uno::Any[nElements];
1874             uno_Any const * p = (uno_Any const *)seq->elements;
1875             for (sal_Int32 nPos = 0; nPos < nElements; ++nPos )
1876             {
1877 				System::Object* cli_obj = NULL;
1878                 map_to_cli(
1879                     &cli_obj, &p[ nPos ], element_type, 0, false);
1880                 arCli[nPos]= *__try_cast<__box uno::Any*>(cli_obj);
1881             }
1882             *cli_data= arCli;
1883             break;
1884         }
1885         case typelib_TypeClass_ENUM:
1886         {
1887             //get the Enum type
1888             System::Type* enumType= NULL;
1889             if (info != NULL)
1890             {
1891                 //info is EnumType[]&, remove &
1892                 OSL_ASSERT(info->IsByRef);
1893                 enumType = info->GetElementType();
1894                 //enumType is EnumType[], remove []
1895                 enumType = enumType->GetElementType();
1896             }
1897             else
1898                 enumType= mapUnoType(element_type);
1899 
1900             System::Array* arEnum = System::Array::CreateInstance(
1901                 enumType, nElements);
1902             for (int i= 0; i < nElements; i++)
1903             {
1904                 arEnum->SetValue(System::Enum::ToObject(enumType,
1905                    ((sal_Int32*) seq->elements)[i]), i);
1906             }
1907             *cli_data = arEnum;
1908             break;
1909         }
1910         case typelib_TypeClass_STRUCT:
1911         case typelib_TypeClass_EXCEPTION:
1912         {
1913             TypeDescr element_td( element_type );
1914             System::Array* ar= System::Array::CreateInstance(
1915                 mapUnoType(element_type),nElements);
1916             if (0 < nElements)
1917             {
1918                 // ToDo check this
1919                 char * p = (char *) &seq->elements;
1920                 sal_Int32 nSize = element_td.get()->nSize;
1921                 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
1922                 {
1923                     System::Object* val;
1924                     map_to_cli(
1925                         &val, p + (nSize * nPos), element_type, 0, false);
1926                     ar->SetValue(val, nPos);
1927                 }
1928             }
1929 			*cli_data = ar;
1930             break;
1931         }
1932 // ToDo, verify
1933         case typelib_TypeClass_SEQUENCE:
1934         {
1935             System::Array *ar= System::Array::CreateInstance(
1936                 mapUnoType(element_type), nElements);
1937             if (0 < nElements)
1938             {
1939                 TypeDescr element_td( element_type );
1940                 uno_Sequence ** elements = (uno_Sequence**) seq->elements;
1941                 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
1942                 {
1943                     System::Object* val;
1944                     map_to_cli(
1945                         &val, &elements[nPos], element_type, 0, false);
1946                     ar->SetValue(val, nPos);
1947                 }
1948             }
1949             *cli_data = ar;
1950             break;
1951         }
1952         case typelib_TypeClass_INTERFACE:
1953         {
1954             TypeDescr element_td( element_type );
1955             System::Type * ifaceType= mapUnoType(element_type);
1956             System::Array* ar= System::Array::CreateInstance(ifaceType, nElements);
1957 
1958             char * p = (char *)seq->elements;
1959             sal_Int32 nSize = element_td.get()->nSize;
1960             for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
1961             {
1962                 System::Object* val;
1963                 map_to_cli(
1964                     &val, p + (nSize * nPos), element_type, NULL, false);
1965 
1966                 ar->SetValue(val, nPos);
1967             }
1968             *cli_data= ar;
1969             break;
1970         }
1971         default:
1972         {
1973             OUStringBuffer buf( 128 );
1974             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_cli():") );
1975             buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) );
1976             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported element type: ") );
1977             buf.append( *reinterpret_cast< OUString const * >( &element_type->pTypeName ) );
1978             throw BridgeRuntimeError( buf.makeStringAndClear() );
1979         }
1980         }
1981         break;
1982     }
1983     case typelib_TypeClass_INTERFACE:
1984     {
1985         uno_Interface * pUnoI = *(uno_Interface * const *)uno_data;
1986         if (0 != pUnoI)
1987         {
1988             TypeDescr td( type );
1989             *cli_data= map_uno2cli( pUnoI, reinterpret_cast<
1990                                           typelib_InterfaceTypeDescription*>(td.get())) ;
1991         }
1992 		else
1993 			*cli_data= NULL;
1994         break;
1995     }
1996     default:
1997     {
1998         //ToDo check this exception. The String is probably crippled
1999         OUStringBuffer buf( 128 );
2000         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_cli():") );
2001         buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) );
2002         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported type!") );
2003         throw BridgeRuntimeError( buf.makeStringAndClear() );
2004     }
2005     }
2006 }
2007 }
2008