1254 lines
33 KiB
C++
1254 lines
33 KiB
C++
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
Copyright (c) 1989-2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
pickle.cxx
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Generates stub routines to call the pickle engine.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
|
||
|
History:
|
||
|
|
||
|
Mar-22-1994 VibhasC Created
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
|
||
|
/****************************************************************************
|
||
|
* include files
|
||
|
***************************************************************************/
|
||
|
#include "becls.hxx"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#pragma warning ( disable : 4127 )
|
||
|
|
||
|
#include "szbuffer.h"
|
||
|
|
||
|
/****************************************************************************
|
||
|
* local definitions
|
||
|
***************************************************************************/
|
||
|
|
||
|
/****************************************************************************
|
||
|
* local data
|
||
|
***************************************************************************/
|
||
|
|
||
|
/****************************************************************************
|
||
|
* externs
|
||
|
***************************************************************************/
|
||
|
/****************************************************************************/
|
||
|
|
||
|
|
||
|
CG_STATUS
|
||
|
CG_ENCODE_PROC::GenClientStubV1(
|
||
|
CCB * pCCB )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Generate DCE style procedure pickling stub code for the V1 interpreter.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - The code gen controller block.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
CG_OK
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
ISTREAM * pStream = pCCB->GetStream();
|
||
|
|
||
|
// Register this procedure as a proc-encoding procedure.
|
||
|
|
||
|
pCCB->RegisterEncodeDecodeProc( this );
|
||
|
|
||
|
// Generate the format strings.
|
||
|
|
||
|
MIDL_ASSERT( pCommand->IsNDRRun() );
|
||
|
GenNdrFormat( pCCB );
|
||
|
|
||
|
// Print the prolog of procedure.
|
||
|
|
||
|
Out_ClientProcedureProlog( pCCB, GetType() );
|
||
|
|
||
|
// If there exists a return type, declare a local resource of that
|
||
|
// type.
|
||
|
|
||
|
if( GetReturnType() )
|
||
|
{
|
||
|
node_id *node = MakeIDNode( RETURN_VALUE_VAR_NAME, GetReturnType()->GetType() );
|
||
|
|
||
|
pStream->Write( " " );
|
||
|
node->PrintType(
|
||
|
(PRT_PARAM_WITH_TYPE | PRT_CSTUB_PREFIX),
|
||
|
pStream,
|
||
|
(node_skl *)0 );
|
||
|
pStream->NewLine();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The V1 interpreter calls NdrMesProcEncodeDecode and passes the addresses
|
||
|
// of all the parameters that were passed to the stub.
|
||
|
//
|
||
|
|
||
|
GenMesProcEncodeDecodeCall( pCCB, PROC_PLATFORM_V1_INTERPRETER );
|
||
|
|
||
|
GenEpilog( pCCB );
|
||
|
|
||
|
return CG_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
CG_STATUS
|
||
|
CG_ENCODE_PROC::GenClientStub(
|
||
|
CCB * pCCB )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Generate DCE style procedure pickling stub code.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - The code gen controller block.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
CG_OK
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
if ( ! ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 ) )
|
||
|
return GenClientStubV1( pCCB );
|
||
|
|
||
|
ISTREAM * pStream = pCCB->GetStream();
|
||
|
|
||
|
// Register this procedure as a proc-encoding procedure.
|
||
|
|
||
|
pCCB->RegisterEncodeDecodeProc( this );
|
||
|
|
||
|
// Generate the format strings.
|
||
|
|
||
|
if ( pCommand->IsNDRRun() )
|
||
|
{
|
||
|
GenNdrFormat( pCCB );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pCCB->GetNdr64Format()->Generate( this );
|
||
|
}
|
||
|
|
||
|
// Print the prolog of procedure.
|
||
|
|
||
|
Out_ClientProcedureProlog( pCCB, GetType() );
|
||
|
|
||
|
// If there exists a return type, declare a local resource of that
|
||
|
// type.
|
||
|
|
||
|
if( GetReturnType() || HasComplexReturnType() )
|
||
|
{
|
||
|
pStream->IndentInc();
|
||
|
|
||
|
if ( HasComplexReturnType() )
|
||
|
{
|
||
|
pStream->NewLine();
|
||
|
( (node_proc *) GetType() )
|
||
|
->GetReturnType()->PrintType(PRT_DECL, pStream);
|
||
|
}
|
||
|
else
|
||
|
pStream->WriteOnNewLine( "CLIENT_CALL_RETURN " );
|
||
|
|
||
|
pStream->Write( RETURN_VALUE_VAR_NAME ";" );
|
||
|
pStream->IndentDec();
|
||
|
pStream->NewLine( 2 );
|
||
|
}
|
||
|
|
||
|
// Generate ia64 or x86 code
|
||
|
|
||
|
if ( pCommand->Is64BitEnv() )
|
||
|
{
|
||
|
GenMesProcEncodeDecodeCall( pCCB, PROC_PLATFORM_IA64) ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GenMesProcEncodeDecodeCall( pCCB, PROC_PLATFORM_X86 );
|
||
|
}
|
||
|
|
||
|
if ( GetReturnType() || HasComplexReturnType() )
|
||
|
{
|
||
|
CG_NDR* pNdr;
|
||
|
node_skl* pType;
|
||
|
|
||
|
if ( GetReturnType() )
|
||
|
{
|
||
|
pNdr = (CG_NDR *) GetReturnType()->GetChild();
|
||
|
pType = GetReturnType()->GetType();
|
||
|
}
|
||
|
|
||
|
pStream->NewLine( 2 );
|
||
|
pStream->Write("return ");
|
||
|
|
||
|
//
|
||
|
// byval structures, unions, floats, doubles
|
||
|
//
|
||
|
|
||
|
if ( HasComplexReturnType() )
|
||
|
{
|
||
|
pStream->Write( RETURN_VALUE_VAR_NAME ";");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Base type return value.
|
||
|
//
|
||
|
else if ( pNdr->IsSimpleType() )
|
||
|
{
|
||
|
pType->PrintType( PRT_CAST_TO_TYPE, pStream );
|
||
|
pStream->Write( RETURN_VALUE_VAR_NAME ".Simple;" );
|
||
|
}
|
||
|
//
|
||
|
// old-style byval structs and unions
|
||
|
//
|
||
|
else if ( pNdr->IsStruct() || pNdr->IsUnion() )
|
||
|
{
|
||
|
expr_node * pExpr;
|
||
|
|
||
|
pExpr = new expr_variable( RETURN_VALUE_VAR_NAME ".Pointer" );
|
||
|
|
||
|
pExpr = MakeDerefExpressionOfCastPtrToType( pType, pExpr );
|
||
|
|
||
|
pExpr->Print( pStream );
|
||
|
|
||
|
pStream->Write( ';' );
|
||
|
}
|
||
|
//
|
||
|
// Otherwise pointer or array.
|
||
|
//
|
||
|
else
|
||
|
{
|
||
|
pType->PrintType( PRT_CAST_TO_TYPE, pStream );
|
||
|
pStream->Write( RETURN_VALUE_VAR_NAME ".Pointer;" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pStream->IndentDec();
|
||
|
pStream->WriteOnNewLine("}");
|
||
|
|
||
|
return CG_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
CG_STATUS
|
||
|
CG_ENCODE_PROC::GenMesProcEncodeDecodeCall(
|
||
|
CCB * pCCB,
|
||
|
PROC_CALL_PLATFORM Platform )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Generate DCE style procedure pickling stub code.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - The code gen controller block.
|
||
|
Platform - ia64, etc
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
CG_OK
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
expr_proc_call * pProc;
|
||
|
node_skl * pType;
|
||
|
expr_node * pExpr;
|
||
|
CG_ITERATOR I;
|
||
|
CG_PARAM * pCG;
|
||
|
ISTREAM * pStream = pCCB->GetStream();
|
||
|
PNAME pHandleName;
|
||
|
RESOURCE * pReturnResource = 0;
|
||
|
bool fOutputConstantZero = true;
|
||
|
|
||
|
//
|
||
|
// Generate a call to the single encode proc engine call.
|
||
|
|
||
|
if ( pCommand->NeedsNDR64Run() )
|
||
|
pProc = new expr_proc_call( "NdrMesProcEncodeDecode3" );
|
||
|
else if ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 )
|
||
|
pProc = new expr_proc_call( PROC_ENCODE_DECODE_RTN_NAME2 );
|
||
|
else
|
||
|
pProc = new expr_proc_call( PROC_ENCODE_DECODE_RTN_NAME );
|
||
|
|
||
|
// Handle. If the handle is explicit, then it must be a MIDL_ES_HANDLE
|
||
|
|
||
|
if( GetHandleUsage() == HU_EXPLICIT )
|
||
|
{
|
||
|
pHandleName = SearchForBindingParam()->GetName();
|
||
|
pType = MakeIDNodeFromTypeName( pHandleName,
|
||
|
MIDL_ES_HANDLE_TYPE_NAME );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MIDL_ASSERT( pCCB->GetInterfaceCG()->GetImplicitHandle() != 0 );
|
||
|
|
||
|
pType = (node_id *)pCCB->GetInterfaceCG()->GetImplicitHandle()->
|
||
|
GetHandleIDOrParam();
|
||
|
pHandleName = pType->GetSymName();
|
||
|
}
|
||
|
|
||
|
pProc->SetParam( new expr_variable( pHandleName, pType ) );
|
||
|
|
||
|
// ProcEncodeDecode3 needs a proxy info and a proc number. 1 and 2
|
||
|
// need a stub descriptor and a format string
|
||
|
|
||
|
if ( pCommand->NeedsNDR64Run() )
|
||
|
{
|
||
|
long ProcNum = GetProcNum();
|
||
|
|
||
|
pExpr = new expr_variable(pCCB->GetInterfaceCG()->GetProxyInfoName());
|
||
|
pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
|
||
|
pExpr = MakeExpressionOfCastToTypeName(
|
||
|
PMIDL_PROXY_INFO_TYPE_NAME,
|
||
|
pExpr);
|
||
|
|
||
|
pProc->SetParam( new expr_param( pExpr ) );
|
||
|
pProc->SetParam( new expr_param( new expr_constant( ProcNum ) ) );
|
||
|
|
||
|
if ( HasComplexReturnType() )
|
||
|
{
|
||
|
pExpr = new expr_variable( RETURN_VALUE_VAR_NAME );
|
||
|
pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pExpr = new expr_param( new expr_constant( (long) 0 ) );
|
||
|
}
|
||
|
|
||
|
pProc->SetParam( pExpr );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Stub descriptor.
|
||
|
|
||
|
pExpr = new RESOURCE( pCCB->GetInterfaceCG()->GetStubDescName(),
|
||
|
(node_skl *)0 );
|
||
|
|
||
|
pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
|
||
|
pExpr = MakeExpressionOfCastToTypeName( PSTUB_DESC_STRUCT_TYPE_NAME,
|
||
|
pExpr );
|
||
|
|
||
|
pProc->SetParam( pExpr );
|
||
|
|
||
|
// Offset into the format string.
|
||
|
|
||
|
pExpr = Make_1_ArrayExpressionFromVarName(
|
||
|
PROC_FORMAT_STRING_STRING_FIELD,
|
||
|
GetFormatStringOffset() );
|
||
|
|
||
|
pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
|
||
|
pExpr = MakeExpressionOfCastToTypeName(
|
||
|
PFORMAT_STRING_TYPE_NAME,
|
||
|
pExpr );
|
||
|
pProc->SetParam( pExpr );
|
||
|
}
|
||
|
|
||
|
switch ( Platform )
|
||
|
{
|
||
|
case PROC_PLATFORM_V1_INTERPRETER:
|
||
|
{
|
||
|
// Parameters to the engine are the address of each of the parameters to
|
||
|
// this procedure. If there is no parameter AND no return type, push a
|
||
|
// null (0).
|
||
|
|
||
|
if( GetMembers( I ) )
|
||
|
{
|
||
|
fOutputConstantZero = false;
|
||
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
||
|
{
|
||
|
pExpr = new expr_variable( pCG->GetType()->GetSymName(),
|
||
|
pCG->GetType());
|
||
|
pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
|
||
|
pExpr = MakeCastExprPtrToUChar( pExpr );
|
||
|
pProc->SetParam( pExpr );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case PROC_PLATFORM_IA64:
|
||
|
{
|
||
|
// Parameters to the engine are the actual parameter to this
|
||
|
// this procedure. If there is no parameter AND no return type, push a
|
||
|
// null (0).
|
||
|
|
||
|
if( GetMembers( I ) )
|
||
|
{
|
||
|
fOutputConstantZero = false;
|
||
|
while( ITERATOR_GETNEXT( I, pCG ) )
|
||
|
{
|
||
|
pExpr = new expr_variable( pCG->GetType()->GetSymName(),
|
||
|
pCG->GetType());
|
||
|
pProc->SetParam( pExpr );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default: // PROC_PLATFORM_DEFAULT (i.e. x86)
|
||
|
{
|
||
|
CG_PARAM * pParam = (CG_PARAM *) GetChild();
|
||
|
|
||
|
if (NULL != pParam)
|
||
|
{
|
||
|
fOutputConstantZero = false;
|
||
|
pExpr = new expr_variable( pParam->GetType()->GetSymName(), pParam->GetType() );
|
||
|
pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
|
||
|
pExpr = MakeCastExprPtrToUChar( pExpr );
|
||
|
pProc->SetParam( pExpr );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If there is a return value, for the V1 interpreter add another
|
||
|
// parameter to the generated procedure expression. For the V2
|
||
|
// interpreter assign the return value from the engine to the local
|
||
|
// return value variable.
|
||
|
//
|
||
|
|
||
|
expr_node *pFinalExpr = pProc;
|
||
|
|
||
|
if( GetReturnType() && !HasComplexReturnType() )
|
||
|
{
|
||
|
|
||
|
if ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 )
|
||
|
{
|
||
|
pFinalExpr = new expr_assign(
|
||
|
new expr_variable( RETURN_VALUE_VAR_NAME ),
|
||
|
pProc );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pReturnResource = new RESOURCE( RETURN_VALUE_VAR_NAME,
|
||
|
GetReturnType()->GetType() );
|
||
|
pExpr = MakeAddressExpressionNoMatterWhat( pReturnResource );
|
||
|
pExpr = MakeCastExprPtrToUChar( pExpr );
|
||
|
pProc->SetParam( pExpr );
|
||
|
}
|
||
|
}
|
||
|
else if (fOutputConstantZero )
|
||
|
{
|
||
|
pProc->SetParam( new expr_constant( 0L ) );
|
||
|
}
|
||
|
|
||
|
// Now print the call out.
|
||
|
|
||
|
pStream->IndentInc();
|
||
|
pStream->NewLine();
|
||
|
|
||
|
pFinalExpr->PrintCall( pStream, 0, 0 );
|
||
|
|
||
|
pStream->NewLine();
|
||
|
pStream->IndentDec();
|
||
|
|
||
|
return CG_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
CG_STATUS
|
||
|
CG_TYPE_ENCODE_PROC::GenClientStub(
|
||
|
CCB * pCCB )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Generate the client side type encoding stub for this proc.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - The code gen controller block.
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
CG_OK
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
This proc node hanging under the encode interface node is really a dummy
|
||
|
proc, put in so that the format string generator can have a placeholder
|
||
|
node to look at.
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
return ((CG_PARAM *)GetChild())->GenTypeEncodingStub( pCCB );
|
||
|
}
|
||
|
|
||
|
|
||
|
CG_STATUS
|
||
|
CG_PARAM::GenTypeEncodingStub(
|
||
|
CCB * pCCB )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Generate the client side type encoding stub for this param.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - The code gen controller block.
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
CG_OK
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
This param is really a dummy param, put in so that the format string
|
||
|
generator can have a placeholder node to look at.
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
CG_STATUS Status;
|
||
|
CG_NDR * pLast = pCCB->SetLastPlaceholderClass( this );
|
||
|
|
||
|
Status = ((CG_TYPE_ENCODE *)GetChild())->GenTypeEncodingStub( pCCB );
|
||
|
|
||
|
pCCB->SetLastPlaceholderClass( pLast );
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
CG_STATUS
|
||
|
CG_TYPE_ENCODE::GenTypeEncodingStub(
|
||
|
CCB * pCCB )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Generate the pickling stubs for a given type.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - A pointer to the code generator control block.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
CG_OK
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
Emit the Type_Encode(), Type_Size() and Type_Decode() routines.
|
||
|
If the encode is needed, then sizing is needed too !.
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
CG_NDR * pChild = (CG_NDR *)GetChild();
|
||
|
|
||
|
// Generate the ndr format for the types.
|
||
|
|
||
|
if( ! pChild->IsSimpleType() )
|
||
|
{
|
||
|
if ( pCommand->IsNDRRun() )
|
||
|
pChild->GenNdrFormat( pCCB );
|
||
|
else
|
||
|
pCCB->GetNdr64Format()->Generate( pChild );
|
||
|
|
||
|
// Register this type so we can output a table of type offsets later
|
||
|
|
||
|
if ( pCommand->NeedsNDR64Run() )
|
||
|
TypeIndex = pCCB->RegisterPickledType( this );
|
||
|
}
|
||
|
|
||
|
// Check if implicit binding exists.
|
||
|
|
||
|
if( pCCB->GetInterfaceCG()->GetImplicitHandle() )
|
||
|
{
|
||
|
SetHasImplicitHandle();
|
||
|
}
|
||
|
|
||
|
// Create a resource dictionary database.
|
||
|
|
||
|
pCCB->SetResDictDatabase( new RESOURCE_DICT_DATABASE );
|
||
|
pCCB->ClearParamResourceDict();
|
||
|
|
||
|
if ( ! pCCB->HasTypePicklingInfoBeenEmitted() &&
|
||
|
( pCommand->GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 ) )
|
||
|
{
|
||
|
Out_TypePicklingInfo( pCCB );
|
||
|
pCCB->SetTypePicklingInfoEmitted();
|
||
|
}
|
||
|
|
||
|
// If the type has [encode] on it, generate the sizing and encode routines.
|
||
|
|
||
|
if( IsEncode() )
|
||
|
{
|
||
|
// Allocate standard resources for type encoding.
|
||
|
|
||
|
AllocateEncodeResources( pCCB );
|
||
|
|
||
|
// Generate the sizing and encode routines.
|
||
|
|
||
|
GenTypeSize( pCCB );
|
||
|
GenTypeEncode( pCCB );
|
||
|
|
||
|
}
|
||
|
|
||
|
pCCB->ClearParamResourceDict();
|
||
|
|
||
|
// If the type has [decode] on it, generate the decode routine.
|
||
|
|
||
|
if( IsDecode() )
|
||
|
{
|
||
|
// Allocate standard resources for type decoding.
|
||
|
|
||
|
AllocateEncodeResources( pCCB );
|
||
|
|
||
|
GenTypeDecode( pCCB );
|
||
|
GenTypeFree( pCCB );
|
||
|
}
|
||
|
|
||
|
return CG_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
CG_STATUS
|
||
|
CG_TYPE_ENCODE::GenTypeSize(
|
||
|
CCB * pCCB )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Generate the type sizing routine for the type.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - The code gen controller block.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
CG_OK
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
ISTREAM * pStream = pCCB->GetStream();
|
||
|
PNAME pName;
|
||
|
TYPE_ENCODE_INFO * pTEInfo = new TYPE_ENCODE_INFO;
|
||
|
|
||
|
// Generate the standard prototype. This really means emit the proto of
|
||
|
// the proc in the stub file. Remember, a real proc node does not exist
|
||
|
// for this pickling type. So we emit a prototype by hand (so to speak).
|
||
|
// The body of the function is output later,
|
||
|
|
||
|
GenStdMesPrototype( pCCB,
|
||
|
(pName = GetType()->GetSymName()),
|
||
|
TYPE_ALIGN_SIZE_CODE,
|
||
|
HasImplicitHandle()
|
||
|
);
|
||
|
|
||
|
pStream->NewLine();
|
||
|
pStream->Write( '{' );
|
||
|
pStream->IndentInc();
|
||
|
pStream->NewLine();
|
||
|
|
||
|
// The procedure body consists of a single procedure call.
|
||
|
|
||
|
expr_proc_call * pProc = CreateStdMesEngineProc( pCCB, TYPE_ALIGN_SIZE_CODE);
|
||
|
|
||
|
pStream->Write( "return " );
|
||
|
pProc->PrintCall( pStream, 0, 0 );
|
||
|
|
||
|
// Terminate the procedure body.
|
||
|
|
||
|
pStream->IndentDec();
|
||
|
pStream->NewLine();
|
||
|
pStream->Write( '}' );
|
||
|
pStream->NewLine();
|
||
|
|
||
|
// Register the routine with the ccb to enable emitting of prototypes.
|
||
|
|
||
|
pTEInfo->pName = pName;
|
||
|
pTEInfo->Flags = HasImplicitHandle() ? TYPE_ENCODE_WITH_IMPL_HANDLE : TYPE_ENCODE_FLAGS_NONE;
|
||
|
pCCB->RegisterTypeAlignSize( pTEInfo );
|
||
|
|
||
|
return CG_OK;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
CG_STATUS
|
||
|
CG_TYPE_ENCODE::GenTypeEncode(
|
||
|
CCB * pCCB )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Generate the type encoding routine for the type.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - The code gen controller block.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
CG_OK
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
ISTREAM * pStream = pCCB->GetStream();
|
||
|
PNAME pName;
|
||
|
TYPE_ENCODE_INFO * pTEInfo = new TYPE_ENCODE_INFO;
|
||
|
|
||
|
// Generate the standard prototype. This really means emit the proto of
|
||
|
// the proc in the stub file. The body of the function output later,
|
||
|
|
||
|
GenStdMesPrototype( pCCB,
|
||
|
(pName = GetType()->GetSymName()),
|
||
|
TYPE_ENCODE_CODE,
|
||
|
HasImplicitHandle()
|
||
|
);
|
||
|
|
||
|
pStream->NewLine();
|
||
|
pStream->Write( '{' );
|
||
|
pStream->IndentInc();pStream->NewLine();
|
||
|
|
||
|
// The procedure body consists of a single procedure call.
|
||
|
|
||
|
expr_proc_call * pProc = CreateStdMesEngineProc( pCCB, TYPE_ENCODE_CODE);
|
||
|
|
||
|
pProc->PrintCall( pCCB->GetStream(), 0, 0 );
|
||
|
|
||
|
// Terminate the procedure body.
|
||
|
|
||
|
pStream->IndentDec();
|
||
|
pStream->NewLine();
|
||
|
pStream->Write( '}' );
|
||
|
pStream->NewLine();
|
||
|
|
||
|
// Register the routine with the ccb to enable emitting of prototypes.
|
||
|
|
||
|
pTEInfo->pName = pName;
|
||
|
pTEInfo->Flags = HasImplicitHandle() ? TYPE_ENCODE_WITH_IMPL_HANDLE : TYPE_ENCODE_FLAGS_NONE;
|
||
|
pCCB->RegisterTypeEncode( pTEInfo );
|
||
|
|
||
|
return CG_OK;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
CG_STATUS
|
||
|
CG_TYPE_ENCODE::GenTypeDecode(
|
||
|
CCB * pCCB )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Generate the type sizing routine for the type.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - The code gen controller block.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
CG_OK
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
ISTREAM * pStream = pCCB->GetStream();
|
||
|
PNAME pName;
|
||
|
TYPE_ENCODE_INFO * pTEInfo = new TYPE_ENCODE_INFO;
|
||
|
|
||
|
// Generate the standard prototype. This really means emit the proto of
|
||
|
// the proc in the stub file. The body of the function output later,
|
||
|
|
||
|
GenStdMesPrototype( pCCB,
|
||
|
( pName = GetType()->GetSymName()),
|
||
|
TYPE_DECODE_CODE,
|
||
|
HasImplicitHandle()
|
||
|
);
|
||
|
|
||
|
pStream->NewLine();
|
||
|
pStream->Write( '{' );
|
||
|
pStream->IndentInc();pStream->NewLine();
|
||
|
|
||
|
// The procedure body consists of a single procedure call.
|
||
|
|
||
|
expr_proc_call * pProc = CreateStdMesEngineProc( pCCB, TYPE_DECODE_CODE);
|
||
|
|
||
|
pProc->PrintCall( pCCB->GetStream(), 0, 0 );
|
||
|
|
||
|
// Terminate the procedure body.
|
||
|
|
||
|
pStream->IndentDec();
|
||
|
pStream->NewLine();
|
||
|
pStream->Write( '}' );
|
||
|
pStream->NewLine();
|
||
|
|
||
|
// Register the routine with the ccb to enable emitting of prototypes.
|
||
|
|
||
|
pTEInfo->pName = pName;
|
||
|
pTEInfo->Flags = HasImplicitHandle() ? TYPE_ENCODE_WITH_IMPL_HANDLE : TYPE_ENCODE_FLAGS_NONE;
|
||
|
pCCB->RegisterTypeDecode( pTEInfo );
|
||
|
|
||
|
return CG_OK;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
CG_STATUS
|
||
|
CG_TYPE_ENCODE::GenTypeFree( CCB* pCCB )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Generate the type freeing routine for the type.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - The code gen controller block.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
CG_OK
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
// Freeing is only allowed under the new intrepreter
|
||
|
|
||
|
if ( ! ( pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER_V2 ) )
|
||
|
return CG_OK;
|
||
|
|
||
|
ISTREAM * pStream = pCCB->GetStream();
|
||
|
PNAME pName;
|
||
|
TYPE_ENCODE_INFO * pTEInfo = new TYPE_ENCODE_INFO;
|
||
|
|
||
|
// Generate the standard prototype. This really means emit the proto of
|
||
|
// the proc in the stub file. The body of the function output later,
|
||
|
|
||
|
if ( ((CG_NDR *)GetChild())->IsSimpleType() )
|
||
|
return CG_OK;
|
||
|
|
||
|
GenStdMesPrototype( pCCB,
|
||
|
( pName = GetType()->GetSymName()),
|
||
|
TYPE_FREE_CODE,
|
||
|
HasImplicitHandle()
|
||
|
);
|
||
|
|
||
|
pStream->NewLine();
|
||
|
pStream->Write( '{' );
|
||
|
pStream->IndentInc();pStream->NewLine();
|
||
|
|
||
|
// The procedure body consists of a single procedure call.
|
||
|
|
||
|
expr_proc_call * pProc = CreateStdMesEngineProc( pCCB, TYPE_FREE_CODE);
|
||
|
|
||
|
pProc->PrintCall( pCCB->GetStream(), 0, 0 );
|
||
|
|
||
|
// Terminate the procedure body.
|
||
|
|
||
|
pStream->IndentDec();
|
||
|
pStream->NewLine();
|
||
|
pStream->Write( '}' );
|
||
|
pStream->NewLine();
|
||
|
|
||
|
// Register the routine with the ccb to enable emitting of prototypes.
|
||
|
|
||
|
pTEInfo->pName = pName;
|
||
|
pTEInfo->Flags = HasImplicitHandle() ? TYPE_ENCODE_WITH_IMPL_HANDLE : TYPE_ENCODE_FLAGS_NONE;
|
||
|
pCCB->RegisterTypeFree( pTEInfo );
|
||
|
|
||
|
return CG_OK;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CG_TYPE_ENCODE::AllocateEncodeResources(
|
||
|
CCB * pCCB )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Allocate predefined resources for type pickling.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - The code gen controller block.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
CG_OK
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
Resources are:
|
||
|
|
||
|
1. The MIDL_ES_HANDLE if explicit binding.
|
||
|
2. A pointer to the type.
|
||
|
|
||
|
If there is no explicit binding set the implicit binding resource.
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
node_id * pMidlESHandle;
|
||
|
RESOURCE * pBindingResource;
|
||
|
node_id * pType = MakeIDNode( PTYPE_VAR_NAME,GetType());
|
||
|
|
||
|
// If explicit binding, then a parameter of the type MIDL_ES_HANDLE will
|
||
|
// be specified by the user. This must be added to the dictionary of
|
||
|
// parameter resources.
|
||
|
|
||
|
if( !HasImplicitHandle() )
|
||
|
{
|
||
|
pMidlESHandle = MakeIDNodeFromTypeName( MIDL_ES_HANDLE_VAR_NAME,
|
||
|
MIDL_ES_HANDLE_TYPE_NAME
|
||
|
);
|
||
|
pBindingResource = pCCB->AddParamResource(
|
||
|
MIDL_ES_HANDLE_VAR_NAME,
|
||
|
pMidlESHandle
|
||
|
);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
PNAME pName;
|
||
|
|
||
|
// If an implicit binding has been specified, a global variable of the
|
||
|
// type MIDL_ES_HANDLE will have been specified by the user. Pick that
|
||
|
// up and use as the binding resource.
|
||
|
|
||
|
MIDL_ASSERT( pCCB->GetInterfaceCG()->GetImplicitHandle() != 0 );
|
||
|
|
||
|
pMidlESHandle =
|
||
|
(node_id *)pCCB->GetInterfaceCG()->
|
||
|
GetImplicitHandle()->
|
||
|
GetHandleIDOrParam();
|
||
|
pName = pMidlESHandle->GetSymName();
|
||
|
|
||
|
pBindingResource = new RESOURCE( pName,
|
||
|
MakeIDNodeFromTypeName(
|
||
|
pName,
|
||
|
MIDL_ES_HANDLE_TYPE_NAME));
|
||
|
|
||
|
}
|
||
|
|
||
|
SetBindingResource( pBindingResource );
|
||
|
|
||
|
// Add a param for the type being pickled.
|
||
|
|
||
|
pCCB->AddParamResource( PTYPE_VAR_NAME, pType );
|
||
|
}
|
||
|
|
||
|
|
||
|
expr_proc_call *
|
||
|
CG_TYPE_ENCODE::CreateStdMesEngineProc(
|
||
|
CCB * pCCB,
|
||
|
int Code )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Create a standard proc expression for calls to the engine for encode,
|
||
|
decode, align/size, and free.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - The code gen controller block.
|
||
|
Code - Which can be any standard encoding services code.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
CG_OK
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
If the child is a base type that is being pickled, make direct calls
|
||
|
to the internal apis.
|
||
|
|
||
|
In -Oicf mode the emitted stub looks like the following with Encode
|
||
|
changed to whichever operation [Code] specifies:
|
||
|
|
||
|
void
|
||
|
<typename>_Encode(
|
||
|
<object>)
|
||
|
{
|
||
|
NdrMesTypeEncodeXXX();
|
||
|
}
|
||
|
|
||
|
For pre -Oicf modes the <&type_pickling_info> parameter is omitted.
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
expr_node * pExpr;
|
||
|
expr_proc_call * pProc;
|
||
|
PNAME pProcName;
|
||
|
CG_NDR * pChild = (CG_NDR *)GetChild();
|
||
|
CSzBuffer ProcNameBuf;
|
||
|
BOOL fIsBaseType;
|
||
|
bool fNeedPicklingInfoParam = false;
|
||
|
int fNeedsNDR64;
|
||
|
|
||
|
fIsBaseType = pChild->IsSimpleType();
|
||
|
fNeedsNDR64 = pCommand->NeedsNDR64Run();
|
||
|
|
||
|
//
|
||
|
// Figure out what the name of the routine to call is
|
||
|
//
|
||
|
|
||
|
PNAME pNdrMesProcNames[4] =
|
||
|
{
|
||
|
"NdrMesTypeAlignSize",
|
||
|
"NdrMesTypeEncode",
|
||
|
"NdrMesTypeDecode",
|
||
|
"NdrMesTypeFree"
|
||
|
};
|
||
|
|
||
|
if ( fIsBaseType )
|
||
|
{
|
||
|
MIDL_ASSERT( Code != TYPE_FREE_CODE );
|
||
|
|
||
|
ProcNameBuf.Set("NdrMesSimpleType");
|
||
|
ProcNameBuf.Append((Code == TYPE_ALIGN_SIZE_CODE) ? "AlignSize" :
|
||
|
(Code == TYPE_ENCODE_CODE) ? "Encode" : "Decode");
|
||
|
|
||
|
if ( fNeedsNDR64 )
|
||
|
{
|
||
|
ProcNameBuf.Append( "All" );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ProcNameBuf.Set( pNdrMesProcNames[Code] );
|
||
|
|
||
|
// -protocol all and ndr64 uses "3" routines.
|
||
|
// -Oicf in straight dce mode uses "2" routines
|
||
|
// otherwise uses unnumbered routines
|
||
|
|
||
|
if ( fNeedsNDR64 )
|
||
|
{
|
||
|
ProcNameBuf.Append( "3" );
|
||
|
fNeedPicklingInfoParam = true;
|
||
|
}
|
||
|
else if ( pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER_V2 )
|
||
|
{
|
||
|
ProcNameBuf.Append( "2" );
|
||
|
fNeedPicklingInfoParam = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MIDL_ASSERT( TYPE_FREE_CODE != Code );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pProcName = new char [strlen( ProcNameBuf ) + 1];
|
||
|
strcpy( pProcName, ProcNameBuf );
|
||
|
|
||
|
//
|
||
|
// Start putting together the proc call
|
||
|
//
|
||
|
|
||
|
pProc = new expr_proc_call( pProcName );
|
||
|
|
||
|
// Set parameters.
|
||
|
|
||
|
// First the encoding handle.
|
||
|
|
||
|
pProc->SetParam( GetBindingResource() );
|
||
|
|
||
|
// Then pickling info structure
|
||
|
|
||
|
if( fNeedPicklingInfoParam )
|
||
|
{
|
||
|
pExpr = new RESOURCE( PICKLING_INFO_STRUCT_NAME,
|
||
|
(node_skl *)0 );
|
||
|
|
||
|
pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
|
||
|
pExpr = MakeExpressionOfCastToTypeName( PMIDL_TYPE_PICKLING_INFO_NAME,
|
||
|
pExpr );
|
||
|
|
||
|
pProc->SetParam( pExpr );
|
||
|
}
|
||
|
|
||
|
// Next the stub descriptor or the proxy info
|
||
|
|
||
|
if ( !fIsBaseType || fNeedsNDR64 || Code == TYPE_ENCODE_CODE )
|
||
|
{
|
||
|
PNAME StubOrProxy;
|
||
|
|
||
|
if ( fNeedsNDR64 )
|
||
|
StubOrProxy = pCCB->GetInterfaceCG()->GetProxyInfoName();
|
||
|
else
|
||
|
StubOrProxy = pCCB->GetInterfaceCG()->GetStubDescName();
|
||
|
|
||
|
pExpr = new RESOURCE( StubOrProxy,
|
||
|
(node_skl *)0 );
|
||
|
|
||
|
pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
|
||
|
|
||
|
pProc->SetParam( pExpr );
|
||
|
}
|
||
|
|
||
|
// Next in straight dce, if it's not a simple type, comes the offset into
|
||
|
// the format string of the type
|
||
|
|
||
|
if( !fNeedsNDR64 && !fIsBaseType )
|
||
|
{
|
||
|
// Next parameter is the address of the format string indexed by the
|
||
|
// correct offset i.e &__MIDLFormatString[ ? ].
|
||
|
|
||
|
pExpr = Make_1_ArrayExpressionFromVarName(FORMAT_STRING_STRING_FIELD,
|
||
|
pChild->GetFormatStringOffset());
|
||
|
pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
|
||
|
pExpr = MakeExpressionOfCastToTypeName( PFORMAT_STRING_TYPE_NAME, pExpr );
|
||
|
pProc->SetParam( pExpr );
|
||
|
|
||
|
}
|
||
|
|
||
|
// For -protocol all or ndr64, the table of type offset tables is next
|
||
|
// followed by the index of this type into the tables.
|
||
|
|
||
|
if ( fNeedsNDR64 && !fIsBaseType )
|
||
|
{
|
||
|
pExpr = new RESOURCE( "TypePicklingOffsetTable", NULL );
|
||
|
pProc->SetParam( pExpr );
|
||
|
|
||
|
pExpr = new expr_constant( this->TypeIndex );
|
||
|
pProc->SetParam( pExpr );
|
||
|
}
|
||
|
|
||
|
// Now for everything except simply type AlignSize, we need the object
|
||
|
// itself
|
||
|
|
||
|
if ( ! (fIsBaseType && Code == TYPE_ALIGN_SIZE_CODE) )
|
||
|
{
|
||
|
pExpr = pCCB->GetParamResource( PTYPE_VAR_NAME );
|
||
|
pProc->SetParam( pExpr );
|
||
|
}
|
||
|
|
||
|
// Data size for simple type encoding and decoding
|
||
|
|
||
|
if ( fIsBaseType )
|
||
|
{
|
||
|
switch ( Code )
|
||
|
{
|
||
|
case TYPE_ALIGN_SIZE_CODE:
|
||
|
break;
|
||
|
|
||
|
case TYPE_ENCODE_CODE:
|
||
|
{
|
||
|
pExpr = new expr_constant( (short) pChild->GetMemorySize() );
|
||
|
pProc->SetParam( pExpr );
|
||
|
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TYPE_DECODE_CODE:
|
||
|
// We need format char because of conversion.
|
||
|
|
||
|
pExpr = new expr_constant( (short)
|
||
|
((CG_BASETYPE *)pChild)->GetFormatChar() );
|
||
|
pProc->SetParam( pExpr );
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
MIDL_ASSERT( FALSE );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pProc;
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
GenStdMesPrototype(
|
||
|
CCB * pCCB,
|
||
|
PNAME TypeName,
|
||
|
int Code,
|
||
|
BOOL fImplicitHandle )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Generate a standard prototype for the type pickle routines.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCCB - The code gen controller block.
|
||
|
PNAME - Name of the type.
|
||
|
Code - Size / Encode / Decode code.
|
||
|
fImplicitImplicitHandle - TRUE if implicit binding handle used.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
CSzBuffer Buffer;
|
||
|
char * p;
|
||
|
|
||
|
switch( Code )
|
||
|
{
|
||
|
case TYPE_ALIGN_SIZE_CODE: p = "AlignSize"; break;
|
||
|
case TYPE_ENCODE_CODE: p = "Encode"; break;
|
||
|
case TYPE_DECODE_CODE: p = "Decode"; break;
|
||
|
case TYPE_FREE_CODE: p = "Free"; break;
|
||
|
default:
|
||
|
MIDL_ASSERT( FALSE );
|
||
|
}
|
||
|
|
||
|
if( fImplicitHandle )
|
||
|
{
|
||
|
Buffer.Set("\n");
|
||
|
Buffer.Append((Code == TYPE_ALIGN_SIZE_CODE) ? "size_t" : "void");
|
||
|
Buffer.Append("\n");
|
||
|
Buffer.Append(TypeName);
|
||
|
Buffer.Append("_");
|
||
|
Buffer.Append(p);
|
||
|
Buffer.Append("(\n ");
|
||
|
Buffer.Append(TypeName);
|
||
|
Buffer.Append(" * ");
|
||
|
Buffer.Append(PTYPE_VAR_NAME);
|
||
|
Buffer.Append(")");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Buffer.Set("\n");
|
||
|
Buffer.Append((Code == TYPE_ALIGN_SIZE_CODE) ? "size_t" : "void");
|
||
|
Buffer.Append("\n");
|
||
|
Buffer.Append(TypeName);
|
||
|
Buffer.Append("_");
|
||
|
Buffer.Append(p);
|
||
|
Buffer.Append("(\n ");
|
||
|
Buffer.Append(MIDL_ES_HANDLE_TYPE_NAME);
|
||
|
Buffer.Append(" ");
|
||
|
Buffer.Append(MIDL_ES_HANDLE_VAR_NAME);
|
||
|
Buffer.Append(",\n ");
|
||
|
Buffer.Append(TypeName);
|
||
|
Buffer.Append(" * ");
|
||
|
Buffer.Append(PTYPE_VAR_NAME);
|
||
|
Buffer.Append(")");
|
||
|
}
|
||
|
|
||
|
pCCB->GetStream()->Write( Buffer );
|
||
|
}
|
||
|
|