windows-nt/Source/XPSP1/NT/com/ole32/oleprx32/proxy/bstr.cxx
2020-09-26 16:20:57 +08:00

225 lines
5.5 KiB
C++

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1993 Microsoft Corporation
Module Name:
bstr.cxx
Abstract:
Windows Data Type Support by means of [user_marshal] attribute.
Covers:
BSTR
Author:
Bill Morel (billmo) Oct 14, 1995
These routines provide [wire_marshal] support for BSTRs.
Revision History:
14-Jun-96 MikeHill Converted to use the new PrivSysAllocString,
PrivSysReAllocString, & PrivSysFreeString routines
(defined elsewhere in OLE32).
-------------------------------------------------------------------*/
//#include "stdrpc.hxx"
#pragma hdrstop
#include <wtypes.h>
#include "transmit.h"
#include <privoa.h> // PrivSys* routines
// round up string alloc requests to nearest N-byte boundary, since allocator
// will round up anyway. Improves cache hits.
//
// UNDONE: optimal for Chicago is 4
// UNDONE: optimal for Daytona is 32
// UNDONE: 4 didn't help the a$ = a$ + "x" case at all.
// UNDONE: 8 did (gave 50% cache hit)
//
#define WIN32_ALLOC_ALIGN (4 - 1)
#define DEFAULT_ALLOC_ALIGN (2 - 1)
/***
*unsigned int PrivSysStringByteLen(BSTR)
*Purpose:
* return the length in bytes of the given BSTR.
*
*Entry:
* bstr = the BSTR to return the length of
*
*Exit:
* return value = unsigned int, length in bytes.
*
***********************************************************************/
// #########################################################################
//
// BSTR
//
// #########################################################################
//+-------------------------------------------------------------------------
//
// Function: BSTR_UserSize
//
// Synopsis: Get the wire size for the BSTR handle and data.
//
// Derivation: Conformant struct with a flag field:
// align + 12 + data size.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
BSTR_UserSize (
unsigned long * pFlags,
unsigned long Offset,
BSTR * pBstr)
{
// Null bstr doesn't get marshalled.
if ( pBstr == NULL || *pBstr == NULL )
return Offset;
unsigned long ulDataSize;
LENGTH_ALIGN( Offset, 3 );
// Takes the byte length of a unicode string
ulDataSize = PrivSysStringByteLen( *pBstr );
return( Offset + 12 + ulDataSize) ;
}
//+-------------------------------------------------------------------------
//
// Function: BSTR_UserMarshall
//
// Synopsis: Marshalls an BSTR object into the RPC buffer.
//
// Derivation: Conformant struct with a flag field:
// align, size, null flag, size, data (bytes, if any)
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
BSTR_UserMarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
BSTR * pBstr)
{
// A null Bstr is not marshalled, the engine will take care of it.
if ( pBstr == NULL || *pBstr == NULL )
return pBuffer;
unsigned long ulDataSize;
// Data size (in bytes): a null bstr gets a data size of zero.
ulDataSize = PrivSysStringByteLen( *pBstr );
// Conformant size.
ALIGN( pBuffer, 3 );
*( PULONG_LV_CAST pBuffer)++ = (ulDataSize >> 1);
// FLAGGED_WORD_BLOB: Handle is the null/non-null flag
*( PULONG_LV_CAST pBuffer)++ = (unsigned long)*pBstr;
// Length on wire is in words.
*( PULONG_LV_CAST pBuffer)++ = (ulDataSize >> 1);
if( ulDataSize )
{
// we don't put the terminating string on wire
WdtpMemoryCopy( pBuffer, *pBstr, ulDataSize );
}
return( pBuffer + ulDataSize );
}
//+-------------------------------------------------------------------------
//
// Function: BSTR_UserUnmarshall
//
// Synopsis: Unmarshalls an BSTR object from the RPC buffer.
//
// Derivation: Conformant struct with a flag field:
// align, size, null flag, size, data (bytes, if any)
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
BSTR_UserUnmarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
BSTR * pBstr)
{
unsigned long ulDataSize, fHandle;
BSTR Bstr = NULL; // Default to NULL BSTR
ALIGN( pBuffer, 3 );
ulDataSize = *( PULONG_LV_CAST pBuffer)++;
fHandle = *(ulong *)pBuffer;
pBuffer += 8;
if ( fHandle )
{
// Length on wire is in words, and the string is unicode.
if ( *pBstr &&
*(((ulong *)*pBstr) -1) == (ulDataSize << 1) )
WdtpMemoryCopy( *pBstr, pBuffer, (ulDataSize << 1) );
else
{
if (!PrivSysReAllocStringLen( pBstr,
(OLECHAR *)pBuffer,
ulDataSize ))
RpcRaiseException( E_OUTOFMEMORY );
}
}
else
{
// free the old one, make it NULL.
PrivSysFreeString( *pBstr );
*pBstr = NULL;
}
return( pBuffer + (ulDataSize << 1) );
}
//+-------------------------------------------------------------------------
//
// Function: BSTR_UserFree
//
// Synopsis: Free an BSTR.
//
//--------------------------------------------------------------------------
void __RPC_USER
BSTR_UserFree(
unsigned long * pFlags,
BSTR * pBstr)
{
if( pBstr && *pBstr )
{
PrivSysFreeString(* pBstr);
*pBstr = NULL;
}
}