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

557 lines
15 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: clipformat.cxx
//
// Contents: Support for Windows/OLE data types for oleprx32.dll.
// Used to be transmit_as routines, now user_marshal routines.
//
// This file contains support for SNB.
//
// Functions:
// SNB_UserSize
// SNB_UserMarshal
// SNB_UserUnmarshal
// SNB_UserFree
// SNB_UserSize64
// SNB_UserMarshal64
// SNB_UserUnmarshal64
// SNB_UserFree64
//
// History: 13-Dec-00 JohnDoty Migrated from transmit.cxx
//
//--------------------------------------------------------------------------
#include "stdrpc.hxx"
#pragma hdrstop
#include <oleauto.h>
#include <objbase.h>
#include "transmit.hxx"
#include <rpcwdt.h>
#include <storext.h>
#include "widewrap.h"
#include <valid.h>
#include <obase.h>
#include <stream.hxx>
#include "carefulreader.hxx"
//+-------------------------------------------------------------------------
//
// Function: SNB_UserSize
//
// Synopsis: Sizes an SNB.
//
// Derivation: An array of strings in one block of memory.
//
// history: June-95 Ryszardk Created, based on SNB_*_xmit.
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
SNB_UserSize (
unsigned long * pFlags,
unsigned long Offset,
SNB * pSnb )
{
if ( ! pSnb )
return Offset;
// calculate the number of strings and characters (with their terminators)
ULONG ulCntStr = 0;
ULONG ulCntChar = 0;
if (pSnb && *pSnb)
{
SNB snb = *pSnb;
WCHAR *psz = *snb;
while (psz)
{
ulCntChar += lstrlenW(psz) + 1;
ulCntStr++;
snb++;
psz = *snb;
}
}
// The wire size is: conf size, 2 fields and the wchars.
LENGTH_ALIGN( Offset, 3 );
return ( Offset + 3 * sizeof(long) + ulCntChar * sizeof( WCHAR ) );
}
//+-------------------------------------------------------------------------
//
// Function: SNB_UserMarshall
//
// Synopsis: Marshalls an SNB into the RPC buffer.
//
// Derivation: An array of strings in one block of memory.
//
// history: June-95 Ryszardk Created, based on SNB_*_xmit.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
SNB_UserMarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
SNB * pSnb )
{
UserNdrDebugOut((UNDR_FORCE, "SNB_UserMarshal\n"));
if ( ! pSnb )
return pBuffer;
// calculate the number of strings and characters (with their terminators)
ULONG ulCntStr = 0;
ULONG ulCntChar = 0;
if (pSnb && *pSnb)
{
SNB snb = *pSnb;
WCHAR *psz = *snb;
while (psz)
{
ulCntChar += lstrlenW(psz) + 1;
ulCntStr++;
snb++;
psz = *snb;
}
}
// conformant size
ALIGN( pBuffer, 3 );
*( PULONG_LV_CAST pBuffer)++ = ulCntChar;
// fields
*( PULONG_LV_CAST pBuffer)++ = ulCntStr;
*( PULONG_LV_CAST pBuffer)++ = ulCntChar;
// actual strings only
if ( pSnb && *pSnb )
{
// There is a NULL string pointer to mark the end of the pointer array.
// However, the strings don't have to follow tightly.
// Hence, we have to copy one string at a time.
SNB snb = *pSnb;
WCHAR *pszSrc;
while (pszSrc = *snb++)
{
ULONG ulCopyLen = (lstrlenW(pszSrc) + 1) * sizeof(WCHAR);
WdtpMemoryCopy( pBuffer, pszSrc, ulCopyLen );
pBuffer += ulCopyLen;
}
}
return pBuffer;
}
//+-------------------------------------------------------------------------
//
// Function: SNB_UserUnmarshall
//
// Synopsis: Unmarshalls an SNB from the RPC buffer.
//
// Derivation: An array of strings in one block of memory.
//
// history: June-95 Ryszardk Created, based on SNB_*_xmit.
// Aug-99 JohnStra Add consistency checks.
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
SNB_UserUnmarshal (
unsigned long * pFlags,
unsigned char * pBuffer,
SNB * pSnb )
{
UserNdrDebugOut((UNDR_FORCE, "SNB_UserUnmarshal\n"));
// Initialize CUserMarshalInfo object and get the buffer
// size and pointer to the start of the buffer.
CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
UCHAR* pBufferStart = MarshalInfo.GetBuffer();
// Align the buffer and save the size of the fixup.
ALIGN( pBuffer, 3 );
ULONG_PTR cbFixup = (ULONG_PTR)(pBuffer - pBufferStart);
// Check for EOB before trying to get header.
CHECK_BUFFER_SIZE( BufferSize, cbFixup + (3 * sizeof( ULONG )) );
// Get the header from the buffer.
ULONG ulCntChar = *( PULONG_LV_CAST pBuffer)++;
ULONG ulCntStr = *( PULONG_LV_CAST pBuffer)++;
ULONG ulCntCharDup = *(PULONG_LV_CAST pBuffer)++;
// Verify that 2nd instance of count matches first.
if ( ulCntCharDup != ulCntChar )
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
// No reusage of pSNB.
if ( *pSnb )
WdtpFree( pFlags, *pSnb );
if ( ulCntStr == 0 )
{
// There are no strings.
// NULL pSnb and return.
*pSnb = NULL;
return pBuffer;
}
// Validate the header:
// Repeated char count must match first instance and char count must
// not be less than the number of strings since that would mean at
// least one of them doesn't isn't terminated.
if ( (ulCntChar != ulCntCharDup) || (ulCntChar < ulCntStr) )
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
// Check for EOB before trying to get the strings.
CHECK_BUFFER_SIZE(
BufferSize,
cbFixup + (3 * sizeof(ULONG)) + (ulCntChar * sizeof(WCHAR)) );
// Last WCHAR in the buffer must be the UNICODE terminator.
WCHAR* pszChars = (WCHAR*) pBuffer;
if ( pszChars[ulCntChar - 1] != 0x0000 )
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
// construct the SNB.
SNB Snb = (SNB) WdtpAllocate( pFlags,
( (ulCntStr + 1) * sizeof(WCHAR *) +
ulCntChar * sizeof(WCHAR)) );
*pSnb = Snb;
if (Snb)
{
// create the pointer array within the SNB. to do this, we go through
// the buffer, and use strlen to find the end of the each string for
// us.
WCHAR *pszSrc = (WCHAR *) pBuffer;
WCHAR *pszTgt = (WCHAR *) (Snb + ulCntStr + 1); // right behind array
void* SnbStart = Snb;
ULONG ulTotLen = 0;
ULONG i;
for (i = ulCntStr; (i > 0) && (ulTotLen < ulCntChar); i--)
{
*Snb++ = pszTgt;
ULONG ulLen = lstrlenW(pszSrc) + 1;
pszSrc += ulLen;
pszTgt += ulLen;
ulTotLen += ulLen;
}
*Snb++ = NULL;
// Verify that the number of strings and the number of chars
// in the buffer matches what is supposed to be there.
if ( (i > 0) || (ulTotLen < ulCntChar) )
{
WdtpFree( pFlags, SnbStart );
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
}
// Copy the actual strings.
// We can do a block copy here as we packed them tight in the buffer.
// Snb points right behind the lastarray of pointers within the SNB.
WdtpMemoryCopy( Snb, pBuffer, ulCntChar * sizeof(WCHAR) );
pBuffer += ulCntChar * sizeof(WCHAR);
}
return pBuffer;
}
//+-------------------------------------------------------------------------
//
// Function: SNB_UserFree
//
// Synopsis: Frees an SNB.
//
// Derivation: An array of strings in one block of memory.
//
// history: June-95 Ryszardk Created, based on SNB_*_xmit.
//
//--------------------------------------------------------------------------
void __RPC_USER
SNB_UserFree(
unsigned long * pFlags,
SNB * pSnb )
{
if ( pSnb && *pSnb )
WdtpFree( pFlags, *pSnb );
}
#if defined(_WIN64)
//+-------------------------------------------------------------------------
//
// Function: SNB_UserSize64
//
// Synopsis: Sizes an SNB.
//
// Derivation: An array of strings in one block of memory.
//
// history: Dec-00 JohnDoty Created from 32bit function
//
//--------------------------------------------------------------------------
unsigned long __RPC_USER
SNB_UserSize64 (
unsigned long * pFlags,
unsigned long Offset,
SNB * pSnb )
{
if ( ! pSnb )
return Offset;
// calculate the number of strings and characters (with their terminators)
ULONG ulCntStr = 0;
ULONG ulCntChar = 0;
if (pSnb && *pSnb)
{
SNB snb = *pSnb;
WCHAR *psz = *snb;
while (psz)
{
ulCntChar += lstrlenW(psz) + 1;
ulCntStr++;
snb++;
psz = *snb;
}
}
// The wire size is: conf size, 2 fields and the wchars.
LENGTH_ALIGN( Offset, 7 );
return ( Offset + 8 + (2 * sizeof(long)) + (ulCntChar * sizeof(WCHAR)) );
}
//+-------------------------------------------------------------------------
//
// Function: SNB_UserMarshal64
//
// Synopsis: Marshalls an SNB into the RPC buffer.
//
// Derivation: An array of strings in one block of memory.
//
// history: Dec-00 JohnDoty Created from 32bit function
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
SNB_UserMarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
SNB * pSnb )
{
UserNdrDebugOut((UNDR_FORCE, "SNB_UserMarshal\n"));
if ( ! pSnb )
return pBuffer;
// calculate the number of strings and characters (with their terminators)
ULONG ulCntStr = 0;
ULONG ulCntChar = 0;
if (pSnb && *pSnb)
{
SNB snb = *pSnb;
WCHAR *psz = *snb;
while (psz)
{
ulCntChar += lstrlenW(psz) + 1;
ulCntStr++;
snb++;
psz = *snb;
}
}
// conformant size
ALIGN( pBuffer, 7 );
*( PHYPER_LV_CAST pBuffer)++ = ulCntChar;
// fields
*( PULONG_LV_CAST pBuffer)++ = ulCntStr;
*( PULONG_LV_CAST pBuffer)++ = ulCntChar;
// actual strings only
if ( pSnb && *pSnb )
{
// There is a NULL string pointer to mark the end of the pointer array.
// However, the strings don't have to follow tightly.
// Hence, we have to copy one string at a time.
SNB snb = *pSnb;
WCHAR *pszSrc;
while (pszSrc = *snb++)
{
ULONG ulCopyLen = (lstrlenW(pszSrc) + 1) * sizeof(WCHAR);
WdtpMemoryCopy( pBuffer, pszSrc, ulCopyLen );
pBuffer += ulCopyLen;
}
}
return pBuffer;
}
//+-------------------------------------------------------------------------
//
// Function: SNB_UserUnmarshal64
//
// Synopsis: Unmarshalls an SNB from the RPC buffer.
//
// Derivation: An array of strings in one block of memory.
//
// history: Dec-00 JohnDoty Created from 32bit function
//
//--------------------------------------------------------------------------
unsigned char __RPC_FAR * __RPC_USER
SNB_UserUnmarshal64 (
unsigned long * pFlags,
unsigned char * pBuffer,
SNB * pSnb )
{
UserNdrDebugOut((UNDR_FORCE, "SNB_UserUnmarshal\n"));
// Initialize CUserMarshalInfo object and get the buffer
// size and pointer to the start of the buffer.
CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
CarefulBufferReader stream( pBuffer, MarshalInfo.GetBufferSize() );
// Get the header from the buffer.... (ReadHYPER aligns on 8).
ULONG ulCntChar = (ULONG)stream.ReadHYPER();
ULONG ulCntStr = stream.ReadULONGNA();
ULONG ulCntCharDup = stream.ReadULONGNA();
// Verify that 2nd instance of count matches first.
if ( ulCntCharDup != ulCntChar )
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
// No reusage of pSNB.
if ( *pSnb )
{
WdtpFree( pFlags, *pSnb );
*pSnb = NULL;
}
if ( ulCntStr == 0 )
{
// There are no strings.
return stream.GetBuffer();
}
// Validate the header:
// Repeated char count must match first instance and char count must
// not be less than the number of strings since that would mean at
// least one of them doesn't isn't terminated.
if ( ulCntChar < ulCntStr )
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
// Check for EOB before trying to get the strings.
stream.CheckSize(ulCntChar * sizeof(WCHAR));
// Last WCHAR in the buffer must be the UNICODE terminator.
WCHAR* pszChars = (WCHAR*)stream.GetBuffer();
if ( pszChars[ulCntChar - 1] != L'\0' )
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
// construct the SNB.
SNB Snb = (SNB) WdtpAllocate( pFlags,
( (ulCntStr + 1) * sizeof(WCHAR *) +
ulCntChar * sizeof(WCHAR)) );
*pSnb = Snb;
if (Snb)
{
// create the pointer array within the SNB. to do this, we go through
// the buffer, and use strlen to find the end of the each string for
// us.
WCHAR *pszSrc = (WCHAR *) stream.GetBuffer();
WCHAR *pszTgt = (WCHAR *) (Snb + ulCntStr + 1); // right behind array
void* SnbStart = Snb;
ULONG ulTotLen = 0;
ULONG i;
for (i = ulCntStr; (i > 0) && (ulTotLen < ulCntChar); i--)
{
*Snb++ = pszTgt;
ULONG ulLen = lstrlenW(pszSrc) + 1;
pszSrc += ulLen;
pszTgt += ulLen;
ulTotLen += ulLen;
}
*Snb++ = NULL;
// Verify that the number of strings and the number of chars
// in the buffer matches what is supposed to be there.
if ( (i > 0) || (ulTotLen < ulCntChar) )
{
WdtpFree( pFlags, SnbStart );
RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
}
// Copy the actual strings.
// We can do a block copy here as we packed them tight in the buffer.
// Snb points right behind the lastarray of pointers within the SNB.
WdtpMemoryCopy( Snb, stream.GetBuffer(), ulCntChar * sizeof(WCHAR) );
stream.Advance(ulCntChar * sizeof(WCHAR));
}
return stream.GetBuffer();
}
//+-------------------------------------------------------------------------
//
// Function: SNB_UserFree64
//
// Synopsis: Frees an SNB.
//
// Derivation: An array of strings in one block of memory.
//
// history: Dec-00 JohnDoty Created from 32bit function
//
//--------------------------------------------------------------------------
void __RPC_USER
SNB_UserFree64 (
unsigned long * pFlags,
SNB * pSnb )
{
if ( pSnb && *pSnb )
WdtpFree( pFlags, *pSnb );
}
#endif