/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Copyright (c) 1993 Microsoft Corporation Module Name : unmrshlp.c Abstract : This file contains the routines for unmarshalling an array's or a structure's embedded pointers. Author : David Kays dkays September 1993. Revision History : ---------------------------------------------------------------------*/ #include "ndrp.h" PFORMAT_STRING NdrpEmbeddedPointerUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, uchar * pMemory, PFORMAT_STRING pFormat, uchar fNewMemory ) /*++ Routine Description : Unmarshalls an array's or a structure's embedded pointers. Arguments : pStubMsg - Pointer to the stub message. pMemory - Pointer to the structure or array whose embedded pointers are being unmarshalled. pFormat - Pointer layout format string description. fNewMemory - TRUE if the array or structure was allocated during unmarshalling, FALSE otherwise. Return : Format string pointer after the pointer layout. --*/ { uchar ** ppMemPtr; uchar ** ppBufPtr; uchar * pBufferMark; uchar * pBufferSave; long MaxCountSave, OffsetSave; MaxCountSave = pStubMsg->MaxCount; OffsetSave = pStubMsg->Offset; // // Check if we're handling pointers in a complex struct, and re-set the // Buffer pointer if so. // if ( pStubMsg->PointerBufferMark ) { pBufferSave = pStubMsg->Buffer; pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = 0; } else pBufferSave = 0; // Save BufferMark in a local. pBufferMark = pStubMsg->BufferMark; // Increment past FC_PP and FC_PAD. pFormat += 2; for (;;) { if ( *pFormat == FC_END ) { if ( pBufferSave ) { pStubMsg->PointerBufferMark = pStubMsg->Buffer; pStubMsg->Buffer = pBufferSave; } return pFormat; } // Check for FC_FIXED_REPEAT or FC_VARIABLE_REPEAT. if ( *pFormat != FC_NO_REPEAT ) { pStubMsg->MaxCount = MaxCountSave; pStubMsg->Offset = OffsetSave; pStubMsg->BufferMark = pBufferMark; pFormat = NdrpEmbeddedRepeatPointerUnmarshall( pStubMsg, pMemory, pFormat, fNewMemory ); // Continue to the next pointer. continue; } // Compute the pointer to the current memory pointer to the data. ppMemPtr = (uchar **)( pMemory + *((signed short *)(pFormat + 2)) ); // Compute the pointer to the pointer in the buffer. ppBufPtr = (uchar **)(pBufferMark + *((signed short *)(pFormat + 4))); // Increment to the pointer description. pFormat += 6; // // If the incomming encapsulating memory pointer was just allocated, // then explicitly null out the current pointer. // if ( fNewMemory ) *ppMemPtr = 0; NdrpPointerUnmarshall( pStubMsg, ppBufPtr, *ppMemPtr, pFormat ); // Increment to the next pointer description. pFormat += 4; } } PFORMAT_STRING NdrpEmbeddedRepeatPointerUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, uchar * pMemory, PFORMAT_STRING pFormat, uchar fNewMemory ) /*++ Routine Description : Unmarshalls an array's embedded pointers. Arguments : pStubMsg - Pointer to the stub message. pMemory - Pointer to the array whose embedded pointers are being unmarshalled. pFormat - Pointer layout format string description. fNewMemory - TRUE if the array was allocated during unmarshalling, FALSE otherwise. Return : Format string pointer after the pointer layout. --*/ { uchar ** ppMemPtr; uchar ** ppBufPtr; PFORMAT_STRING pFormatSave; uchar * pBufferMark; ulong RepeatCount, RepeatIncrement, Pointers, PointersSave; // Get the beginning of the array in the buffer. pBufferMark = pStubMsg->BufferMark; // Get the repeat count. switch ( *pFormat ) { case FC_FIXED_REPEAT : pFormat += 2; RepeatCount = *((ushort *)pFormat); break; case FC_VARIABLE_REPEAT : RepeatCount = pStubMsg->MaxCount; // // Check if this variable repeat instance also has a variable // offset (this would be the case for a conformant varying array // of pointers, or structures which contain pointers). If so then // increment the format string to point to the actual first array // element which is being marshalled. // if ( pFormat[1] == FC_VARIABLE_OFFSET ) pMemory += *((ushort *)(pFormat + 2)) * pStubMsg->Offset; // else pFormat[1] == FC_FIXED_OFFSET - do nothing break; default : NDR_ASSERT(0,"NdrpEmbeddedRepeatPointerUnmarshall : bad format"); RpcRaiseException( RPC_S_INTERNAL_ERROR ); return 0; } // Increment format string to increment field. pFormat += 2; // Get the increment amount between successive pointers. RepeatIncrement = *((ushort *)pFormat)++; // Array offset is ignored. pFormat += 2; // Get number of pointers in each array element. PointersSave = Pointers = *((ushort *)pFormat)++; pFormatSave = pFormat; // // Loop over the number of shipped array elements. // for ( ; RepeatCount--; pBufferMark += RepeatIncrement, pMemory += RepeatIncrement ) { pFormat = pFormatSave; Pointers = PointersSave; // // Loop over the number of pointer per array element (which can // be greater than one for an array of structures). // for ( ; Pointers--; ) { // Pointer to the pointer in memory. ppMemPtr = (uchar **)(pMemory + *((signed short *)pFormat)++); // Pointer to the pointer's id in the buffer. ppBufPtr = (uchar **)(pBufferMark + *((signed short *)pFormat)++); // // If the incomming encapsulating memory pointer was just // allocated, then explicitly null out the current pointer. // if ( fNewMemory ) *ppMemPtr = 0; NdrpPointerUnmarshall( pStubMsg, ppBufPtr, *ppMemPtr, pFormat ); // Increment past the pointer description. pFormat += 4; } } // Return the format string pointer past the array's pointer description. return pFormatSave + PointersSave * 8; }