1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: urp_unmarshal.cxx,v $
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"
35 #include <osl/diagnose.h>
37 #include <rtl/alloc.h>
38 #include <rtl/ustrbuf.hxx>
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
;
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
) ),
66 m_callback( callback
),
67 m_pEnvRemote( pEnvRemote
),
68 m_pBridgeImpl( pBridgeImpl
)
72 Unmarshal::~Unmarshal()
74 rtl_freeMemory( m_base
);
78 sal_Bool
Unmarshal::unpackTid( sal_Sequence
**ppThreadId
)
81 sal_Bool bReturn
= unpackCompressedSize( &nSize
);
86 rtl_byte_sequence_constructFromArray( ppThreadId
, m_pos
, nSize
);
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
)
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() );
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
);
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() );
132 m_pBridgeImpl
->addError( "couldn't unpack thread id because of previous errors" );
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
);
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
;
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() );
169 rtl_uString_new( ppOid
);
175 // reference in cache !
176 if( nCacheIndex
< m_pBridgeImpl
->m_properties
.nOidCacheSize
)
178 rtl_uString_assign( ppOid
, m_pBridgeImpl
->m_pOidIn
[nCacheIndex
].pData
);
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() );
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
:
217 case typelib_TypeClass_BYTE
:
219 bReturn
= unpackInt8( pDest
);
222 case typelib_TypeClass_BOOLEAN
:
224 bReturn
= ! checkOverflow( 1 );
227 *((sal_Bool
*)pDest
) = (sal_Bool
) ( *m_pos
);
232 *((sal_Bool
*)pDest
) = 0;
237 case typelib_TypeClass_CHAR
:
238 case typelib_TypeClass_SHORT
:
239 case typelib_TypeClass_UNSIGNED_SHORT
:
241 unpackInt16( pDest
);
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
);
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 );
260 if( isSystemLittleEndian() )
286 // Do not trigger alignment errors:
287 p
[0] = p
[1] = p
[2] = p
[3] = p
[4] = p
[5] = p
[6] = p
[7] = 0;
291 case typelib_TypeClass_STRING
:
293 unpackString( pDest
);
296 case typelib_TypeClass_ANY
:
298 uno_Any
*pAny
= ( uno_Any
* )pDest
;
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
);
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
) );
322 pAny
->pData
= &pAny
->pReserved
;
325 case typelib_TypeClass_FLOAT
:
326 if (sizeof(void *) < sizeof(float))
328 pAny
->pData
= rtl_allocateMemory( sizeof(float) );
332 pAny
->pData
= &pAny
->pReserved
;
335 case typelib_TypeClass_DOUBLE
:
336 if (sizeof(void *) < sizeof(double))
338 pAny
->pData
= rtl_allocateMemory( sizeof(double) );
342 pAny
->pData
= &pAny
->pReserved
;
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
);
351 case typelib_TypeClass_ANY
:
353 m_pBridgeImpl
->addError(
354 OUString( RTL_CONSTASCII_USTRINGPARAM(
355 "can't unmarshal any: any in any not supported!" ) ) );
359 pAny
->pType
= type
.getTypeLibType();
360 typelib_typedescriptionreference_acquire( pAny
->pType
);
366 pAny
->pData
= &pAny
->pReserved
;
371 m_aItemsToUnpack
.push(
372 UnpackItem( pAny
->pData
, pDataType
) );
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() );
387 typelib_typedescription_release( pDataType
);
393 pAny
->pType
= type
.getTypeLibType();
394 typelib_typedescriptionreference_acquire( pAny
->pType
);
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
,
414 urp_releaseRemoteCallback
);
418 rtl_uString_release( pString
);
422 case typelib_TypeClass_TYPE
:
424 bReturn
= unpackType( pDest
);
427 case typelib_TypeClass_STRUCT
:
428 case typelib_TypeClass_EXCEPTION
:
430 typelib_CompoundTypeDescription
* pCompType
=
431 (typelib_CompoundTypeDescription
*)pType
;
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 ],
449 true /* construct even in error case */ ) );
451 m_aTypesToRelease
.push_back( pMemberType
);
455 if (pCompType
->pBaseTypeDescription
)
457 m_aItemsToUnpack
.push(
459 (typelib_TypeDescription
*)
460 pCompType
->pBaseTypeDescription
) );
464 case typelib_TypeClass_SEQUENCE
:
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
);
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
);
497 for ( sal_Int32 i
= nLen
; i
; --i
)
499 m_aItemsToUnpack
.push(
501 ((char*)pSequence
->elements
)
502 + (i
- 1) * nElementSize
,
506 m_aTypesToRelease
.push_back( pET
);
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() );
521 uno_constructData( &pSequence
, pType
);
524 *((uno_Sequence
**)pDest
) = pSequence
;
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
:
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() );
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();
566 typelib_typedescription_release( *it
);
569 m_aTypesToRelease
.clear();
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;
584 if( nTypeClass
<= 14 /* any */ )
586 pTypeRef
= * typelib_static_type_getByTypeClass((typelib_TypeClass
)nTypeClass
);
587 typelib_typedescriptionreference_acquire( pTypeRef
);
591 sal_uInt16 nCacheIndex
= 0;
592 bReturn
= bReturn
&& unpackInt16( &nCacheIndex
);
596 if( nTypeClass
& 0x80 )
599 rtl_uString
*pString
= 0;
600 bReturn
= bReturn
&& unpackString( &pString
);
603 typelib_TypeDescription
*pType
= 0;
604 typelib_typedescription_getByName( &pType
, pString
);
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
);
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 ...
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
);
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
639 typelib_typedescriptionreference_new(
640 &pTypeRef
, (typelib_TypeClass
)(nTypeClass
& 0x7f), pString
);
644 // typeclass is out of range !
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
;
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() );
676 rtl_uString_release( pString
);
681 if( nCacheIndex
< m_pBridgeImpl
->m_properties
.nTypeCacheSize
)
683 pTypeRef
= m_pBridgeImpl
->m_pTypeIn
[nCacheIndex
].getTypeLibType();
684 typelib_typedescriptionreference_acquire( pTypeRef
);
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() );
701 pTypeRef
= * typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
);
702 typelib_typedescriptionreference_acquire( pTypeRef
);
704 // pTypeRef is already acquired
705 *(typelib_TypeDescriptionReference
**)pDest
= pTypeRef
;