RpcView/RpcDecompiler/internalComplexTypesArrays.cpp

1115 lines
29 KiB
C++
Raw Permalink Blame History

#include "..\RpcCommon\RpcView.h"
#include "internalRpcDecompTypeDefs.h"
#include "internalComplexTypesArrays.h"
#include "internalTypeTools.h"
#include "internalComplexTypesPointers.h"
#include "internalRpcDecompiler.h"
#include "InternalComplexTypesMisc.h"
#include <stdio.h>
BOOL __fastcall processFixedSizeArray(
_In_ VOID* pContext,
_In_ RVA_T pType,
_In_ FC_TYPE fcType,
_Inout_ ParamDesc& ParamDesc,
_Inout_ std::list<TypeToDefine>& listAdditionalTypes,
_Inout_ std::ostringstream& oss)
{
BOOL bResult = FALSE;
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
ArrayDescrHeader_U ArrayToDecode;
UINT ArrayMemorySize = 0;
INT16 OffsetToEmbeddedElement = 0;
INT fixedArraySizes[30];
UINT fixedArraySizesIndex = 0;
UINT i = 0;
// Variables related to embedded element (if any)
StructMemberLayout_U ElementMemberLayoutToDecode;
RVA_T pElementDescr = 0;
SimpleStructHeader_t embeddedStruct;
BYTE elementToDecode;
SMFixedSizedArrayHeader_t SMArray;
LGFixedSizedArrayHeader_t LGArray;
switch(fcType)
{
case FC_SMFARRAY:
RPC_GET_PROCESS_DATA(
pType,
&ArrayToDecode,
sizeof(SMFixedSizedArrayHeader_t)
);
ArrayMemorySize = ArrayToDecode.smFixedSizedArrayHdr.totalSize;
pType += sizeof(SMFixedSizedArrayHeader_t);
break;
case FC_LGFARRAY:
RPC_GET_PROCESS_DATA(
pType,
&ArrayToDecode,
sizeof(LGFixedSizedArrayHeader_t)
);
ArrayMemorySize = ArrayToDecode.lgFixedSizedArrayHdr.totalSize;
pType += sizeof(LGFixedSizedArrayHeader_t);
break;
default:
bResult = FALSE;
goto End;
}
//TODO Check for Pointer_layout presence
// -->Write code here<--
//END TODO
RPC_GET_PROCESS_DATA(
pType,
&ElementMemberLayoutToDecode,
sizeof(StructMemberLayout_U)
);
fixedArraySizes[fixedArraySizesIndex] = ArrayMemorySize;
pElementDescr = pType;
if( ElementMemberLayoutToDecode.baseTypeMemberLayout == FC_EMBEDDED_COMPLEX )
{
// We need the offset of the embedded structure to actually know what is inside the struct
// Offset is positive if the struct is declared after the array we're analyzing; negative otherwise
OffsetToEmbeddedElement = ElementMemberLayoutToDecode.nonBaseTypeMemberLayout.offsetToDescription;
pType += sizeof(StructNonBaseTypeMemberLayout_t);
pElementDescr = pType + OffsetToEmbeddedElement - sizeof(ElementMemberLayoutToDecode.nonBaseTypeMemberLayout.offsetToDescription);
RPC_GET_PROCESS_DATA(
pElementDescr,
&elementToDecode,
sizeof(BYTE)
);
// Processing multi-dimensional array
while((elementToDecode & 0xFF) == FC_SMFARRAY || (elementToDecode & 0xFF) == FC_LGFARRAY){
if((elementToDecode & 0xFF) == FC_SMFARRAY){
RPC_GET_PROCESS_DATA(
pElementDescr,
&SMArray,
sizeof(SMFixedSizedArrayHeader_t)
);
ArrayMemorySize = SMArray.totalSize;
pElementDescr += sizeof(SMFixedSizedArrayHeader_t);
}else{
if((elementToDecode & 0xFF) == FC_LGFARRAY){
RPC_GET_PROCESS_DATA(
pElementDescr,
&LGArray,
sizeof(LGFixedSizedArrayHeader_t)
);
ArrayMemorySize = LGArray.totalSize;
pElementDescr += sizeof(LGFixedSizedArrayHeader_t);
}
}
fixedArraySizes[fixedArraySizesIndex] /= ArrayMemorySize;
fixedArraySizesIndex++;
fixedArraySizes[fixedArraySizesIndex] = ArrayMemorySize;
RPC_GET_PROCESS_DATA(
pElementDescr,
&ElementMemberLayoutToDecode,
sizeof(StructMemberLayout_U)
);
if(ElementMemberLayoutToDecode.baseTypeMemberLayout == FC_EMBEDDED_COMPLEX){
OffsetToEmbeddedElement = ElementMemberLayoutToDecode.nonBaseTypeMemberLayout.offsetToDescription;
pElementDescr += sizeof(StructNonBaseTypeMemberLayout_t);
pElementDescr = pElementDescr + OffsetToEmbeddedElement - sizeof(ElementMemberLayoutToDecode.nonBaseTypeMemberLayout.offsetToDescription);
RPC_GET_PROCESS_DATA(
pElementDescr,
&elementToDecode,
sizeof(BYTE)
);
}else{
elementToDecode = ElementMemberLayoutToDecode.baseTypeMemberLayout;
}
} // end while
}else{ // ElementMemberLayoutToDecode.baseTypeMemberLayout == FC_EMBEDDED_COMPLEX
RPC_GET_PROCESS_DATA(
pType,
&elementToDecode,
sizeof(BYTE)
);
}
ParamDesc.setRva(pElementDescr);
if(isSimpleType((FC_TYPE)ElementMemberLayoutToDecode.baseTypeMemberLayout))
{
bResult = rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss);
if(bResult == FALSE)
{
RPC_DEBUG_FN((UCHAR*) "[ERROR] processFixedSizeArray : error while dumping simpleType");
return FALSE;
}
fixedArraySizes[fixedArraySizesIndex] = ArrayMemorySize / getSimpleTypeMemorySize((FC_TYPE)elementToDecode);
fixedArraySizesIndex++;
} // isSimpleType(ElementMemberLayoutToDecode.baseTypeMemberLayout
else{
//UINT OffstetInTypeFormatString = 0;
RPC_GET_PROCESS_DATA(
pElementDescr,
&embeddedStruct,
sizeof(SimpleStructHeader_t)
);
fixedArraySizes[fixedArraySizesIndex] = ArrayMemorySize / embeddedStruct.memory_size;
fixedArraySizesIndex++;
bResult = rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss);
if(bResult == FALSE)
{
RPC_DEBUG_FN((UCHAR*) "[ERROR] processFixedSizeArray : error while dumping non simple type");
return FALSE;
}
// store array memory size
//ParamDesc.setMemorySize(ArrayMemorySize);
}
for(i=0; i<fixedArraySizesIndex; i++)
{
oss<<"["<<std::dec<<fixedArraySizes[i]<<"]";
}
bResult = TRUE;
End:
return(bResult);
}
BOOL __fastcall processConformantArray(
_In_ VOID* pContext,
_In_ RVA_T pType,
_In_ FC_TYPE fcType,
_Inout_ ParamDesc& ParamDesc,
_Inout_ std::list<TypeToDefine>& listAdditionalTypes,
_Inout_ std::ostringstream& oss)
{
BOOL bResult = FALSE;
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
ProcFormatStringParam_U paramToPrint;
CorrelationDescriptor_U correlationDescriptorToRead;
ConformanceDescr_T confDesc;
BYTE elementType;
StructNonBaseTypeMemberLayout_t elementDescription;
BYTE correlationType;
BYTE correlationOperator;
short correlationOffset;
NDR_CORRELATION_FLAGS correlationFlags = {0,0,0,0,0};
std::ostringstream rangeStr;
UNREFERENCED_PARAMETER(fcType);
#ifdef DBG_DECOMP
oss << " /* FC_CARRAY */";
#endif
RPC_GET_PROCESS_DATA(
pType,
&paramToPrint,
sizeof(paramToPrint)
);
pType += sizeof(ConformantArrayHeader_t);
// Get correlation descriptor offset in the type format string
RPC_GET_PROCESS_DATA(
pType,
&correlationDescriptorToRead,
sizeof(correlationDescriptorToRead) //
);
confDesc.pType = pType;
if(robustFlagWasSet){
correlationType = correlationDescriptorToRead.corrDescRobust.correlation_type;
correlationOperator = correlationDescriptorToRead.corrDescRobust.correlation_operator;
correlationOffset = correlationDescriptorToRead.corrDescRobust.offset;
correlationFlags = correlationDescriptorToRead.corrDescRobust.robust_flags;
}else{
correlationType = correlationDescriptorToRead.corrDescNonRobust.correlation_type;
correlationOperator = correlationDescriptorToRead.corrDescNonRobust.correlation_operator;
correlationOffset = correlationDescriptorToRead.corrDescNonRobust.offset;
}
if(robustFlagWasSet)
{
pType += sizeof(CorrelationDescriptorRobust_t);
}
else
{
pType += sizeof(CorrelationDescriptorNonRobust_t);
}
confDesc.confType = size_is;
confDesc.corrDesc = correlationDescriptorToRead.corrDescNonRobust;
bResult = processCorrelationDescriptor(pContext, confDesc, oss,ParamDesc);
if(bResult == FALSE)
{
RPC_DEBUG_FN((UCHAR*) "[ERROR] processConformantArray : correlation descriptor not correctly decoded");
return FALSE;
}
// Handle undocumented range attribute on conformance
if(ParamDesc.hasRangeOnConformance() )//&& confDesc.corrDesc.correlation_type != FC_CONSTANT_CONFORMANCE && confDesc.corrDesc.correlation_type != FC_POINTER_CONFORMANCE)
{
bResult = ProcessArrayRange(pContext, pType, ParamDesc, rangeStr);
if(bResult == FALSE)
{
RPC_DEBUG_FN((UCHAR*) "[ERROR] processConformantArray : range on conformance not correctly decoded");
return FALSE;
}
oss << rangeStr.str();
pType += sizeof(Range_t);
}
RPC_GET_PROCESS_DATA(
pType,
&elementType,
sizeof(BYTE));
if(bResult == FALSE)
{
RPC_DEBUG_FN((UCHAR*)"[ERROR] processConformantArray : unable to get process data \n");
return FALSE;
}
//
// check if a pointer layout is present
// Warning : if a pointer layout is present it's skipped since this information seems to be redundant
// this should be investigated
//
if(elementType == FC_PP)
{
pType += sizeof(BYTE);
// read until FC_END is found
while(TRUE)
{
RPC_GET_PROCESS_DATA(
pType,
&elementType,
sizeof(BYTE));
if(bResult == FALSE)
{
RPC_DEBUG_FN((UCHAR*)"[ERROR] processConformantArray : unable to get process data \n");
return FALSE;
}
pType ++ ;
if(elementType == FC_END)
{
break;
}
}
}
RPC_GET_PROCESS_DATA(
pType,
&elementType,
sizeof(BYTE));
if(elementType == FC_EMBEDDED_COMPLEX){
RPC_GET_PROCESS_DATA(
pType,
&elementDescription,
sizeof(StructNonBaseTypeMemberLayout_t)
)
pType += elementDescription.offsetToDescription + sizeof(elementDescription.offsetToDescription);
}
// ParamDesc.setuOffset((UINT)(pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString));
ParamDesc.setRva(pType);
// Write the type of array
if(rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss) == FALSE)
{
RPC_DEBUG_FN((UCHAR*)"[ERROR] processConformantArray : unable to dump type \n");
return FALSE;
}
// <bugfix_julien>
// proposition : ne pas ajouter de [] si le tableau est pr<70>fix<69> par un pointeur
if(ParamDesc.getuPtrLevel() == 0)
{
oss << "[]";
}
else
{
#ifdef DBG_DECOMP
oss<<"/*[] CONFORMANT_ARRAY*/";
#endif
}
bResult = TRUE;
return bResult;
}
BOOL __fastcall processConformantVaryingArray(
_In_ VOID* pContext,
_In_ RVA_T pType,
_In_ FC_TYPE fcType,
_Inout_ ParamDesc& ParamDesc,
_Inout_ std::list<TypeToDefine>& listAdditionalTypes,
_Inout_ std::ostringstream& oss)
{
BOOL bResult = FALSE;
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
CorrelationDescriptor_U correlationDescriptorToRead;
BYTE elementType = 0;
StructNonBaseTypeMemberLayout_t elementDescription;
BYTE correlationType;
BYTE correlationOperator;
short correlationOffset;
NDR_CORRELATION_FLAGS correlationFlags = {0,0,0,0,0};
ConformanceDescr_T confDesc;
std::ostringstream rangeStr;
UNREFERENCED_PARAMETER(fcType);
oss << " /* [DBG] FC_CVARRAY */";
pType += sizeof(ConformantVaryingArrayHeader_t);
// Read the first correlation descriptor
RPC_GET_PROCESS_DATA(
pType,
&correlationDescriptorToRead,
sizeof(correlationDescriptorToRead) //
);
if(robustFlagWasSet){
correlationType = correlationDescriptorToRead.corrDescRobust.correlation_type;
correlationOperator = correlationDescriptorToRead.corrDescRobust.correlation_operator;
correlationOffset = correlationDescriptorToRead.corrDescRobust.offset;
correlationFlags = correlationDescriptorToRead.corrDescRobust.robust_flags;
}else{
correlationType = correlationDescriptorToRead.corrDescNonRobust.correlation_type;
correlationOperator = correlationDescriptorToRead.corrDescNonRobust.correlation_operator;
correlationOffset = correlationDescriptorToRead.corrDescNonRobust.offset;
}
if(robustFlagWasSet)
{
pType += sizeof(CorrelationDescriptorRobust_t);
}
else
{
pType += sizeof(CorrelationDescriptorNonRobust_t);
}
confDesc.confType = size_is;
confDesc.corrDesc = correlationDescriptorToRead.corrDescNonRobust;
bResult = processCorrelationDescriptor(pContext, confDesc, oss,ParamDesc);
if(bResult == FALSE)
{
RPC_DEBUG_FN((UCHAR*) "[ERROR] processConformantVaryingArray : first correlation descriptor not correctly decoded");
return FALSE;
}
if(ParamDesc.hasRangeOnConformance() )//&& confDesc.corrDesc.correlation_type != FC_CONSTANT_CONFORMANCE && confDesc.corrDesc.correlation_type != FC_POINTER_CONFORMANCE)
{
bResult = ProcessArrayRange(pContext, pType, ParamDesc, rangeStr);
if(bResult == FALSE)
{
RPC_DEBUG_FN((UCHAR*) "[ERROR] processConformantArray : range on conformance not correctly decoded");
return FALSE;
}
oss << rangeStr.str();
pType += sizeof(Range_t);
}
// Read the second correlation descriptor
RPC_GET_PROCESS_DATA(
pType,
&correlationDescriptorToRead,
sizeof(correlationDescriptorToRead) //
);
if(robustFlagWasSet){
correlationType = correlationDescriptorToRead.corrDescRobust.correlation_type;
correlationOperator = correlationDescriptorToRead.corrDescRobust.correlation_operator;
correlationOffset = correlationDescriptorToRead.corrDescRobust.offset;
correlationFlags = correlationDescriptorToRead.corrDescRobust.robust_flags;
}else{
correlationType = correlationDescriptorToRead.corrDescNonRobust.correlation_type;
correlationOperator = correlationDescriptorToRead.corrDescNonRobust.correlation_operator;
correlationOffset = correlationDescriptorToRead.corrDescNonRobust.offset;
}
if(robustFlagWasSet)
{
pType += sizeof(CorrelationDescriptorRobust_t);
}
else
{
pType += sizeof(CorrelationDescriptorNonRobust_t);
}
confDesc.confType = length_is; // todo : cas du first_is
confDesc.corrDesc = correlationDescriptorToRead.corrDescNonRobust;
bResult = processCorrelationDescriptor(pContext, confDesc, oss,ParamDesc);
if(bResult == FALSE)
{
RPC_DEBUG_FN((UCHAR*) "[ERROR] processConformantVaryingArray : second correlation descriptor not correctly decoded");
return FALSE;
}
if(ParamDesc.hasRangeOnConformance())
{
pType += sizeof(Range_t);
}
//
// check if a pointer layout is present
// Warning : if a pointer layout is present it's skipped since this information seems to be redundant
// this should be investigated
//
RPC_GET_PROCESS_DATA(
pType,
&elementType,
sizeof(BYTE) //
);
if(elementType == FC_PP)
{
pType += sizeof(BYTE);
// read until FC_END is found
while(TRUE)
{
RPC_GET_PROCESS_DATA(
pType,
&elementType,
sizeof(BYTE));
if(bResult == FALSE)
{
RPC_DEBUG_FN((UCHAR*)"[ERROR] processConformantArray : unable to get process data \n");
return FALSE;
}
pType ++ ;
if(elementType == FC_END)
{
break;
}
}
}
RPC_GET_PROCESS_DATA(
pType,
&elementType,
sizeof(BYTE));
if(elementType == FC_EMBEDDED_COMPLEX){
RPC_GET_PROCESS_DATA(
pType,
&elementDescription,
sizeof(StructNonBaseTypeMemberLayout_t)
)
pType += elementDescription.offsetToDescription + sizeof(elementDescription.offsetToDescription);
}
///ParamDesc.setuOffset((UINT)(pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString));
ParamDesc.setRva(pType);
bResult = rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss); // Write the type of array
if(bResult == FALSE)
{
RPC_DEBUG_FN((UCHAR*) "[ERROR] processConformantVaryingArray : dump type failed");
return FALSE;
}
// <bugfix_julien>
// proposition : ne pas ajouter de [] si le tableau est pr<70>fix<69> par un pointeur
if(ParamDesc.getuPtrLevel() == 0)
{
oss << "[]";
}
else
{
oss<<"/*[] CONFORMANT_ARRAY*/";
}
bResult = TRUE;
return bResult;
}
BOOL __fastcall processVaryingArray(
_In_ VOID* pContext,
_In_ RVA_T pType,
_In_ FC_TYPE fcType,
_Inout_ ParamDesc& ParamDesc,
_Inout_ std::list<TypeToDefine>& listAdditionalTypes,
_Inout_ std::ostringstream& oss)
{
BOOL bResult = FALSE;
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
CorrelationDescriptor_U correlationDescriptorToRead;
UINT argNbr = 0;
INT size = 0;
ArrayDescrHeader_U ArrayToDecode;
UINT ArraySize;
BYTE correlationType;
BYTE correlationOperator;
short correlationOffset;
NDR_CORRELATION_FLAGS correlationFlags = {0,0,0,0,0};
BYTE value;
UNREFERENCED_PARAMETER(fcType);
RPC_GET_PROCESS_DATA(
pType,
&value,
sizeof(BYTE) //
);
switch(value){
case FC_LGVARRAY:
RPC_GET_PROCESS_DATA(
pType,
&ArrayToDecode,
sizeof(LGVaryingArrayHeader_t)
);
ArraySize = ArrayToDecode.lgVaryingArrayHdr.numberOfElements;
pType += sizeof(LGVaryingArrayHeader_t);
break;
case FC_SMVARRAY:
RPC_GET_PROCESS_DATA(
pType,
&ArrayToDecode,
sizeof(SMVaryingArrayHeader_t)
);
ArraySize = ArrayToDecode.smVaryingArrayHdr.numberOfElements;
pType += sizeof(SMVaryingArrayHeader_t);
break;
default:
RPC_DEBUG_FN((UCHAR*)"Error in PrintParamVaryingArray : bad array type");
goto End;
}
// Read the variance correlation descriptor
RPC_GET_PROCESS_DATA(
pType,
&correlationDescriptorToRead,
sizeof(correlationDescriptorToRead) //
);
if(robustFlagWasSet){
correlationType = correlationDescriptorToRead.corrDescRobust.correlation_type;
correlationOperator = correlationDescriptorToRead.corrDescRobust.correlation_operator;
correlationOffset = correlationDescriptorToRead.corrDescRobust.offset;
correlationFlags = correlationDescriptorToRead.corrDescRobust.robust_flags;
}else{
correlationType = correlationDescriptorToRead.corrDescNonRobust.correlation_type;
correlationOperator = correlationDescriptorToRead.corrDescNonRobust.correlation_operator;
correlationOffset = correlationDescriptorToRead.corrDescNonRobust.offset;
}
pType += getCorrelationDescriptorSize(robustFlagWasSet, ParamDesc.hasRangeOnConformance());
if(is64B) argNbr = correlationOffset / VIRTUAL_STACK_OFFSET_GRANULARITY_64B;
else argNbr = correlationOffset / VIRTUAL_STACK_OFFSET_GRANULARITY_32B;
// Only FC_CONSTANT_CONFORMANCE handled as of now.
switch(correlationType & 0xF0){
case FC_CONSTANT_CONFORMANCE:
size = ((correlationOperator << 16) | correlationOffset) & 0xFFFFFF;
break;
default:
break;
}
switch(correlationOperator){
case FC_CALLBACK: // Callback called to evaluate expression given to last_is(). Not handled yet
oss<<"[/*TODO first_is and/or last_is(<callback_routine_"<<std::dec<<correlationOffset<<">) */]";
break;
case FC_DEREFERENCE:
oss<<"[length_is( * arg_"<<std::dec<<argNbr<<")]";
break;
case FC_ADD_1:
RPC_DEBUG_FN((UCHAR*)", last_is(arg_%d)]", argNbr);
oss<<"[last_is(arg_"<<std::dec<<argNbr<<")]";
break;
default:
RPC_DEBUG_FN((UCHAR*)", length_is(%d)]", size);
oss<<"[length_is("<<std::dec<<size<<")]";
break;
} // end switch(correlationType)
//ParamDesc.setuOffset((UINT)(pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString));
ParamDesc.setRva(pType);
bResult = rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss); // Write the type of array
if(bResult == FALSE)
{
RPC_DEBUG_FN((UCHAR*) "[ERROR] processVaryingArray : rpcDumpType failed");
return FALSE;
}
oss<<"["<<std::dec<<ArraySize<<"]";
// store array size in memory
//ParamDesc.setMemorySize(ArraySize);
bResult = TRUE;
End:
return bResult;
}
BOOL __fastcall processComplexArray(
_In_ VOID* pContext,
_In_ RVA_T pType,
_In_ FC_TYPE fcType,
_Inout_ ParamDesc& ParamDesc,
_Inout_ std::list<TypeToDefine>& listAdditionalTypes,
_Inout_ std::ostringstream& oss)
{
BOOL bResult = FALSE;
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
CorrelationDescriptor_U correlationDescriptorToRead;
ComplexArrayHeader_t complexArray;
UINT64 arrayDescrOffset = pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString;
UINT argNbr = 0;
INT size = 0;
BYTE correlationType;
BYTE correlationOperator;
short correlationOffset;
NDR_CORRELATION_FLAGS correlationFlags = {0,0,0,0,0};
StructNonBaseTypeMemberLayout_t elementDescription;
UINT8 elementToDecode;
UINT32 arraySize[30];
UINT32 arraySizeIndex = 0;
UINT8 varDescrHandled[15];
UINT16 callbacksCalled[15];
UINT32 i = 0;
UINT32 j = 0;
BOOL isLastEmbeddedArray = FALSE;
BOOL lengthIs = FALSE;
BOOL lastIs = FALSE;
BOOL firstArray = TRUE;
std::stringstream lastIsStdString;
lastIsStdString << "[last_is(";
std::stringstream lengthIsStdStr;
lengthIsStdStr << "[length_is(";
std::ostringstream rangeStr;
ConformanceDescr_T confDesc;
UNREFERENCED_PARAMETER(fcType);
memset(varDescrHandled, 0, sizeof(varDescrHandled));
memset(callbacksCalled, -1, sizeof(callbacksCalled));
oss << " /* [DBG] FC_BOGUS_ARRAY */ ";
//// <DBG>
//RPC_GET_PROCESS_DATA(
// pType,
// dbgBuf,
// DBG_BUF_SIZE
// );
//oss<< std::endl << "DUMP : ";
//for(int i=0; i<DBG_BUF_SIZE; i++)
//{
// oss<<" 0x"<<std::hex<<(int)dbgBuf[i];
// //if(i % 2 == 0 )
// //{
// // oss<<"/* "<<i<<" */";
// //}
// //oss<<std::endl;
//}
//oss << std::endl;
//// </DBG>
oss<<"[size_is(";
while(!isLastEmbeddedArray)
{
RPC_GET_PROCESS_DATA(
pType,
&complexArray,
sizeof(ComplexArrayHeader_t) //
);
pType += sizeof(ComplexArrayHeader_t);
if(complexArray.numberOfElements == 0){
RVA_T pRangeDesc = pType;
// Read the conformance correlation descriptor ( size_is, max_is )
RPC_GET_PROCESS_DATA(
pType,
&correlationDescriptorToRead,
sizeof(correlationDescriptorToRead)
);
if(robustFlagWasSet){
correlationType = correlationDescriptorToRead.corrDescRobust.correlation_type;
correlationOperator = correlationDescriptorToRead.corrDescRobust.correlation_operator;
correlationOffset = correlationDescriptorToRead.corrDescRobust.offset;
correlationFlags = correlationDescriptorToRead.corrDescRobust.robust_flags;
}else{
correlationType = correlationDescriptorToRead.corrDescNonRobust.correlation_type;
correlationOperator = correlationDescriptorToRead.corrDescNonRobust.correlation_operator;
correlationOffset = correlationDescriptorToRead.corrDescNonRobust.offset;
}
if(robustFlagWasSet)
{
pRangeDesc += sizeof(CorrelationDescriptorRobust_t);
}
else
{
pRangeDesc += sizeof(CorrelationDescriptorNonRobust_t);
}
confDesc.confType = size_is;
confDesc.corrDesc = correlationDescriptorToRead.corrDescNonRobust;
// decode target of ConformanceDescriptor
bResult = processCorrelationDescriptorNaked(pContext, confDesc, oss,ParamDesc);
if(bResult == FALSE)
{
RPC_ERROR_FN("processCorrelationDescriptorNaked failed\n");
return FALSE;
}
if(ParamDesc.hasRangeOnConformance() && firstArray)// && confDesc.corrDesc.correlation_type != FC_CONSTANT_CONFORMANCE && confDesc.corrDesc.correlation_type != FC_POINTER_CONFORMANCE)
{
bResult = ProcessArrayRange(pContext, pRangeDesc, ParamDesc, rangeStr);
if(bResult == FALSE)
{
RPC_ERROR_FN("ProcessArrayRange failed\n");
return FALSE;
}
firstArray = FALSE;
}
arraySize[arraySizeIndex++] = 0;
}else{ // complexArray.numberOfElements == 0
arraySize[arraySizeIndex++] = complexArray.numberOfElements;
}
pType += 2 * getCorrelationDescriptorSize(robustFlagWasSet, ParamDesc.hasRangeOnConformance()); // Forget about 2nd correlation descriptor, will be handled later
RPC_GET_PROCESS_DATA(
pType,
&elementDescription,
sizeof(StructNonBaseTypeMemberLayout_t)
)
if(elementDescription.memberType == FC_EMBEDDED_COMPLEX)
{
pType = pType + sizeof(StructNonBaseTypeMemberLayout_t) + elementDescription.offsetToDescription - sizeof(elementDescription.offsetToDescription);
RPC_GET_PROCESS_DATA(
pType,
&elementToDecode,
sizeof(UINT8)
);
if(elementToDecode != FC_BOGUS_ARRAY)
{
oss<<")]";
isLastEmbeddedArray = TRUE;
}else{
oss<<",";
}
}else{ // elementDescription.memberType == FC_EMBEDDED_COMPLEX
oss<<")]";
isLastEmbeddedArray = TRUE;
}
} // while(!isLastEmbeddedArray)
// Add the range if any
oss << rangeStr.str();
pType = (RVA_T)(arrayDescrOffset + pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString);
isLastEmbeddedArray = FALSE;
/****************************************************
*
*
* Variance descriptor
*
*
****************************************************/
while(!isLastEmbeddedArray){
RPC_GET_PROCESS_DATA(
pType,
&complexArray,
sizeof(ComplexArrayHeader_t)
);
pType += sizeof(ComplexArrayHeader_t);
// Jump over conformance descriptor
pType += getCorrelationDescriptorSize(robustFlagWasSet, ParamDesc.hasRangeOnConformance());
// Read variance descriptor
RPC_GET_PROCESS_DATA(
pType,
&correlationDescriptorToRead,
sizeof(correlationDescriptorToRead)
);
if(robustFlagWasSet){
correlationType = correlationDescriptorToRead.corrDescRobust.correlation_type;
correlationOperator = correlationDescriptorToRead.corrDescRobust.correlation_operator;
correlationOffset = correlationDescriptorToRead.corrDescRobust.offset;
correlationFlags = correlationDescriptorToRead.corrDescRobust.robust_flags;
}else{
correlationType = correlationDescriptorToRead.corrDescNonRobust.correlation_type;
correlationOperator = correlationDescriptorToRead.corrDescNonRobust.correlation_operator;
correlationOffset = correlationDescriptorToRead.corrDescNonRobust.offset;
}
pType += getCorrelationDescriptorSize(robustFlagWasSet, ParamDesc.hasRangeOnConformance());
if(correlationType != 0xFF)
{ // If variance descriptor is not invalid
if(is64B) argNbr = correlationOffset / VIRTUAL_STACK_OFFSET_GRANULARITY_64B;
else argNbr = correlationOffset / VIRTUAL_STACK_OFFSET_GRANULARITY_32B;
// Only FC_CONSTANT_CONFORMANCE handled yet.
switch(correlationType & 0xF0){
case FC_CONSTANT_CONFORMANCE:
size = ((correlationOperator << 16) | correlationOffset) & 0xFFFFFF;
lastIsStdString<<std::dec<<(size-1);
lastIs = TRUE;
break;
default:
switch(correlationOperator){
case FC_CALLBACK: // Callback called to evaluate expression given to last_is(). Not handled yet
callbacksCalled[i] = correlationOffset;
varDescrHandled[i] = TRUE;
i++;
break;
case FC_DEREFERENCE:
lengthIsStdStr<<" * arg_"<<std::dec<<argNbr;
lengthIs = TRUE;
break;
case FC_ADD_1:
lastIsStdString << " arg_"<<std::dec<<argNbr;
lastIs = TRUE;
break;
case FC_EXPR:
// TODO : FC_EXPR not handled. mIDA reversing needed
RPC_ERROR_FN("FC_EXPR todo...\n");
break;
default:
lengthIsStdStr << " arg_" <<std::dec<< argNbr;
lengthIs = TRUE;
break;
} // end switch(correlationType)
break;
}
}// correlationType != 0xFF
RPC_GET_PROCESS_DATA(
pType,
&elementDescription,
sizeof(StructNonBaseTypeMemberLayout_t)
)
if(elementDescription.memberType == FC_EMBEDDED_COMPLEX){
pType = pType + sizeof(StructNonBaseTypeMemberLayout_t) + elementDescription.offsetToDescription - sizeof(elementDescription.offsetToDescription);
RPC_GET_PROCESS_DATA(
pType,
&elementToDecode,
sizeof(UINT8)
);
if(elementToDecode != FC_BOGUS_ARRAY)
{
lengthIsStdStr << ")]";
lastIsStdString << ")]";
isLastEmbeddedArray = TRUE;
}else{
lengthIsStdStr << ",";
lastIsStdString << ",";
}
}else{ // elementDescription.memberType == FC_EMBEDDED_COMPLEX
lengthIsStdStr << ")]";
lastIsStdString << ")]";
isLastEmbeddedArray = TRUE;
}
} // while(!isLastEmbeddedArray)
// Only write to file if something was written into buffers
if(lengthIs)
{
oss<< lengthIsStdStr.str();//std::string(lengthIsStr);
}
if(lastIs)
{
oss<< lastIsStdString.str();//std::string(lastIsStr);
}
// Write any variance callback
oss<<" /* ";
for(j; j<i; j++){
if(callbacksCalled[j] != (UINT16)-1)
{
oss<<" callback_"<<std::dec<<callbacksCalled[j]<<" used, ";
}
}
oss<<" */ ";
ParamDesc.setRva(pType);
bResult = rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss); // Write the type of array
if(bResult == FALSE)
{
RPC_ERROR_FN("rpcDumpType failed\n");
return FALSE;
}
// <bugfix_julien>
// proposition : ne pas ajouter de [] si le tableau est pr<70>fix<69> par un pointeur
if(ParamDesc.getuPtrLevel() == 0)
{
for(i=0; i<arraySizeIndex; i++)
{
if(arraySize[i] != 0)
{
oss<<"["<<std::dec<<arraySize[i]<<"]";
}else{
oss<<"[]";
}
}
}
bResult = TRUE;
return bResult;
}
UINT __fastcall getArrayMemorySize(
_In_ VOID* pContext,
_In_ RVA_T pType)
{
BOOL bResult = FALSE;
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
// We only need size information, which is at the same offset for both variant and fixed size array.
SMFixedSizedArrayHeader_t smallArray;
LGFixedSizedArrayHeader_t longArray;
UINT8 arrayType;
UINT arraySize = 0;
RPC_GET_PROCESS_DATA(pType, &arrayType, sizeof(UINT8));
switch(arrayType)
{
case FC_SMFARRAY:
case FC_SMVARRAY:
RPC_GET_PROCESS_DATA(pType, &smallArray, sizeof(SMFixedSizedArrayHeader_t));
arraySize = smallArray.totalSize;
break;
case FC_LGFARRAY:
case FC_LGVARRAY:
RPC_GET_PROCESS_DATA(pType, &longArray, sizeof(LGFixedSizedArrayHeader_t));
arraySize = longArray.totalSize;
break;
default:
arraySize = POINTER_SIZE;
break;
}
return arraySize;
}