Blame winpr/libwinpr/rpc/ndr_pointer.c

Packit Service fa4841
/**
Packit Service fa4841
 * WinPR: Windows Portable Runtime
Packit Service fa4841
 * Microsoft Remote Procedure Call (MSRPC)
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
#ifdef HAVE_CONFIG_H
Packit Service fa4841
#include "config.h"
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#include <stdio.h>
Packit Service fa4841
#include <stdlib.h>
Packit Service fa4841
Packit Service fa4841
#include <winpr/rpc.h>
Packit Service fa4841
Packit Service fa4841
#ifndef _WIN32
Packit Service fa4841
Packit Service fa4841
#include "ndr_pointer.h"
Packit Service fa4841
#include "ndr_private.h"
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Pointer Layout: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374376/
Packit Service fa4841
 *
Packit Service fa4841
 * pointer_layout<>:
Packit Service fa4841
 *
Packit Service fa4841
 * FC_PP
Packit Service fa4841
 * FC_PAD
Packit Service fa4841
 * { pointer_instance_layout<> }*
Packit Service fa4841
 * FC_END
Packit Service fa4841
 *
Packit Service fa4841
 * pointer_instance<8>:
Packit Service fa4841
 *
Packit Service fa4841
 * offset_to_pointer_in_memory<2>
Packit Service fa4841
 * offset_to_pointer_in_buffer<2>
Packit Service fa4841
 * pointer_description<4>
Packit Service fa4841
 *
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
PFORMAT_STRING NdrpSkipPointerLayout(PFORMAT_STRING pFormat)
Packit Service fa4841
{
Packit Service fa4841
	pFormat += 2;
Packit Service fa4841
Packit Service fa4841
	while (*pFormat != FC_END)
Packit Service fa4841
	{
Packit Service fa4841
		if (*pFormat == FC_NO_REPEAT)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * FC_NO_REPEAT
Packit Service fa4841
			 * FC_PAD
Packit Service fa4841
			 * pointer_instance<8>
Packit Service fa4841
			 */
Packit Service fa4841
			pFormat += 10;
Packit Service fa4841
		}
Packit Service fa4841
		else if (*pFormat == FC_FIXED_REPEAT)
Packit Service fa4841
		{
Packit Service fa4841
			unsigned short number_of_pointers;
Packit Service fa4841
			/**
Packit Service fa4841
			 * FC_FIXED_REPEAT
Packit Service fa4841
			 * FC_PAD
Packit Service fa4841
			 * iterations<2>
Packit Service fa4841
			 * increment<2>
Packit Service fa4841
			 * offset_to_array<2>
Packit Service fa4841
			 * number_of_pointers<2>
Packit Service fa4841
			 * { pointer_instance<8> }*
Packit Service fa4841
			 */
Packit Service fa4841
			pFormat += 8;
Packit Service bb5c11
			number_of_pointers = *(unsigned short*) pFormat;
Packit Service fa4841
			pFormat += 2 + (number_of_pointers * 8);
Packit Service fa4841
		}
Packit Service fa4841
		else if (*pFormat == FC_VARIABLE_REPEAT)
Packit Service fa4841
		{
Packit Service fa4841
			unsigned short number_of_pointers;
Packit Service fa4841
			/**
Packit Service fa4841
			 * FC_VARIABLE_REPEAT (FC_FIXED_OFFSET | FC_VARIABLE_OFFSET)
Packit Service fa4841
			 * FC_PAD ?!
Packit Service fa4841
			 * increment<2>
Packit Service fa4841
			 * offset_to_array<2>
Packit Service fa4841
			 * number_of_pointers<2>
Packit Service fa4841
			 * { pointer_instance<8> }*
Packit Service fa4841
			 */
Packit Service fa4841
			pFormat += 6;
Packit Service bb5c11
			number_of_pointers = *(unsigned short*) pFormat;
Packit Service fa4841
			pFormat += 2 + (number_of_pointers * 8);
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "error: NdrpSkipPointerLayout unexpected 0x%02X", *pFormat);
Packit Service fa4841
			break;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return pFormat + 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/* Pointers: http://msdn.microsoft.com/en-us/library/windows/desktop/hh802750/ */
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * pointer_type<1>
Packit Service fa4841
 * pointer_attributes<1>
Packit Service fa4841
 * simple_type<1>
Packit Service fa4841
 * FC_PAD
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * pointer_type<1>
Packit Service fa4841
 * pointer_attributes<1>
Packit Service fa4841
 * offset_to_complex_description<2>
Packit Service fa4841
 */
