Update ooo320-m1
[ooovba.git] / bridges / source / remote / urp / urp_unmarshal.cxx
blob2ae66562a15d58c9b8dd56d5d8aeb94fab817141
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: urp_unmarshal.cxx,v $
10 * $Revision: 1.16 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_bridges.hxx"
33 #include <string.h>
35 #include <osl/diagnose.h>
37 #include <rtl/alloc.h>
38 #include <rtl/ustrbuf.hxx>
40 #include <uno/data.h>
41 #include <uno/any2.h>
42 #include <uno/sequence2.h>
44 #include <com/sun/star/uno/Any.hxx>
46 #include "urp_unmarshal.hxx"
47 #include "urp_bridgeimpl.hxx"
50 using namespace ::rtl;
51 using namespace ::com::sun::star::uno;
53 namespace bridges_urp
55 static int g_nDetectLittleEndian = 1;
56 char g_bSystemIsLittleEndian = ((char*)&g_nDetectLittleEndian)[0];
59 Unmarshal::Unmarshal( struct urp_BridgeImpl *pBridgeImpl,
60 uno_Environment *pEnvRemote,
61 remote_createStubFunc callback ) :
62 m_nBufferSize( 4096 ),
63 m_base( (sal_Int8*) rtl_allocateMemory( m_nBufferSize ) ),
64 m_pos( m_base ),
65 m_nLength( 0 ),
66 m_callback( callback ),
67 m_pEnvRemote( pEnvRemote ),
68 m_pBridgeImpl( pBridgeImpl )
72 Unmarshal::~Unmarshal()
74 rtl_freeMemory( m_base );
77 // special unpacks
78 sal_Bool Unmarshal::unpackTid( sal_Sequence **ppThreadId )
80 sal_Int32 nSize;
81 sal_Bool bReturn = unpackCompressedSize( &nSize );
82 if( bReturn )
84 if( nSize )
86 rtl_byte_sequence_constructFromArray( ppThreadId , m_pos , nSize );
87 m_pos += nSize;
88 sal_uInt16 nIndex;
89 bReturn = unpackInt16( &nIndex );
90 if( nIndex < m_pBridgeImpl->m_properties.nTidCacheSize )
92 m_pBridgeImpl->m_pTidIn[nIndex] = *(ByteSequence * )ppThreadId;
94 else if( 0xffff != nIndex )
96 bReturn = sal_False;
97 rtl_byte_sequence_construct( ppThreadId , 0 );
99 OUStringBuffer error( 128 );
100 error.appendAscii( "cache index for tid " );
101 OString o = byteSequence2HumanReadableString( *(ByteSequence * ) ppThreadId );
102 error.appendAscii( o.getStr(), o.getLength() );
103 error.appendAscii( "out of range(0x");
104 error.append( (sal_Int32) nIndex ,16 );
105 error.appendAscii( ")" );
106 m_pBridgeImpl->addError( error.makeStringAndClear() );
109 else
111 sal_uInt16 nIndex;
112 bReturn = unpackInt16( &nIndex );
113 if( nIndex < m_pBridgeImpl->m_properties.nTidCacheSize )
115 *ppThreadId = m_pBridgeImpl->m_pTidIn[nIndex].getHandle();
116 rtl_byte_sequence_acquire( *ppThreadId );
118 else
120 bReturn = sal_False;
121 rtl_byte_sequence_construct( ppThreadId , 0 );
122 OUStringBuffer error(128);
123 error.appendAscii( "cache index for tids out of range(0x" );
124 error.append( (sal_Int32) nIndex ,16 );
125 error.appendAscii( ")" );
126 m_pBridgeImpl->addError( error.makeStringAndClear() );
130 else
132 m_pBridgeImpl->addError( "couldn't unpack thread id because of previous errors" );
134 return bReturn;
137 sal_Bool Unmarshal::unpackOid( rtl_uString **ppOid )
139 sal_Bool bReturn = sal_True;
140 sal_uInt16 nCacheIndex = 0;
142 bReturn = bReturn && unpackString( ppOid );
143 bReturn = bReturn && unpackInt16( &nCacheIndex );
145 if( bReturn &&
146 ! ( 0xffff == nCacheIndex && 0 == (*ppOid)->length ) /* null reference */ )
148 if( (*ppOid)->length )
150 // new unknown reference
151 if( 0xffff != nCacheIndex )
153 // oid should be cached ?
154 if( nCacheIndex < m_pBridgeImpl->m_properties.nOidCacheSize )
156 m_pBridgeImpl->m_pOidIn[nCacheIndex] = *ppOid;
158 else
160 OUStringBuffer error( 128 );
161 error.appendAscii( "new oid provided (" );
162 error.append( *ppOid );
163 error.appendAscii( "), but new cache index is out of range(0x");
164 error.append( (sal_Int32) nCacheIndex ,16 );
165 error.appendAscii( ")" );
166 m_pBridgeImpl->addError( error.makeStringAndClear() );
168 bReturn = sal_False;
169 rtl_uString_new( ppOid );
173 else
175 // reference in cache !
176 if( nCacheIndex < m_pBridgeImpl->m_properties.nOidCacheSize )
178 rtl_uString_assign( ppOid , m_pBridgeImpl->m_pOidIn[nCacheIndex].pData );
180 else
182 bReturn = sal_False;
183 rtl_uString_new( ppOid );
185 OUStringBuffer error( 128 );
186 error.appendAscii( "cache index for oids out of range(0x");
187 error.append( (sal_Int32) nCacheIndex ,16 );
188 error.appendAscii( ")" );
189 m_pBridgeImpl->addError( error.makeStringAndClear() );
194 return bReturn;
197 sal_Bool Unmarshal::unpack( void *pDestination ,
198 typelib_TypeDescription *pTypeDescr )
200 // Note: We implement unpack functionality without recursions in order
201 // to avoid stack overflows caused by rotten URP blocks.
203 m_aItemsToUnpack.push( UnpackItem( pDestination, pTypeDescr ) );
205 sal_Bool bReturn = sal_True;
208 void * pDest = m_aItemsToUnpack.top().pDest;
209 typelib_TypeDescription * pType = m_aItemsToUnpack.top().pType;
210 m_aItemsToUnpack.pop();
212 switch( pType->eTypeClass )
214 case typelib_TypeClass_VOID:
215 // do nothing
216 break;
217 case typelib_TypeClass_BYTE:
219 bReturn = unpackInt8( pDest );
220 break;
222 case typelib_TypeClass_BOOLEAN:
224 bReturn = ! checkOverflow( 1 );
225 if( bReturn )
227 *((sal_Bool*)pDest) = (sal_Bool ) ( *m_pos);
228 m_pos ++;
230 else
232 *((sal_Bool*)pDest) = 0;
234 break;
237 case typelib_TypeClass_CHAR:
238 case typelib_TypeClass_SHORT:
239 case typelib_TypeClass_UNSIGNED_SHORT:
241 unpackInt16( pDest );
242 break;
244 case typelib_TypeClass_ENUM:
245 case typelib_TypeClass_FLOAT:
246 case typelib_TypeClass_LONG:
247 case typelib_TypeClass_UNSIGNED_LONG:
249 bReturn = unpackInt32( pDest );
250 break;
252 case typelib_TypeClass_DOUBLE:
253 case typelib_TypeClass_HYPER:
254 case typelib_TypeClass_UNSIGNED_HYPER:
256 sal_Int8 * p = static_cast< sal_Int8 * >(pDest);
257 bReturn = ! checkOverflow( 8 );
258 if( bReturn )
260 if( isSystemLittleEndian() )
262 p[7] = m_pos[0];
263 p[6] = m_pos[1];
264 p[5] = m_pos[2];
265 p[4] = m_pos[3];
266 p[3] = m_pos[4];
267 p[2] = m_pos[5];
268 p[1] = m_pos[6];
269 p[0] = m_pos[7];
271 else
273 p[0] = m_pos[0];
274 p[1] = m_pos[1];
275 p[2] = m_pos[2];
276 p[3] = m_pos[3];
277 p[4] = m_pos[4];
278 p[5] = m_pos[5];
279 p[6] = m_pos[6];
280 p[7] = m_pos[7];
282 m_pos += 8;
284 else
286 // Do not trigger alignment errors:
287 p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = p[6] = p[7] = 0;
289 break;
291 case typelib_TypeClass_STRING:
293 unpackString( pDest );
294 break;
296 case typelib_TypeClass_ANY:
298 uno_Any *pAny = ( uno_Any * )pDest;
300 pAny->pType = 0;
301 // Type is acquired with typelib_typedescription_acquire
303 bReturn = unpackType( &(pAny->pType) );
305 typelib_TypeDescription *pDataType = 0;
306 if( bReturn && pAny->pType )
308 typelib_typedescriptionreference_getDescription( &pDataType , pAny->pType );
310 if( pDataType )
312 switch (pDataType->eTypeClass)
314 case typelib_TypeClass_HYPER:
315 case typelib_TypeClass_UNSIGNED_HYPER:
316 if (sizeof(void *) < sizeof(sal_Int64))
318 pAny->pData = rtl_allocateMemory( sizeof(sal_Int64) );
320 else
322 pAny->pData = &pAny->pReserved;
324 break;
325 case typelib_TypeClass_FLOAT:
326 if (sizeof(void *) < sizeof(float))
328 pAny->pData = rtl_allocateMemory( sizeof(float) );
330 else
332 pAny->pData = &pAny->pReserved;
334 break;
335 case typelib_TypeClass_DOUBLE:
336 if (sizeof(void *) < sizeof(double))
338 pAny->pData = rtl_allocateMemory( sizeof(double) );
340 else
342 pAny->pData = &pAny->pReserved;
344 break;
345 case typelib_TypeClass_STRUCT:
346 case typelib_TypeClass_UNION:
347 case typelib_TypeClass_EXCEPTION:
348 case typelib_TypeClass_ARRAY:
349 pAny->pData = rtl_allocateMemory( pDataType->nSize );
350 break;
351 case typelib_TypeClass_ANY:
353 m_pBridgeImpl->addError(
354 OUString( RTL_CONSTASCII_USTRINGPARAM(
355 "can't unmarshal any: any in any not supported!" ) ) );
357 pAny->pData = 0;
358 Type type; // void
359 pAny->pType = type.getTypeLibType();
360 typelib_typedescriptionreference_acquire( pAny->pType );
362 bReturn = sal_False;
363 break;
365 default:
366 pAny->pData = &pAny->pReserved;
369 if ( bReturn )
371 m_aItemsToUnpack.push(
372 UnpackItem( pAny->pData, pDataType ) );
375 else
377 OUStringBuffer error;
378 error.appendAscii( "can't unmarshal any because typedescription for " );
379 error.append( pAny->pType->pTypeName );
380 error.appendAscii( " is missing" );
381 m_pBridgeImpl->addError( error.makeStringAndClear() );
385 if( pDataType )
387 typelib_typedescription_release( pDataType );
389 else
391 pAny->pData = 0;
392 Type type; // void
393 pAny->pType = type.getTypeLibType();
394 typelib_typedescriptionreference_acquire( pAny->pType );
396 bReturn = sal_False;
399 break;
401 case typelib_TypeClass_INTERFACE:
403 *(remote_Interface**)pDest = 0;
405 rtl_uString *pString = 0;
406 bReturn = unpackOid( &pString ) && bReturn;
408 if( bReturn && pString && pString->length )
410 m_callback( (remote_Interface**) pDest ,
411 pString,
412 pType->pWeakRef ,
413 m_pEnvRemote,
414 urp_releaseRemoteCallback );
416 if( pString )
418 rtl_uString_release( pString );
420 break;
422 case typelib_TypeClass_TYPE:
424 bReturn = unpackType( pDest );
425 break;
427 case typelib_TypeClass_STRUCT:
428 case typelib_TypeClass_EXCEPTION:
430 typelib_CompoundTypeDescription * pCompType =
431 (typelib_CompoundTypeDescription *)pType;
433 // direct members
434 typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs;
435 sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets;
436 sal_Int32 nDescr = pCompType->nMembers;
438 // at least assume 1 byte per member
439 bReturn = bReturn && ! checkOverflow( nDescr * 1 );
440 for ( sal_Int32 nPos = nDescr; nPos; --nPos )
442 typelib_TypeDescription * pMemberType = 0;
443 typelib_typedescriptionreference_getDescription(
444 &pMemberType, ppTypeRefs[ nPos - 1 ] );
446 m_aItemsToUnpack.push(
447 UnpackItem( (char*)pDest + pMemberOffsets[ nPos - 1 ],
448 pMemberType,
449 true /* construct even in error case */ ) );
451 m_aTypesToRelease.push_back( pMemberType );
454 // parent
455 if (pCompType->pBaseTypeDescription)
457 m_aItemsToUnpack.push(
458 UnpackItem( pDest,
459 (typelib_TypeDescription *)
460 pCompType->pBaseTypeDescription ) );
462 break;
464 case typelib_TypeClass_SEQUENCE:
466 sal_Int32 nLen;
467 bReturn = unpackCompressedSize( &nLen );
469 // urp protocol does not allow to use the elementsize as a guess, if enough data
470 // is available. However, at least one byte per member must be within the message
471 bReturn = bReturn && ! checkOverflow( 1 * nLen );
472 uno_Sequence *pSequence = 0;
473 if( nLen && bReturn )
475 typelib_TypeDescriptionReference * pETRef =
476 ((typelib_IndirectTypeDescription *)pType)->pType;
478 typelib_TypeDescription * pET = 0;
479 typelib_typedescriptionreference_getDescription( &pET , pETRef );
481 if( pET )
483 sal_Int32 nElementSize = pET->nSize;
485 pSequence = (uno_Sequence *)rtl_allocateMemory(
486 SAL_SEQUENCE_HEADER_SIZE + nElementSize * nLen );
487 pSequence->nRefCount = 1;
488 pSequence->nElements = nLen;
490 if( typelib_TypeClass_BYTE == pET->eTypeClass )
492 memcpy( pSequence->elements , m_pos , nLen );
493 m_pos += nLen;
495 else
497 for ( sal_Int32 i = nLen; i; --i )
499 m_aItemsToUnpack.push(
500 UnpackItem(
501 ((char*)pSequence->elements)
502 + (i - 1) * nElementSize,
503 pET ) );
506 m_aTypesToRelease.push_back( pET );
508 else
510 bReturn = sal_False;
511 uno_constructData( &pSequence , pType );
512 OUStringBuffer error;
513 error.appendAscii( "can't unmarshal sequence, because there is no typedescription for element type " );
514 error.append( pETRef->pTypeName );
515 error.appendAscii( " available" );
516 m_pBridgeImpl->addError( error.makeStringAndClear() );
519 else
521 uno_constructData( &pSequence , pType );
524 *((uno_Sequence **)pDest) = pSequence;
525 break;
527 case typelib_TypeClass_UNION:
528 case typelib_TypeClass_ARRAY:
529 case typelib_TypeClass_SERVICE:
530 case typelib_TypeClass_MODULE:
531 case typelib_TypeClass_INTERFACE_METHOD:
532 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
533 case typelib_TypeClass_UNKNOWN:
534 default:
536 ::rtl::OUStringBuffer buffer( 128 );
537 buffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Unsupported typeclass during unmarshaling ("));
538 buffer.append( ( sal_Int32 ) pType->eTypeClass , 10 );
539 buffer.appendAscii( ")" );
540 m_pBridgeImpl->addError( buffer.makeStringAndClear() );
541 bReturn = sal_False;
545 if ( !bReturn )
547 // construct default data for every remaining item.
548 while ( !m_aItemsToUnpack.empty() )
550 const UnpackItem & rItem = m_aItemsToUnpack.top();
552 if ( rItem.bMustBeConstructed )
553 uno_constructData( rItem.pDest , rItem.pType );
555 m_aItemsToUnpack.pop();
559 while ( !m_aItemsToUnpack.empty() );
561 // release pending type descriptions
562 TypeDescVector::const_iterator it = m_aTypesToRelease.begin();
563 const TypeDescVector::const_iterator end = m_aTypesToRelease.end();
564 while ( it != end )
566 typelib_typedescription_release( *it );
567 it++;
569 m_aTypesToRelease.clear();
571 return bReturn;
574 sal_Bool Unmarshal::unpackType( void *pDest )
576 *(typelib_TypeDescriptionReference **) pDest = 0;
578 sal_uInt8 nTypeClass;
579 sal_Bool bReturn = unpackInt8( &nTypeClass );
581 typelib_TypeDescriptionReference *pTypeRef = 0;
582 if( bReturn )
584 if( nTypeClass <= 14 /* any */ )
586 pTypeRef = * typelib_static_type_getByTypeClass((typelib_TypeClass )nTypeClass);
587 typelib_typedescriptionreference_acquire( pTypeRef );
589 else
591 sal_uInt16 nCacheIndex = 0;
592 bReturn = bReturn && unpackInt16( &nCacheIndex );
594 if( bReturn )
596 if( nTypeClass & 0x80 )
598 // new type
599 rtl_uString *pString = 0;
600 bReturn = bReturn && unpackString( &pString );
601 if( bReturn )
603 typelib_TypeDescription *pType = 0;
604 typelib_typedescription_getByName( &pType, pString );
605 if( pType )
607 // type is known in this process
608 if( (typelib_TypeClass )(nTypeClass & 0x7f) == pType->eTypeClass )
610 //typename and typeclass match, this is as it should be
611 pTypeRef = pType->pWeakRef;
612 typelib_typedescriptionreference_acquire( pTypeRef );
614 else
616 // typename and typeclass do not match, dispose the bridge
617 // as there must be inconsistent type base between both processes
618 // or trash comes over the wire ...
619 bReturn = sal_False;
620 OUStringBuffer error( 128 );
621 error.appendAscii( "it is tried to introduce type " );
622 error.append( pString );
623 error.appendAscii( "with typeclass " );
624 error.append( (sal_Int32)( nTypeClass & 0x7f ) , 10 );
625 error.appendAscii( " , which does not match with typeclass " );
626 error.append( (sal_Int32) pType->eTypeClass ,10 );
627 m_pBridgeImpl->addError( error.makeStringAndClear() );
629 typelib_typedescription_release( pType );
630 pType = 0;
632 else
634 // a type by this name is not known in the process.
635 if( (nTypeClass & 0x7f) < typelib_TypeClass_UNKNOWN )
637 // typeclass is within a valid range, introduce the new
638 // type.
639 typelib_typedescriptionreference_new(
640 &pTypeRef, (typelib_TypeClass )(nTypeClass & 0x7f), pString );
642 else
644 // typeclass is out of range !
645 bReturn = sal_False;
646 OUStringBuffer error( 128 );
647 error.appendAscii( "it is tried to introduce type " );
648 error.append( pString );
649 error.appendAscii( "with an out of range typeclass " );
650 error.append( (sal_Int32)( nTypeClass & 0x7f ) , 10 );
651 m_pBridgeImpl->addError( error.makeStringAndClear() );
655 if( bReturn && nCacheIndex != 0xffff )
657 if( nCacheIndex < m_pBridgeImpl->m_properties.nTypeCacheSize )
659 m_pBridgeImpl->m_pTypeIn[nCacheIndex] = *( Type * )&pTypeRef;
661 else
663 bReturn = sal_False;
664 OUStringBuffer error( 128 );
665 error.appendAscii( "cache index for type " );
666 error.append( pString );
667 error.appendAscii( "out of range(0x" );
668 error.append( (sal_Int32) nCacheIndex ,16 );
669 error.appendAscii( ")" );
670 m_pBridgeImpl->addError( error.makeStringAndClear() );
674 if( pString )
676 rtl_uString_release( pString );
679 else
681 if( nCacheIndex < m_pBridgeImpl->m_properties.nTypeCacheSize )
683 pTypeRef = m_pBridgeImpl->m_pTypeIn[nCacheIndex].getTypeLibType();
684 typelib_typedescriptionreference_acquire( pTypeRef );
686 else
688 bReturn = sal_False;
689 OUStringBuffer error;
690 error.appendAscii( "cache index for types out of range(0x" );
691 error.append( (sal_Int32) nCacheIndex ,16 );
692 error.appendAscii( ")" );
693 m_pBridgeImpl->addError( error.makeStringAndClear() );
699 if( ! pTypeRef )
701 pTypeRef = * typelib_static_type_getByTypeClass(typelib_TypeClass_VOID);
702 typelib_typedescriptionreference_acquire( pTypeRef );
704 // pTypeRef is already acquired
705 *(typelib_TypeDescriptionReference**)pDest = pTypeRef;
706 return bReturn;