|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1993-2000 Microsoft Corporation
Module Name:
frmtstr.hxx
Abstract:
Notes:
History:
DKays Oct-1993 Created. ----------------------------------------------------------------------------*/
#include "becls.hxx"
#pragma hdrstop
extern CMD_ARG * pCommand;
const char * pExprFormatCharNames[] = { "" ,"FC_EXPR_CONST32" ,"FC_EXPR_CONST64" ,"FC_EXPR_VAR" ,"FC_EXPR_OPER" ,"FC_EXPR_PAD" };
const char * pFormatCharNames[] = { "", // FC_ZERO
"FC_BYTE", "FC_CHAR", "FC_SMALL", "FC_USMALL", "FC_WCHAR", "FC_SHORT", "FC_USHORT", "FC_LONG", "FC_ULONG", "FC_FLOAT", "FC_HYPER", "FC_DOUBLE",
"FC_ENUM16", "FC_ENUM32", "FC_IGNORE", "FC_ERROR_STATUS_T",
"FC_RP", // 11
"FC_UP", "FC_OP", "FC_FP",
"FC_STRUCT", "FC_PSTRUCT", "FC_CSTRUCT", "FC_CPSTRUCT", "FC_CVSTRUCT", "FC_BOGUS_STRUCT",
"FC_CARRAY", "FC_CVARRAY", "FC_SMFARRAY", "FC_LGFARRAY", "FC_SMVARRAY", "FC_LGVARRAY or FC_SPLIT", // 20
"FC_BOGUS_ARRAY",
"FC_C_CSTRING", "FC_C_BSTRING", "FC_C_SSTRING", "FC_C_WSTRING", "FC_CSTRING", "FC_BSTRING", "FC_SSTRING", "FC_WSTRING",
"FC_ENCAPSULATED_UNION", "FC_NON_ENCAPSULATED_UNION",
"FC_BYTE_COUNT_POINTER", "FC_TRANSMIT_AS", "FC_REPRESENT_AS",
"FC_IP",
"FC_BIND_CONTEXT", // 30
"FC_BIND_GENERIC", "FC_BIND_PRIMITIVE", "FC_AUTO_HANDLE", "FC_CALLBACK_HANDLE", "FC_UNUSED1", "FC_POINTER",
"FC_ALIGNM2", "FC_ALIGNM4", "FC_ALIGNM8", "FC_UNUSED2", "FC_UNUSED3", "FC_UNUSED4", "FC_STRUCTPAD1", "FC_STRUCTPAD2", "FC_STRUCTPAD3", "FC_STRUCTPAD4", // 40
"FC_STRUCTPAD5", "FC_STRUCTPAD6", "FC_STRUCTPAD7",
"FC_STRING_SIZED", "FC_UNUSED5",
"FC_NO_REPEAT", "FC_FIXED_REPEAT", "FC_VARIABLE_REPEAT", "FC_FIXED_OFFSET", "FC_VARIABLE_OFFSET", "FC_PP",
"FC_EMBEDDED_COMPLEX",
"FC_IN_PARAM", "FC_IN_PARAM_BASETYPE", "FC_IN_PARAM_NO_FREE_INST", "FC_IN_OUT_PARAM", // 50
"FC_OUT_PARAM", "FC_RETURN_PARAM", "FC_RETURN_PARAM_BASETYPE",
"FC_DEREFERENCE", // 54
"FC_DIV_2", // 55
"FC_MULT_2", // 56
"FC_ADD_1", // 57
"FC_SUB_1", // 58
"FC_CALLBACK", // 59
"FC_CONSTANT_IID", // 5a
"FC_END", // 5b
"FC_PAD", // 5c
"FC_EXPR", // 5d
"FC_PARTIAL_IGNORE_PARAM", // 5e,
"?", // 5f
"?", "?", "?", "?", "?", "?", "?", "?", // 60-67
"?", "?", "?", "?", "?", "?", "?", "?", // 68-6f
"?", "?", "?", "?", // 70-73
"FC_SPLIT_DEREFERENCE", // 74
"FC_SPLIT_DIV_2", // 75
"FC_SPLIT_MULT_2", // 76
"FC_SPLIT_ADD_1", // 77
"FC_SPLIT_SUB_1", // 78
"FC_SPLIT_CALLBACK", // 79
"?", "?", "?", "?", "?", "?", // 7a-7f
"?", "?", "?", "?", "?", "?", "?", "?", // 80-87
"?", "?", "?", "?", "?", "?", "?", "?", // 88-8f
"?", "?", "?", "?", "?", "?", "?", "?", // 90-97
"?", "?", "?", "?", "?", "?", "?", "?", // 98-9f
"?", "?", "?", "?", "?", "?", "?", "?", // a0-a7
"?", "?", "?", "?", "?", "?", "?", "?", // a8-af
"?", // b0
"FC_HARD_STRUCT",
"FC_TRANSMIT_AS_PTR", "FC_REPRESENT_AS_PTR",
"FC_USER_MARSHAL",
"FC_PIPE",
"?", // FC_BLKHOLE. obselete
"FC_RANGE", // b7
"FC_INT3264", // b8
"FC_UINT3264", // b9
// Post NT5.0
"FC_CSARRAY", // ba
"FC_CS_TAG", // bb
"FC_STRUCTPADN", // bc
"FC_INT128", // 0xbd
"FC_UINT128", // 0xbe
"FC_FLOAT80", // 0xbf
"FC_FLOAT128", // 0xc0
"FC_BUFFER_ALIGN", // 0xc1
"FC_ENCAP_UNION", // 0xc2
// new 64bit array types
"FC_FIX_ARRAY", // 0xc3
"FC_CONF_ARRAY", // 0xc4
"FC_VAR_ARRAY", // 0xc5
"FC_CONFVAR_ARRAY", // 0xc6
"FC_FIX_FORCED_BOGUS_ARRAY",// 0xc7
"FC_FIX_BOGUS_ARRAY", // 0xc8
"FC_FORCED_BOGUS_ARRAY", // 0xc9
"FC_CHAR_STRING", // 0xca
"FC_WCHAR_STRING", // 0xcb
"FC_STRUCT_STRING", // 0xcc
"FC_CONF_CHAR_STRING", // 0xcd
"FC_CONF_WCHAR_STRING", // 0xce
"FC_CONF_STRUCT_STRING", // 0xcf
// new structure types
"FC_CONF_STRUCT", // 0xd0
"FC_CONF_PSTRUCT", // 0xd1
"FC_CONFVAR_STRUCT", // 0xd2
"FC_CONFVAR_PSTRUCT", // 0xd3
"FC_FORCED_BOGUS_STRUCT", // 0xd4
"FC_CONF_BOGUS_STRUCT", // 0xd5
"FC_FORCED_CONF_BOGUS_STRUCT",// 0xd7
"FC_END_OF_UNIVERSE" // 0xd8
};
const char * pExprOpFormatCharNames[] = { "", "OP_UNARY_PLUS", "OP_UNARY_MINUS", "OP_UNARY_NOT", "OP_UNARY_COMPLEMENT", "OP_UNARY_INDIRECTION", "OP_UNARY_CAST", "OP_UNARY_AND", "OP_UNARY_SIZEOF", "OP_UNARY_ALIGNOF", "OP_PRE_INCR", "OP_PRE_DECR", "OP_POST_INCR", "OP_POST_DECR", "OP_PLUS", "OP_MINUS", "OP_STAR", "OP_SLASH", "OP_MOD", "OP_LEFT_SHIFT", "OP_RIGHT_SHIFT", "OP_LESS", "OP_LESS_EQUAL", "OP_GREATER_EQUAL", "OP_GREATER", "OP_EQUAL", "OP_NOT_EQUAL",
"OP_AND", "OP_OR", "OP_XOR",
"OP_LOGICAL_AND", "OP_LOGICAL_OR", "OP_EXPRESSION", "", "", "", // function
"", // param
"", // pointsto
"", // dot
"", // index
"", // comma
"", // stmt
"", // assign
"OP_ASYNCSPLIT", // asyncsplit
"OP_CORR_POINTER", // corr_pointer
"OP_CORR_TOP_LEVEL", // corr_toplevel
};
//
// This table is indexed by FORMAT_CHARACTER (see ndrtypes.h).
// To construct the correct name concatenate the name in this table with
// "Marshall", "Unmarshall", "BufferSize" etc.
//
char * pNdrRoutineNames[] = { "", // FC_ZERO
"NdrSimpleType", // FC_BYTE
"NdrSimpleType", // FC_CHAR
"NdrSimpleType", // FC_SMALL
"NdrSimpleType", // FC_USMALL
"NdrSimpleType", // FC_WCHAR
"NdrSimpleType", // FC_SHORT
"NdrSimpleType", // FC_USHORT
"NdrSimpleType", // FC_LONG
"NdrSimpleType", // FC_ULONG
"NdrSimpleType", // FC_FLOAT
"NdrSimpleType", // FC_HYPER
"NdrSimpleType", // FC_DOUBLE
"NdrSimpleType", // FC_ENUM16
"NdrSimpleType", // FC_ENUM32
"NdrSimpleType", // FC_IGNORE
"NdrSimpleType", // FC_ERROR_STATUS_T
"NdrPointer", // FC_RP
"NdrPointer", // FC_UP
"NdrPointer", // FC_OP
"NdrPointer", // FC_FP
"NdrSimpleStruct", // FC_STRUCT
"NdrSimpleStruct", // FC_PSTRUCT
"NdrConformantStruct", // FC_CSTRUCT
"NdrConformantStruct", // FC_CPSTRUCT
"NdrConformantVaryingStruct", // FC_CVSTRUCT
"NdrComplexStruct", // FC_BOGUS_STRUCT
"NdrConformantArray", // FC_CARRAY
"NdrConformantVaryingArray", // FC_CVARRAY
"NdrFixedArray", // FC_SMFARRAY
"NdrFixedArray", // FC_LGFARRAY
"NdrVaryingArray", // FC_SMVARRAY
"NdrVaryingArray", // FC_LGVARRAY
"NdrComplexArray", // FC_BOGUS_ARRAY
"NdrConformantString", // FC_C_CSTRING
"NdrConformantString", // FC_C_BSTRING
"NdrConformantString", // FC_C_SSTRING
"NdrConformantString", // FC_C_WSTRING
"NdrNonConformantString", // FC_CSTRING
"NdrNonConformantString", // FC_BSTRING
"NdrNonConformantString", // FC_SSTRING
"NdrNonConformantString", // FC_WSTRING
"NdrEncapsulatedUnion", // FC_ENCAPSULATED_UNION
"NdrNonEncapsulatedUnion", // FC_NON_ENCAPSULATED_UNION
"NdrByteCountPointer", // FC_BYTE_COUNT_POINTER
"NdrXmitOrRepAs", // FC_TRANSMIT_AS
"NdrXmitOrRepAs", // FC_REPRESENT_AS
"NdrInterfacePointer", // FC_INTERFACE_POINTER
"NdrContextHandle", // FC_BIND_CONTEXT
"?", "?", "?", "?", "?", "?", "?", // 31-37
"?", "?", "?", "?", "?", "?", "?", "?", // 38-3f
"?", "?", "?", "?", "?", "?", "?", "?", // 40-47
"?", "?", "?", "?", "?", "?", "?", "?", // 48-4f
"?", "?", "?", "?", "?", "?", "?", "?", // 50-57
"?", "?", "?", // 58-5a
"?", "?", // FC_END & FC_PAD
"?", "?", "?", // 5d-5f
"?", "?", "?", "?", "?", "?", "?", "?", // 60-67
"?", "?", "?", "?", "?", "?", "?", "?", // 68-6f
"?", "?", "?", "?", "?", "?", "?", "?", // 70-77
"?", "?", "?", "?", "?", "?", "?", "?", // 78-7f
"?", "?", "?", "?", "?", "?", "?", "?", // 80-87
"?", "?", "?", "?", "?", "?", "?", "?", // 88-8f
"?", "?", "?", "?", "?", "?", "?", "?", // 90-97
"?", "?", "?", "?", "?", "?", "?", "?", // 98-9f
"?", "?", "?", "?", "?", "?", "?", "?", // a0-a7
"?", "?", "?", "?", "?", "?", "?", "?", // a8-af
"?", // 0xb0
"NdrHardStruct", // FC_HARD_STRUCT
"NdrXmitOrRepAs", // FC_TRANSMIT_AS_PTR
"NdrXmitOrRepAs", // FC_REPRESENT_AS_PTR
"NdrUserMarshal", // FC_USER_MARSHAL
"NdrPipe", // FC_PIPE
0, // FC_BLKHOLE
0, // FC_RANGE
"NdrSimpleType", // FC_INT3264
"NdrSimpleType", // FC_UINT3264
"NdrCsArray", // FC_CSARRAY
"NdrCsTag", // FC_CS_TAG
0 };
// ============================================================================
//
// FORMAT_STRING class, general comments on fragment optimization.
//
// There are 3 type of offsets that matter a lot when format string fragments
// are optimized. These are absolute type offsets, relative type offsets and
// stack (or field) offsets.
//
// - Absolute type offsets are offsets from the proc format string to type
// format string. For 32b implementation they are limited to ushort32 range.
// An absolute type offset indicates a type of a parameter.
// Note that there is only one absolute type offset for a parameter regardless
// of the platform.
//
// - Relative type offsets are offsets within the type format string.
// For 32b implementation they are limited to short32 range.
// A relative type offset indicates a type of a component for a compund type.
// Note that there is only one relative type offset for a field or element
// regardless of the platform.
//
// - Stack offset is a stack offset to a parameter within a proc stack or
// a field offset to a field within a struct.
// For a 32b implementation stack offsets are limited to a short32 range. This
// is because some of these offsets are relative to a current position within
// a struct or union. They have been clampd together because of correlation
// descriptors may have stack or field offsets.
// Proper stack offsets actually come in a ushort and usmall range variaty.
// Proper field offsets come in as shorts.
// For a given position in the format string, there is a set of stack offsets
// as in general a x86 stack offset is different from other platform offsets
// and a field offset may be different as well.
//
// Proc format string uses only absolute type offsets and stack offsets.
//
// the constructor
FORMAT_STRING::FORMAT_STRING() { // Allocate the buffer and align it on a short boundary.
pBuffer = (unsigned char *) new short[ DEFAULT_FORMAT_STRING_SIZE / 2 ];
// Allocate the cousin buffer type array. This does not need to
// be aligned.
pBufferType = new unsigned char[ DEFAULT_FORMAT_STRING_SIZE ];
memset( pBuffer, 0, DEFAULT_FORMAT_STRING_SIZE ); memset( pBufferType, FS_FORMAT_CHARACTER, DEFAULT_FORMAT_STRING_SIZE );
BufferSize = DEFAULT_FORMAT_STRING_SIZE; CurrentOffset = 0; LastOffset = 0; pReuseDict = new FRMTREG_DICT( this ); }
void FORMAT_STRING::CheckSize() /*++
Routine Description : Reallocates a new format string buffer if the current buffer is within 4 bytes of overflowing.
Arguments : None.
--*/ { //
// Allocate a new buffer if we're within 4 bytes of
// overflowing the current buffer.
//
if ( CurrentOffset + 3 > BufferSize ) { unsigned char * pBufferNew;
// double the Buffer size
pBufferNew = (unsigned char *) new short[ BufferSize ];
memcpy( pBufferNew, pBuffer, (unsigned int) BufferSize ); memset( pBufferNew + BufferSize, 0, BufferSize );
delete pBuffer; pBuffer = pBufferNew;
// double the BufferType size
pBufferNew = (unsigned char *) new short[ BufferSize ];
memcpy( pBufferNew, pBufferType, (unsigned int) BufferSize ); memset( pBufferNew + BufferSize, FS_FORMAT_CHARACTER, BufferSize );
delete pBufferType; pBufferType = pBufferNew; BufferSize *= 2; } }
//
// Push a short type-fmt-string offset at the current offset.
// This is used as the offset from a parameter into type format string.
// For 32b code, this needs to be a value within an unsigned short.
// We use a long value internally for better fragment optimization.
//
void FORMAT_STRING::PushShortTypeOffset( long s ) { CheckSize();
if ( s < 0 || s > _UI16_MAX ) { // CG_NDR * pNdr = pCCB->GetLastPlaceholderClass();
CG_NDR * pNdr = 0; char * pName = pNdr ? pNdr->GetSymName() : ""; RpcError(NULL, 0, FORMAT_STRING_LIMITS, pName ); exit( FORMAT_STRING_LIMITS ); }
pBufferType[CurrentOffset] = FS_SHORT_TYPE_OFFSET; pBufferType[CurrentOffset+1] = FS_SMALL; *((unsigned short UNALIGNED *)(pBuffer + CurrentOffset)) = (unsigned short)s;
TypeOffsetDict.Insert( (long) CurrentOffset, s );
IncrementOffset(2); }
//
// Push a short offset at the current offset.
// This is the relative type offset within the type string.
// For 32b code, this needs to be a value within a signed short, eventually.
// We use a long value internally for better fragment optimization.
//
void FORMAT_STRING::PushShortOffset( long TypeOffset ) { CheckSize();
// We don't check the range for the offset here for better optimization.
pBufferType[ CurrentOffset ] = FS_SHORT_OFFSET; pBufferType[ CurrentOffset + 1 ] = FS_SMALL; *((short UNALIGNED *)(pBuffer + CurrentOffset)) = (short)TypeOffset;
TypeOffsetDict.Insert( (long) CurrentOffset, TypeOffset );
IncrementOffset(2); }
// This an auxilary method to handle relative offsets.
// It is used when we need to write out an offset temporarily and then fix it
// later, for example in pointers, structs etc.
//
void FORMAT_STRING::PushShortOffset( long TypeOffset, long Position ) { // We don't check the range for the offset here for better optimization.
pBufferType[ Position ] = FS_SHORT_OFFSET; pBufferType[ Position + 1 ] = FS_SMALL; *((short UNALIGNED *)(pBuffer + Position)) = (short)TypeOffset;
TypeOffsetDict.Insert( Position, TypeOffset ); }
//
// Push a stack size or an absolute offset.
//
void FORMAT_STRING::PushUShortStackOffsetOrSize( long X86Offset ) { CheckSize();
if ( X86Offset < 0 || X86Offset > _UI16_MAX ) { // Make it a warning with a name.
// CG_NDR * pNdr = pCCB->GetLastPlaceholderClass();
CG_NDR * pNdr = 0; char * pName = pNdr ? pNdr->GetSymName() : ""; RpcError(NULL, 0, STACK_SIZE_TOO_BIG, pName ); exit( FORMAT_STRING_LIMITS ); }
pBufferType[CurrentOffset] = FS_SHORT_STACK_OFFSET; pBufferType[CurrentOffset+1] = FS_SMALL; *((short UNALIGNED *)(pBuffer + CurrentOffset)) = (short) X86Offset;
#if defined(RKK_FRAG_OPT)
{ printf("PushShortStackOffset CurrentOffset %d\n", CurrentOffset ); int offLow = CurrentOffset - 10; if (offLow < 0) offLow = 0; int offHig = CurrentOffset + 10; printf(" off=%d ", offLow ); for (int off = offLow; off < offHig; off++) printf("%02x ", pBuffer[ off ]); printf( "\n" ); printf(" off=%d ", offLow ); for ( off = offLow; off < offHig; off++) printf("%02x ", pBufferType[ off ]); printf( "\n" ); } #endif
OffsetDict.Insert( (long) CurrentOffset, X86Offset );
IncrementOffset(2); }
//
// Push a stack offset.
// Needs to be relative because of offsets in structs etc.
//
void FORMAT_STRING::PushShortStackOffset( long X86Offset ) { CheckSize();
if ( X86Offset < _I16_MIN || X86Offset > _I16_MAX ) { // Make it a warning with a name.
// CG_NDR * pNdr = pCCB->GetLastPlaceholderClass();
CG_NDR * pNdr = 0; char * pName = pNdr ? pNdr->GetSymName() : ""; RpcError(NULL, 0, FORMAT_STRING_LIMITS, pName ); exit( FORMAT_STRING_LIMITS ); }
pBufferType[CurrentOffset] = FS_SHORT_STACK_OFFSET; pBufferType[CurrentOffset+1] = FS_SMALL; *((short UNALIGNED *)(pBuffer + CurrentOffset)) = (short) X86Offset;
#if defined(RKK_FRAG_OPT)
{ printf("PushShortStackOffset CurrentOffset %d\n", CurrentOffset ); int offLow = CurrentOffset - 10; if (offLow < 0) offLow = 0; int offHig = CurrentOffset + 10; printf(" off=%d ", offLow ); for (int off = offLow; off < offHig; off++) printf("%02x ", pBuffer[ off ]); printf( "\n" ); printf(" off=%d ", offLow ); for ( off = offLow; off < offHig; off++) printf("%02x ", pBufferType[ off ]); printf( "\n" ); } #endif
OffsetDict.Insert( (long) CurrentOffset, X86Offset );
IncrementOffset(2); }
// =============================================================================
//
// Helper routines writing comments about some tokens.
//
__inline void Out_PointerFlags( ISTREAM * pStream, unsigned char * pFlags ) { if ( *pFlags & FC_ALLOCATE_ALL_NODES ) pStream->Write( " [all_nodes]"); if ( *pFlags & FC_DONT_FREE ) pStream->Write( " [dont_free]"); if ( *pFlags & FC_ALLOCED_ON_STACK ) pStream->Write( " [alloced_on_stack]"); if ( *pFlags & FC_SIMPLE_POINTER ) pStream->Write( " [simple_pointer]"); if ( *pFlags & FC_POINTER_DEREF ) pStream->Write( " [pointer_deref]"); }
__inline void Out_OldProcFlags( ISTREAM * pStream, unsigned char * pFlags ) { INTERPRETER_FLAGS * pOiFlags = (INTERPRETER_FLAGS *)pFlags;
if ( pOiFlags->FullPtrUsed ) pStream->Write( " full ptr,"); if ( pOiFlags->RpcSsAllocUsed ) pStream->Write( " DCE mem package,"); if ( pOiFlags->ObjectProc ) { pStream->Write( " object,"); if ( pOiFlags->IgnoreObjectException ) pStream->Write( " ignore obj exc,"); if ( pOiFlags->HasCommOrFault ) pStream->Write( " Oi2"); } else { if ( pOiFlags->IgnoreObjectException ) pStream->Write( " encode,"); if ( pOiFlags->HasCommOrFault ) pStream->Write( " comm or fault/decode"); } }
__inline void Out_Oi2ProcFlags( ISTREAM * pStream, unsigned char * pFlags ) { INTERPRETER_OPT_FLAGS * pOi2Flags = (INTERPRETER_OPT_FLAGS *)pFlags;
if ( pOi2Flags->ServerMustSize ) pStream->Write( " srv must size,"); if ( pOi2Flags->ClientMustSize ) pStream->Write( " clt must size,"); if ( pOi2Flags->HasReturn ) pStream->Write( " has return,"); if ( pOi2Flags->HasPipes ) pStream->Write( " has pipes,"); if ( pOi2Flags->HasAsyncUuid ) pStream->Write( " has async uuid,"); if ( pOi2Flags->HasExtensions ) pStream->Write( " has ext,"); if ( pOi2Flags->HasAsyncHandle ) pStream->Write( " has async handle"); }
__inline void Out_ExtProcFlags( ISTREAM * pStream, unsigned char * pFlags ) { INTERPRETER_OPT_FLAGS2 * pExtFlags = (INTERPRETER_OPT_FLAGS2 *)pFlags;
if ( pExtFlags->HasNewCorrDesc ) pStream->Write( " new corr desc,"); if ( pExtFlags->ClientCorrCheck ) pStream->Write( " clt corr check,"); if ( pExtFlags->ServerCorrCheck ) pStream->Write( " srv corr check,"); if ( pExtFlags->HasNotify ) pStream->Write( " has notify"); if ( pExtFlags->HasNotify2 ) pStream->Write( " has notify_flag"); if ( pExtFlags->HasComplexReturn ) pStream->Write( " has complex return"); }
__inline void Out_ParameterFlags( ISTREAM * pStream, PARAM_ATTRIBUTES * pParamAttr ) { char Buf[8];
if ( pParamAttr->MustSize ) pStream->Write( " must size,"); if ( pParamAttr->MustFree ) pStream->Write( " must free,"); if ( pParamAttr->IsPipe ) pStream->Write( " pipe,"); if ( pParamAttr->IsIn ) pStream->Write( " in,"); if ( pParamAttr->IsOut ) pStream->Write( " out,"); if ( pParamAttr->IsReturn ) pStream->Write( " return,"); if ( pParamAttr->IsBasetype ) pStream->Write( " base type,"); if ( pParamAttr->IsByValue ) pStream->Write( " by val,"); if ( pParamAttr->IsSimpleRef ) pStream->Write( " simple ref,"); if ( pParamAttr->IsDontCallFreeInst ) pStream->Write( " dont call free inst,"); if ( pParamAttr->IsForceAllocate ) pStream->Write( " force allocate," ); if ( pParamAttr->SaveForAsyncFinish ) pStream->Write( " split async,"); if ( pParamAttr->ServerAllocSize ) { pStream->Write( " srv alloc size="); pStream->Write( MIDL_ITOA( 8 * pParamAttr->ServerAllocSize, Buf, 10) ); } }
__inline void Out_CorrelationType( ISTREAM * pStream, unsigned char * pCorrType ) { unsigned char CorrType = *pCorrType;
if ( CorrType & FC_NORMAL_CONFORMANCE ) pStream->Write( " field, "); if ( CorrType & FC_POINTER_CONFORMANCE ) pStream->Write( " field pointer, "); if ( CorrType & FC_TOP_LEVEL_CONFORMANCE ) pStream->Write( " parameter, "); if ( CorrType & FC_TOP_LEVEL_MULTID_CONFORMANCE ) pStream->Write( " multidim parameter, ");
if ( CorrType & FC_CONSTANT_CONFORMANCE ) { unsigned long ConstVal; char Buf[12];
pStream->Write( " constant, val="); // next three bytes: just a weird way of generating it
ConstVal = (ulong) pCorrType[1] << 16; ConstVal |= *(unsigned short UNALIGNED *)( pCorrType + 2); pStream->Write( MIDL_ITOA( ConstVal, Buf, 10) ); } else { pStream->Write( pFormatCharNames[ CorrType & 0xf ] ); } }
__inline void Out_CorrelationFlags( ISTREAM * pStream, unsigned char * pNewCorrFlags ) { NDR_CORRELATION_FLAGS * pCorrFlags = (NDR_CORRELATION_FLAGS *)pNewCorrFlags;
if ( pCorrFlags->Early ) pStream->Write( " early," ); if ( pCorrFlags->Split ) pStream->Write( " split," ); if ( pCorrFlags->IsIidIs ) pStream->Write( " iid_is," ); if ( pCorrFlags->DontCheck ) pStream->Write( " dont check" ); }
__inline void Out_ContextHandleFlags( ISTREAM * pStream, unsigned char * pContextFlags ) { PNDR_CONTEXT_HANDLE_FLAGS pFlags = (PNDR_CONTEXT_HANDLE_FLAGS)pContextFlags;
if ( pFlags->IsViaPtr ) pStream->Write( " via ptr," ); if ( pFlags->IsIn ) pStream->Write( " in," ); if ( pFlags->IsOut ) pStream->Write( " out," ); if ( pFlags->IsReturn ) pStream->Write( " ret," ); if ( pFlags->IsStrict ) pStream->Write( " strict," ); if ( pFlags->NoSerialize ) pStream->Write( " no serialize," ); if ( pFlags->Serialize ) pStream->Write( " serialize," ); if ( pFlags->CannotBeNull) pStream->Write( " can't be null" ); }
__inline void Out_SmallStackSize( ISTREAM * pStream, long StackSize, char * pEnvComment ) { char Buf[102]; //
// Non-Alpha stack size.
//
pStream->Write( "0x" ); pStream->Write( MIDL_ITOA(StackSize, Buf, 16) ); pStream->Write( ",\t\t/* "); pStream->Write( pEnvComment ); pStream->Write( " stack size = "); pStream->Write( MIDL_ITOA(StackSize, Buf, 10) ); pStream->Write( " */");
}
// The comment table is initialized in FORMAT_STRING::Output as appropriate
// for a given environment { 64b, 32b, others }.
// The comments correspond to the ifdef situation described below.
static char * Env64Comment = "ia64"; static char * Env32Comment = "x86"; static char * OtherEnvComment = "";
__inline void Out_ShortStackOffset( ISTREAM * pStream, OffsetDictElem * pStackOffsets, char * EnvComment ) { char Buf[102];
//
// Emit the main (x86 or ia64) offset.
//
unsigned long OffsetValue = pStackOffsets->X86Offset;
pStream->Write( "NdrFcShort( 0x" ); pStream->Write( MIDL_ITOA( OffsetValue, Buf, 16) ); pStream->Write( " ),\t/* " ); pStream->Write( EnvComment ); pStream->Write( " Stack size/offset = " ); pStream->Write( MIDL_ITOA( OffsetValue, Buf, 10) ); pStream->Write( " */"); }
void FORMAT_STRING::Output( ISTREAM * pStream, char * pTypeName, char * pName, RepAsPadExprDict * pPadDict, RepAsSizeDict * pSizeDict ) /*++
Routine Description : Outputs the format string structure.
Arguments : pStream - Stream to output the format string to.
--*/ { long Offset; long LastPrinted = 0; char Buf[102]; BOOL InPP = FALSE; REP_AS_PAD_EXPR_DESC * pPadExprDesc; REP_AS_SIZE_DESC * pSizeDesc; char * pComment; BOOL fLimitErr = FALSE;
pStream->NewLine(); pStream->Write( "static const " ); pStream->Write( pTypeName ); pStream->Write( ' ' ); pStream->Write( pName ); pStream->Write( " ="); pStream->IndentInc(); pStream->NewLine();
pStream->Write( '{' ); pStream->IndentInc(); pStream->NewLine();
pStream->Write( "0," ); pStream->NewLine();
pStream->Write( '{' ); pStream->IndentInc();
// Reset the pad and size macro dictionaries
pPadExprDesc = pPadDict->GetFirst(); pSizeDesc = pSizeDict->GetFirst();
pStream->IndentDec(); pStream->IndentDec(); pStream->IndentDec();
BOOL f32 = pCommand->GetEnv() == ENV_WIN32; BOOL f64 = pCommand->GetEnv() == ENV_WIN64;
char * EnvComment;
if ( f32 ) { EnvComment = Env32Comment; } else if ( f64 ) { EnvComment = Env64Comment; } else { EnvComment = OtherEnvComment; }
for ( Offset = 0; Offset < (long)LastOffset; ) { pStream->NewLine();
pComment = CommentDict.GetComments( Offset );
if ( pComment ) pStream->Write( pComment );
if ( ! (Offset % 2) && ( Offset != LastPrinted ) ) { sprintf(Buf,"/* %2d */\t",Offset); LastPrinted = Offset; pStream->Write(Buf); } else { pStream->Write("\t\t\t"); }
switch ( pBufferType[Offset] ) { case FS_FORMAT_CHARACTER : // Make the format string readable.
switch ( pBuffer[Offset] ) { case FC_IN_PARAM : case FC_IN_OUT_PARAM : case FC_PARTIAL_IGNORE_PARAM : case FC_OUT_PARAM : case FC_RETURN_PARAM : case FC_STRUCT : case FC_PSTRUCT : case FC_CSTRUCT : case FC_CPSTRUCT : case FC_CVSTRUCT : case FC_BOGUS_STRUCT : case FC_NO_REPEAT : case FC_FIXED_REPEAT : case FC_VARIABLE_REPEAT : case FC_CARRAY : case FC_CVARRAY : case FC_SMFARRAY : case FC_LGFARRAY : case FC_SMVARRAY : case FC_LGVARRAY : case FC_BOGUS_ARRAY : case FC_C_CSTRING : case FC_C_SSTRING : case FC_C_WSTRING : case FC_CSTRING : case FC_SSTRING : case FC_WSTRING : case FC_ENCAPSULATED_UNION : case FC_NON_ENCAPSULATED_UNION : case FC_IP : pStream->NewLine(); pStream->Write("\t\t\t"); break;
case FC_RP : case FC_UP : case FC_OP : case FC_FP : //
// If we're not in a pointer layout, and the previous
// format char was not a param/result char then print
// a new line.
//
if ( ! InPP && ( Offset && pBuffer[Offset - 1] != FC_IN_PARAM && pBuffer[Offset - 1] != FC_IN_OUT_PARAM && pBuffer[Offset - 1] != FC_PARTIAL_IGNORE_PARAM && pBuffer[Offset - 1] != FC_OUT_PARAM && pBuffer[Offset - 1] != FC_IN_PARAM_NO_FREE_INST && pBuffer[Offset - 1] != FC_RETURN_PARAM ) ) { pStream->NewLine(); pStream->Write("\t\t\t"); } break;
case FC_PP : InPP = TRUE; pStream->NewLine(); pStream->Write("\t\t\t"); break;
case FC_END : if ( InPP ) { pStream->NewLine(); pStream->Write("\t\t\t"); } break;
default: break; }
pStream->Write( "0x" ); pStream->Write( MIDL_ITOA( pBuffer[Offset], Buf, 16 ) ); pStream->Write( ",\t\t/* "); pStream->Write( pFormatCharNames[pBuffer[Offset]] ); pStream->Write( " */");
if ( (pBuffer[Offset] == FC_END) && InPP ) { pStream->NewLine(); InPP = FALSE; }
Offset++; break;
case FS_POINTER_FORMAT_CHARACTER : //
// If we're not in a pointer layout, and the previous
// format char was not a param/result char then print
// a new line.
//
if ( ! InPP && ( Offset && pBuffer[Offset - 1] != FC_IN_PARAM && pBuffer[Offset - 1] != FC_IN_OUT_PARAM && pBuffer[Offset - 1] != FC_PARTIAL_IGNORE_PARAM && pBuffer[Offset - 1] != FC_OUT_PARAM && pBuffer[Offset - 1] != FC_RETURN_PARAM ) ) { pStream->NewLine(); pStream->Write("\t\t\t"); }
pStream->Write( "0x" ); pStream->Write( MIDL_ITOA( pBuffer[Offset], Buf, 16 ) ); pStream->Write( ", 0x" ); pStream->Write( MIDL_ITOA( pBuffer[Offset + 1] & 0x00ff, Buf, 16 ) ); pStream->Write( ",\t/* "); pStream->Write( pFormatCharNames[pBuffer[Offset]] ); Out_PointerFlags( pStream, pBuffer + Offset + 1 ); pStream->Write( " */");
Offset += 2; break;
case FS_SMALL : pStream->Write( "0x" ); pStream->Write( MIDL_ITOA( pBuffer[Offset] & 0x00ff, Buf, 16 ) ); pStream->Write( ",\t\t/* "); pStream->Write( MIDL_ITOA( pBuffer[Offset], Buf, 10 ) ); pStream->Write( " */");
Offset++; break;
case FS_OLD_PROC_FLAG_BYTE : pStream->Write( "0x" ); pStream->Write( MIDL_ITOA( pBuffer[Offset] & 0x00ff, Buf, 16 ) ); pStream->Write( ",\t\t/* Old Flags: "); Out_OldProcFlags( pStream, pBuffer + Offset ); pStream->Write( " */");
Offset++; break;
case FS_Oi2_PROC_FLAG_BYTE : pStream->Write( "0x" ); pStream->Write( MIDL_ITOA( pBuffer[Offset] & 0x00ff, Buf, 16 ) ); pStream->Write( ",\t\t/* Oi2 Flags: "); Out_Oi2ProcFlags( pStream, pBuffer + Offset ); pStream->Write( " */");
Offset++; break;
case FS_EXT_PROC_FLAG_BYTE : pStream->Write( "0x" ); pStream->Write( MIDL_ITOA( pBuffer[Offset] & 0x00ff, Buf, 16 ) ); pStream->Write( ",\t\t/* Ext Flags: "); Out_ExtProcFlags( pStream, pBuffer + Offset ); pStream->Write( " */");
Offset++; break;
case FS_CORR_TYPE_BYTE : pStream->Write( "0x" ); pStream->Write( MIDL_ITOA( pBuffer[Offset] & 0x00ff, Buf, 16 ) ); pStream->Write( ",\t\t/* Corr desc: "); Out_CorrelationType( pStream, pBuffer + Offset ); pStream->Write( " */");
Offset++; break;
case FS_CONTEXT_HANDLE_FLAG_BYTE : pStream->Write( "0x" );
pStream->Write( MIDL_ITOA( pBuffer[Offset] & 0x00ff, Buf, 16 ) ); pStream->Write( ",\t\t/* Ctxt flags: "); Out_ContextHandleFlags( pStream, pBuffer + Offset ); pStream->Write( " */");
Offset++; break;
case FS_SHORT : pStream->Write( "NdrFcShort( 0x" ); sprintf(Buf, "%hx",*((unsigned short UNALIGNED *)(pBuffer + Offset)) ); pStream->Write( Buf ); pStream->Write( " ),\t/* "); pStream->Write( MIDL_ITOA(*((short UNALIGNED *)(pBuffer+Offset)), Buf, 10)); pStream->Write( " */");
Offset += 2; break; case FS_MAGIC_UNION_SHORT : pStream->Write( "NdrFcShort( 0x" ); sprintf(Buf, "%hx",*((unsigned short UNALIGNED *)(pBuffer + Offset)) ); pStream->Write( Buf ); pStream->Write( " ),\t/* Simple arm type: "); pStream->Write( pFormatCharNames[ pBuffer[Offset] ] ? pFormatCharNames[ pBuffer[Offset] ] : "" ); pStream->Write( " */");
Offset += 2; break; case FS_PARAM_FLAG_SHORT : pStream->Write( "NdrFcShort( 0x" ); sprintf(Buf, "%hx",*((unsigned short UNALIGNED *)(pBuffer + Offset)) ); pStream->Write( Buf ); pStream->Write( " ),\t/* Flags: "); Out_ParameterFlags( pStream, (PARAM_ATTRIBUTES *)(pBuffer + Offset) ); pStream->Write( " */");
Offset += 2; break; case FS_CORR_FLAG_SHORT : pStream->Write( "NdrFcShort( 0x" ); sprintf(Buf, "%hx",*((unsigned short UNALIGNED *)(pBuffer + Offset)) ); pStream->Write( Buf ); pStream->Write( " ),\t/* Corr flags: "); Out_CorrelationFlags( pStream, pBuffer + Offset ); pStream->Write( " */");
Offset += 2; break; case FS_SHORT_OFFSET : { // The relative type offset.
TypeOffsetDictElem * pTO; long ItsOffset; ItsOffset = *((short UNALIGNED *)(pBuffer + Offset)); pTO = TypeOffsetDict.LookupOffset( Offset );
if ( pTO->TypeOffset != ItsOffset || pTO->TypeOffset < UNION_OFFSET16_MIN ) { pStream->Write( "Relative type offset out of range" ); pStream->NewLine(); RpcError(NULL, 0, FORMAT_STRING_LIMITS, "" ); fLimitErr = TRUE; } if ( 0 == ( pTO->TypeOffset + Offset ) || -1 == ( pTO->TypeOffset + Offset ) ) { fprintf( stdout, " MIDL_fixup: Invalid offset at %d\n", Offset ); RpcError( NULL, 0, FORMAT_STRING_OFFSET_IS_ZERO, "" ); }
pStream->Write( "NdrFcShort( 0x" ); sprintf(Buf, "%hx",ItsOffset ); pStream->Write( Buf ); pStream->Write( " ),\t/* Offset= "); pStream->Write( MIDL_ITOA( pTO->TypeOffset, Buf, 10 ) ); pStream->Write( " ("); pStream->Write( MIDL_ITOA( pTO->TypeOffset + Offset, Buf, 10 ) ); pStream->Write( ") */");
Offset += 2; } break;
case FS_SHORT_TYPE_OFFSET : { // The absolute type offset.
TypeOffsetDictElem * pTO; long ItsOffset; ItsOffset = *((unsigned short UNALIGNED *)(pBuffer + Offset));
pTO = TypeOffsetDict.LookupOffset( Offset );
if ( pTO->TypeOffset != ItsOffset ) { pStream->Write( "Type offset out of range" ); pStream->NewLine(); RpcError(NULL, 0, FORMAT_STRING_LIMITS, "" ); fLimitErr = TRUE; } if ( 0 == pTO->TypeOffset || -1 == pTO->TypeOffset ) { fprintf( stdout, " MIDL_fixup: Invalid type offset at %d\n", Offset ); RpcError( NULL, 0, TYPE_OFFSET_IS_ZERO, "" ); }
pStream->Write( "NdrFcShort( 0x" ); sprintf(Buf, "%hx",ItsOffset ); pStream->Write( Buf ); pStream->Write( " ),\t/* Type Offset="); pStream->Write( MIDL_ITOA( pTO->TypeOffset, Buf, 10 ) ); pStream->Write( " */");
Offset += 2; } break;
case FS_SHORT_STACK_OFFSET : { Out_ShortStackOffset( pStream, OffsetDict.LookupOffset( Offset ), EnvComment ); Offset += 2;
break; } case FS_SMALL_STACK_SIZE : { Out_SmallStackSize( pStream, pBuffer[Offset], EnvComment ); Offset++;
break; }
case FS_LONG : pStream->Write( "NdrFcLong( 0x" ); pStream->Write( MIDL_LTOA( *((long UNALIGNED *)(pBuffer+Offset)), Buf, 16)); pStream->Write( " ),\t/* "); pStream->Write( MIDL_LTOA(*((long UNALIGNED *)(pBuffer+Offset)), Buf, 10)); pStream->Write( " */"); Offset += 4; break;
case FS_PAD_MACRO :
if ( pPadExprDesc ) { MIDL_ASSERT( Offset == (long)pPadExprDesc->KeyOffset );
pPadDict->WriteCurrentPadDesc( pStream ); pPadExprDesc = pPadDict->GetNext(); } else { pStream->Write( "0x0,\t\t/* macro */" ); MIDL_ASSERT( 0 && "Pad macro missing" ); }
Offset++; break;
case FS_SIZE_MACRO :
if ( pSizeDesc ) { MIDL_ASSERT( Offset == (long)pSizeDesc->KeyOffset );
pSizeDict->WriteCurrentSizeDesc( pStream ); pSizeDesc = pSizeDict->GetNext(); } else { pStream->Write( "0x0, 0x0,\t\t// macro" ); MIDL_ASSERT( 0 && "Size macro missing" ); }
Offset += 2; break;
case FS_UNKNOWN_STACK_SIZE : { char * LongBuf = Buf; long NameLen = (long) strlen( UnknownStackSizeDict.LookupTypeName( (long) Offset )); if ( NameLen > 25 ) LongBuf = new char[ 75 + NameLen ];
sprintf( LongBuf, "%s ( (sizeof(%s) + %s) & ~ (%s) ),", "(unsigned char)", UnknownStackSizeDict.LookupTypeName( (long) Offset ), "sizeof(int) - 1", "sizeof(int) - 1" );
pStream->Write( LongBuf ); } Offset++; break; } }
pStream->NewLine( 2 );
//
// Spit out a terminating 0 so we don't ever fall off the end
// of the world.
//
pStream->Write( "\t\t\t0x0" );
pStream->IndentInc(); pStream->IndentInc(); pStream->IndentInc();
pStream->IndentDec(); pStream->NewLine();
pStream->Write( '}' ); pStream->IndentDec(); pStream->NewLine();
pStream->Write( "};" ); pStream->IndentDec(); pStream->NewLine();
if ( LastOffset > _UI16_MAX ) { pStream->Write( "Total Format String size is too big." ); pStream->NewLine(); fprintf(stdout, "Total Format String size = %d\n", LastOffset ); RpcError(NULL, 0, FORMAT_STRING_LIMITS, "" ); fLimitErr = TRUE; }
if ( fLimitErr ) exit( FORMAT_STRING_LIMITS ); }
long FORMAT_STRING::OptimizeFragment( CG_NDR * pNode ) /*++
Routine Description : Optimize a format string fragment away.
Arguments : pNode - CG_NDR node, with format string start and end offsets already set.
--*/ { long StartOffset = pNode->GetFormatStringOffset(); long EndOffset = pNode->GetFormatStringEndOffset();
FRMTREG_ENTRY NewFragment( StartOffset, EndOffset ); FRMTREG_ENTRY * pOldFragment;
// perform format string optimization
#if defined(RKK_FRAG_OPT)
{ printf("Optimizing: start=%d, end=%d\n", StartOffset, EndOffset);
printf(" off str=%d ", StartOffset ); for (int off = StartOffset; off <= EndOffset; off++) printf("%02x ", pBuffer[ off ]); printf( "\n" ); printf(" off typ=%d ", StartOffset ); for ( off = StartOffset; off <= EndOffset; off++) printf("%02x ", pBufferType[ off ]); printf( "\n" ); } #endif
if ( pCommand->IsSwitchDefined( SWITCH_NO_FMT_OPT ) ) return StartOffset;
// We attempt to optimize fragments even if they are apart by more than 32k.
MIDL_ASSERT ( EndOffset <= (long)LastOffset );
// add to dictionary
// if match found, reset format string offset back to our start
if ( GetReuseDict()->GetReUseEntry( pOldFragment, &NewFragment ) ) { long OldStartOffset = pOldFragment->GetStartOffset();
// if we are not the end, we can't do anything about ourselves
// similarly, if we match ourselves, don't do anything
if ( ( GetCurrentOffset() == EndOffset ) && ( OldStartOffset != StartOffset ) ) { // move format string offset back
SetCurrentOffset( StartOffset ); pNode->SetFormatStringOffset( OldStartOffset ); pNode->SetFormatStringEndOffset( pOldFragment->GetEndOffset() ); return OldStartOffset; }
#if defined(RKK_FRAG_OPT)
else if ( GetCurrentOffset() != EndOffset ) { printf( "OptimizeFragment fragment not at the end End=%d, frag End=%d\n", GetCurrentOffset(), EndOffset ); } #endif
} // duplicate found
return StartOffset;
}
unsigned short FORMAT_STRING::RegisterFragment( CG_NDR * pNode ) /*++
Routine Description : Register, but do not remove, a format string fragment.
Arguments : pNode - CG_NDR node, with format string start offset already set. EndOffset - end offset of format string fragment
--*/ { unsigned short StartOffset = (unsigned short) pNode->GetFormatStringOffset(); unsigned short EndOffset = (unsigned short) pNode->GetFormatStringEndOffset(); FRMTREG_ENTRY NewFragment( StartOffset, EndOffset ); FRMTREG_ENTRY * pOldFragment;
// perform format string optimization
if ( pCommand->IsSwitchDefined( SWITCH_NO_FMT_OPT ) ) return StartOffset;
MIDL_ASSERT( ( ((short) StartOffset) != -1 ) && ( ((short) EndOffset) != -1 ) ); MIDL_ASSERT ( EndOffset <= LastOffset );
// add to dictionary, or return pointer to old entry
GetReuseDict()->GetReUseEntry( pOldFragment, &NewFragment );
return StartOffset;
}
char * CommentDictionary::GetComments( long Offset ) { CommentDictElem Elem; CommentDictElem * pHead; CommentDictElem * pElem; Dict_Status DictStatus; char * Comments; long Length;
Elem.FormatStringOffset = Offset;
DictStatus = Dict_Find( &Elem );
if ( DictStatus != SUCCESS ) return 0;
pHead = (CommentDictElem *) Dict_Item();
Length = 0;
for ( pElem = pHead; pElem; pElem = pElem->Next ) Length += (long) strlen( pElem->Comment );
Comments = new char[Length+1]; Comments[0] = 0;
for ( pElem = pHead; pElem; pElem = pElem->Next ) strcat( Comments, pElem->Comment );
return Comments; }
void CommentDictionary::Insert( long FormatStringOffset, char * Comment ) { CommentDictElem Elem; CommentDictElem * pHead; CommentDictElem * pElem; Dict_Status DictStatus;
Elem.FormatStringOffset = FormatStringOffset;
DictStatus = Dict_Find( &Elem );
if ( DictStatus == SUCCESS ) pHead = (CommentDictElem *) Dict_Item(); else pHead = 0;
pElem = new CommentDictElem;
pElem->Next = pHead; pElem->FormatStringOffset = FormatStringOffset; pElem->Comment = Comment;
//
// We delete any current entry and add a new entry so that comments
// are always prepended to the list.
//
if ( pHead ) Dict_Delete( (pUserType *) &pHead );
Dict_Insert( pElem ); }
|