Packit Service fa4841
Packit Service bb5c11
void NdrpPointerBufferSize(unsigned char* pMemory, PFORMAT_STRING pFormat, PMIDL_STUB_MESSAGE pStubMsg)
Packit Service fa4841
{
Packit Service fa4841
	unsigned char type;
Packit Service fa4841
	unsigned char attributes;
Packit Service fa4841
	PFORMAT_STRING pNextFormat;
Packit Service fa4841
	NDR_TYPE_SIZE_ROUTINE pfnSizeRoutine;
Packit Service fa4841
	type = pFormat[0];
Packit Service fa4841
	attributes = pFormat[1];
Packit Service fa4841
	pFormat += 2;
Packit Service fa4841
Packit Service fa4841
	if (attributes & FC_SIMPLE_POINTER)
Packit Service fa4841
		pNextFormat = pFormat;
Packit Service fa4841
	else
Packit Service bb5c11
		pNextFormat = pFormat + *(SHORT*) pFormat;
Packit Service fa4841
Packit Service fa4841
	switch (type)
Packit Service fa4841
	{
Packit Service fa4841
		case FC_RP: /* Reference Pointer */
Packit Service fa4841
			break;
Packit Service fa4841
		case FC_UP: /* Unique Pointer */
Packit Service fa4841
		case FC_OP: /* Unique Pointer in an object interface */
Packit Service fa4841
Packit Service fa4841
			if (!pMemory)
Packit Service fa4841
				return;
Packit Service fa4841
Packit Service fa4841
			break;
Packit Service fa4841
		case FC_FP: /* Full Pointer */
Packit Service fa4841
			WLog_ERR(TAG, "warning: FC_FP unimplemented");
Packit Service fa4841
			break;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if ((attributes & FC_POINTER_DEREF) && pMemory)
Packit Service bb5c11
		pMemory = *(unsigned char**) pMemory;
Packit Service fa4841
Packit Service fa4841
	pfnSizeRoutine = pfnSizeRoutines[*pNextFormat];
Packit Service fa4841
Packit Service fa4841
	if (pfnSizeRoutine)
Packit Service fa4841
		pfnSizeRoutine(pStubMsg, pMemory, pNextFormat);
Packit Service fa4841
}
Packit Service fa4841
Packit Service bb5c11
PFORMAT_STRING NdrpEmbeddedRepeatPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat, unsigned char** ppMemory)
Packit Service fa4841
{
Packit Service fa4841
	ULONG_PTR MaxCount;
Packit Service fa4841
	unsigned char* Memory;
Packit Service fa4841
	unsigned char* MemoryCopy;
Packit Service fa4841
	unsigned char* MemoryPointer;
Packit Service fa4841
	PFORMAT_STRING pFormatNext;
Packit Service fa4841
	PFORMAT_STRING pFormatPointers;
Packit Service fa4841
	unsigned short increment;
Packit Service fa4841
	unsigned short pointer_count;
Packit Service fa4841
	unsigned short offset_to_array;
Packit Service fa4841
	unsigned short number_of_pointers;
Packit Service fa4841
	Memory = pStubMsg->Memory;
Packit Service fa4841
	MemoryCopy = pStubMsg->Memory;
Packit Service fa4841
Packit Service fa4841
	if (*pFormat == FC_FIXED_REPEAT)
Packit Service fa4841
	{
Packit Service fa4841
		pFormat += 2;
Packit Service bb5c11
		MaxCount = *(unsigned short*) pFormat;
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		if (*pFormat != FC_VARIABLE_REPEAT)
Packit Service fa4841
		{
Packit Service fa4841
			RpcRaiseException(1766);
Packit Service fa4841
			return pFormat;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		MaxCount = pStubMsg->MaxCount;
Packit Service fa4841
Packit Service fa4841
		if (pFormat[1] == FC_VARIABLE_OFFSET)
Packit Service fa4841
		{
Packit Service bb5c11
			pMemory += pStubMsg->Offset * (*(unsigned short*) &pFormat[1]);
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	pFormat += 2;
Packit Service bb5c11
	increment = *(unsigned short*) pFormat;
Packit Service fa4841
	pFormat += 2;
Packit Service bb5c11
	offset_to_array = *(unsigned short*) pFormat;
Packit Service fa4841
	pStubMsg->Memory = Memory + offset_to_array;
Packit Service fa4841
	pFormat += 2;
Packit Service bb5c11
	number_of_pointers = *(unsigned short*) pFormat;
Packit Service fa4841
	pFormat += 2;
Packit Service fa4841
	pFormatPointers = pFormat;
Packit Service fa4841
Packit Service fa4841
	if (MaxCount)
Packit Service fa4841
	{
Packit Service fa4841
		do
Packit Service fa4841
		{
Packit Service fa4841
			MaxCount--;
Packit Service fa4841
			pFormatNext = pFormatPointers;
Packit Service fa4841
			pointer_count = number_of_pointers;
Packit Service fa4841
Packit Service fa4841
			if (number_of_pointers)
Packit Service fa4841
			{
Packit Service fa4841
				do
Packit Service fa4841
				{
Packit Service fa4841
					pointer_count--;
Packit Service bb5c11
					MemoryPointer = &pMemory[*(unsigned short*) pFormatNext];
Packit Service fa4841
					NdrpPointerBufferSize(MemoryPointer, pFormatNext + 4, pStubMsg);
Packit Service fa4841
					pFormatNext += 8;
Packit Service bb5c11
				}
Packit Service bb5c11
				while (pointer_count);
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			pMemory += increment;
Packit Service fa4841
			pStubMsg->Memory += increment;
Packit Service bb5c11
		}
Packit Service bb5c11
		while (MaxCount);
Packit Service fa4841
Packit Service fa4841
		Memory = MemoryCopy;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	pFormat = pFormatPointers + (number_of_pointers * 8);
Packit Service fa4841
	pStubMsg->Memory = Memory;
Packit Service fa4841
	return pFormat;
Packit Service fa4841
}
Packit Service fa4841
Packit Service bb5c11
PFORMAT_STRING NdrpEmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat)
Packit Service fa4841
{
Packit Service fa4841
	ULONG_PTR MaxCount;
Packit Service fa4841
	unsigned long Offset;
Packit Service fa4841
	unsigned char* Memory;
Packit Service fa4841
	char PointerLengthSet;
Packit Service fa4841
	PFORMAT_STRING pFormatCopy;
Packit Service fa4841
	unsigned long BufferLength;
Packit Service fa4841
	unsigned long BufferLengthCopy = 0;
Packit Service fa4841
	unsigned long PointerLength;
Packit Service fa4841
	unsigned char* pMemoryPtr = NULL;
Packit Service fa4841
	pFormatCopy = pFormat;
Packit Service fa4841
Packit Service fa4841
	if (!pStubMsg->IgnoreEmbeddedPointers)
Packit Service fa4841
	{
Packit Service fa4841
		PointerLength = pStubMsg->PointerLength;
Packit Service fa4841
		PointerLengthSet = (PointerLength != 0);
Packit Service fa4841
Packit Service fa4841
		if (PointerLengthSet)
Packit Service fa4841
		{
Packit Service fa4841
			BufferLength = pStubMsg->BufferLength;
Packit Service fa4841
			pStubMsg->PointerLength = 0;
Packit Service fa4841
			BufferLengthCopy = BufferLength;
Packit Service fa4841
			pStubMsg->BufferLength = PointerLength;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		MaxCount = pStubMsg->MaxCount;
Packit Service fa4841
		Offset = pStubMsg->Offset;
Packit Service fa4841
		Memory = pStubMsg->Memory;
Packit Service fa4841
		pStubMsg->Memory = pMemory;
Packit Service fa4841
		pFormat = pFormatCopy + 2;
Packit Service fa4841
Packit Service fa4841
		while (*pFormat != FC_END)
Packit Service fa4841
		{
Packit Service fa4841
			if (*pFormat == FC_NO_REPEAT)
Packit Service fa4841
			{
Packit Service fa4841
				NdrpPointerBufferSize(&pMemory[pFormat[2]], &pFormat[6], pStubMsg);
Packit Service fa4841
				pFormat += 10;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			pStubMsg->Offset = Offset;
Packit Service fa4841
			pStubMsg->MaxCount = MaxCount;
Packit Service fa4841
			NdrpEmbeddedRepeatPointerBufferSize(pStubMsg, pMemory, pFormat, &pMemoryPtr);
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		pStubMsg->Memory = Memory;
Packit Service fa4841
Packit Service fa4841
		if (PointerLengthSet)
Packit Service fa4841
		{
Packit Service fa4841
			pStubMsg->PointerLength = pStubMsg->BufferLength;
Packit Service fa4841
			pStubMsg->BufferLength = BufferLengthCopy;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return pFormat;
Packit Service fa4841
}
Packit Service fa4841
Packit Service bb5c11
void NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat)
Packit Service fa4841
{
Packit Service fa4841
	if (*pFormat != FC_RP)
Packit Service fa4841
	{
Packit Service fa4841
		NdrpAlignLength((&pStubMsg->BufferLength), 4);
Packit Service fa4841
		NdrpIncrementLength((&pStubMsg->BufferLength), 4);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	NdrpPointerBufferSize(pMemory, pFormat, pStubMsg);
Packit Service fa4841
}
Packit Service fa4841
Packit Service bb5c11
void NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat)
Packit Service fa4841
{
Packit Service fa4841
	WLog_ERR(TAG, "warning: NdrByteCountPointerBufferSize unimplemented");
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
#endif