557 lines
15 KiB
C++
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
|
|
|
|
|
|
|
|
|