Blame winpr/libwinpr/rpc/ndr.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 * Network Data Representation (NDR)
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <stdio.h>
Packit 1fb8d4
#include <stdlib.h>
Packit 1fb8d4
#include <stdarg.h>
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/ndr.h>
Packit 1fb8d4
Packit 1fb8d4
#ifndef _WIN32
Packit 1fb8d4
Packit 1fb8d4
#include "ndr_array.h"
Packit 1fb8d4
#include "ndr_context.h"
Packit 1fb8d4
#include "ndr_pointer.h"
Packit 1fb8d4
#include "ndr_simple.h"
Packit 1fb8d4
#include "ndr_string.h"
Packit 1fb8d4
#include "ndr_structure.h"
Packit 1fb8d4
#include "ndr_union.h"
Packit 1fb8d4
Packit 1fb8d4
#include "ndr_private.h"
Packit 1fb8d4
Packit 1fb8d4
#include "../log.h"
Packit 1fb8d4
#define TAG WINPR_TAG("rpc")
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * MSRPC NDR Types Technical Overview:
Packit 1fb8d4
 * http://dvlabs.tippingpoint.com/blog/2007/11/24/msrpc-ndr-types/
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void NdrPrintParamAttributes(PARAM_ATTRIBUTES attributes)
Packit 1fb8d4
{
Packit 1fb8d4
	if (attributes.ServerAllocSize)
Packit 1fb8d4
		WLog_INFO(TAG, "ServerAllocSize, ");
Packit 1fb8d4
Packit 1fb8d4
	if (attributes.SaveForAsyncFinish)
Packit 1fb8d4
		WLog_INFO(TAG, "SaveForAsyncFinish, ");
Packit 1fb8d4
Packit 1fb8d4
	if (attributes.IsDontCallFreeInst)
Packit 1fb8d4
		WLog_INFO(TAG, "IsDontCallFreeInst, ");
Packit 1fb8d4
Packit 1fb8d4
	if (attributes.IsSimpleRef)
Packit 1fb8d4
		WLog_INFO(TAG, "IsSimpleRef, ");
Packit 1fb8d4
Packit 1fb8d4
	if (attributes.IsByValue)
Packit 1fb8d4
		WLog_INFO(TAG, "IsByValue, ");
Packit 1fb8d4
Packit 1fb8d4
	if (attributes.IsBasetype)
Packit 1fb8d4
		WLog_INFO(TAG, "IsBaseType, ");
Packit 1fb8d4
Packit 1fb8d4
	if (attributes.IsReturn)
Packit 1fb8d4
		WLog_INFO(TAG, "IsReturn, ");
Packit 1fb8d4
Packit 1fb8d4
	if (attributes.IsOut)
Packit 1fb8d4
		WLog_INFO(TAG, "IsOut, ");
Packit 1fb8d4
Packit 1fb8d4
	if (attributes.IsIn)
Packit 1fb8d4
		WLog_INFO(TAG, "IsIn, ");
Packit 1fb8d4
Packit 1fb8d4
	if (attributes.IsPipe)
Packit 1fb8d4
		WLog_INFO(TAG, "IsPipe, ");
Packit 1fb8d4
Packit 1fb8d4
	if (attributes.MustFree)
Packit 1fb8d4
		WLog_INFO(TAG, "MustFree, ");
Packit 1fb8d4
Packit 1fb8d4
	if (attributes.MustSize)
Packit 1fb8d4
		WLog_INFO(TAG, "MustSize, ");
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void NdrProcessParam(PMIDL_STUB_MESSAGE pStubMsg, NDR_PHASE phase, unsigned char* pMemory, NDR_PARAM* param)
Packit 1fb8d4
{
Packit 1fb8d4
	unsigned char type;
Packit 1fb8d4
	PFORMAT_STRING pFormat;
Packit 1fb8d4
Packit 1fb8d4
	/* Parameter Descriptors: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374362/ */
Packit 1fb8d4
Packit 1fb8d4
	if (param->Attributes.IsBasetype)
Packit 1fb8d4
	{
Packit 1fb8d4
		pFormat = &param->Type.FormatChar;
Packit 1fb8d4
Packit 1fb8d4
		if (param->Attributes.IsSimpleRef)
Packit 1fb8d4
			pMemory = *(unsigned char**) pMemory;
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		pFormat = &pStubMsg->StubDesc->pFormatTypes[param->Type.Offset];
Packit 1fb8d4
Packit 1fb8d4
		if (!(param->Attributes.IsByValue))
Packit 1fb8d4
			pMemory = *(unsigned char**) pMemory;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	type = (pFormat[0] & 0x7F);
Packit 1fb8d4
Packit 1fb8d4
	if (type > FC_PAD)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	if (phase == NDR_PHASE_SIZE)
Packit 1fb8d4
	{
Packit 1fb8d4
		NDR_TYPE_SIZE_ROUTINE pfnSizeRoutine = pfnSizeRoutines[type];
Packit 1fb8d4
Packit 1fb8d4
		if (pfnSizeRoutine)
Packit 1fb8d4
			pfnSizeRoutine(pStubMsg, pMemory, pFormat);
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (phase == NDR_PHASE_MARSHALL)
Packit 1fb8d4
	{
Packit 1fb8d4
		NDR_TYPE_MARSHALL_ROUTINE pfnMarshallRoutine = pfnMarshallRoutines[type];
Packit 1fb8d4
Packit 1fb8d4
		if (pfnMarshallRoutine)
Packit 1fb8d4
			pfnMarshallRoutine(pStubMsg, pMemory, *pFormat);
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (phase == NDR_PHASE_UNMARSHALL)
Packit 1fb8d4
	{
Packit 1fb8d4
		NDR_TYPE_UNMARSHALL_ROUTINE pfnUnmarshallRoutine = pfnUnmarshallRoutines[type];
Packit 1fb8d4
Packit 1fb8d4
		if (pfnUnmarshallRoutine)
Packit 1fb8d4
			pfnUnmarshallRoutine(pStubMsg, pMemory, *pFormat);
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (phase == NDR_PHASE_FREE)
Packit 1fb8d4
	{
Packit 1fb8d4
		NDR_TYPE_FREE_ROUTINE pfnFreeRoutine = pfnFreeRoutines[type];
Packit 1fb8d4
Packit 1fb8d4
		if (pfnFreeRoutine)
Packit 1fb8d4
			pfnFreeRoutine(pStubMsg, pMemory, pFormat);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void NdrProcessParams(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, NDR_PHASE phase, void** fpuArgs, unsigned short numberParams)
Packit 1fb8d4
{
Packit 1fb8d4
	unsigned int i;
Packit 1fb8d4
	NDR_PARAM* params;
Packit 1fb8d4
	PFORMAT_STRING fmt;
Packit 1fb8d4
	unsigned char* arg;
Packit 1fb8d4
	unsigned char type;
Packit 1fb8d4
	params = (NDR_PARAM*) pFormat;
Packit 1fb8d4
	WLog_INFO(TAG, "Params = ");
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < numberParams; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
#ifdef __x86_64__
Packit 1fb8d4
		float tmp;
Packit 1fb8d4
#endif
Packit 1fb8d4
		arg = pStubMsg->StackTop + params[i].StackOffset;
Packit 1fb8d4
		fmt = (PFORMAT_STRING) &pStubMsg->StubDesc->pFormatTypes[params[i].Type.Offset];
Packit 1fb8d4
#ifdef __x86_64__
Packit 1fb8d4
Packit 1fb8d4
		if ((params[i].Attributes.IsBasetype) &&
Packit 1fb8d4
				!(params[i].Attributes.IsSimpleRef) &&
Packit 1fb8d4
				((params[i].Type.FormatChar) == FC_FLOAT) && !fpuArgs)
Packit 1fb8d4
		{
Packit 1fb8d4
			tmp = *(double*) arg;
Packit 1fb8d4
			arg = (unsigned char*) &tm;;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
		type = (params[i].Attributes.IsBasetype) ? params[i].Type.FormatChar : *fmt;
Packit 1fb8d4
		WLog_INFO(TAG, "'\t#%u\ttype %s (0x%02X) ", i, FC_TYPE_STRINGS[type], type);
Packit 1fb8d4
		NdrPrintParamAttributes(params[i].Attributes);
Packit 1fb8d4
Packit 1fb8d4
		if (params[i].Attributes.IsIn)
Packit 1fb8d4
		{
Packit 1fb8d4
			NdrProcessParam(pStubMsg, phase, arg, &params[i]);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void NdrClientInitializeNew(PRPC_MESSAGE pRpcMessage, PMIDL_STUB_MESSAGE pStubMsg,
Packit 1fb8d4
							PMIDL_STUB_DESC pStubDesc, unsigned int ProcNum)
Packit 1fb8d4
{
Packit 1fb8d4
	pRpcMessage->Handle = NULL;
Packit 1fb8d4
	pRpcMessage->RpcFlags = 0;
Packit 1fb8d4
	pRpcMessage->ProcNum = ProcNum;
Packit 1fb8d4
	pRpcMessage->DataRepresentation = 0;
Packit 1fb8d4
	pRpcMessage->ReservedForRuntime = NULL;
Packit 1fb8d4
	pRpcMessage->RpcInterfaceInformation = pStubDesc->RpcInterfaceInformation;
Packit 1fb8d4
	pStubMsg->RpcMsg = pRpcMessage;
Packit 1fb8d4
	pStubMsg->BufferStart = NULL;
Packit 1fb8d4
	pStubMsg->BufferEnd = NULL;
Packit 1fb8d4
	pStubMsg->BufferLength = 0;
Packit 1fb8d4
	pStubMsg->StackTop = NULL;
Packit 1fb8d4
	pStubMsg->StubDesc = pStubDesc;
Packit 1fb8d4
	pStubMsg->IgnoreEmbeddedPointers = 0;
Packit 1fb8d4
	pStubMsg->PointerLength = 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void NdrPrintOptFlags(INTERPRETER_OPT_FLAGS optFlags)
Packit 1fb8d4
{
Packit 1fb8d4
	if (optFlags.ClientMustSize)
Packit 1fb8d4
		WLog_INFO(TAG, "ClientMustSize, ");
Packit 1fb8d4
Packit 1fb8d4
	if (optFlags.ServerMustSize)
Packit 1fb8d4
		WLog_INFO(TAG, "ServerMustSize, ");
Packit 1fb8d4
Packit 1fb8d4
	if (optFlags.HasAsyncUuid)
Packit 1fb8d4
		WLog_INFO(TAG, "HasAsyncUiid, ");
Packit 1fb8d4
Packit 1fb8d4
	if (optFlags.HasAsyncHandle)
Packit 1fb8d4
		WLog_INFO(TAG, "HasAsyncHandle, ");
Packit 1fb8d4
Packit 1fb8d4
	if (optFlags.HasReturn)
Packit 1fb8d4
		WLog_INFO(TAG, "HasReturn, ");
Packit 1fb8d4
Packit 1fb8d4
	if (optFlags.HasPipes)
Packit 1fb8d4
		WLog_INFO(TAG, "HasPipes, ");
Packit 1fb8d4
Packit 1fb8d4
	if (optFlags.HasExtensions)
Packit 1fb8d4
		WLog_INFO(TAG, "HasExtensions, ");
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void NdrPrintExtFlags(INTERPRETER_OPT_FLAGS2 extFlags)
Packit 1fb8d4
{
Packit 1fb8d4
	if (extFlags.HasNewCorrDesc)
Packit 1fb8d4
		WLog_INFO(TAG, "HasNewCorrDesc, ");
Packit 1fb8d4
Packit 1fb8d4
	if (extFlags.ClientCorrCheck)
Packit 1fb8d4
		WLog_INFO(TAG, "ClientCorrCheck, ");
Packit 1fb8d4
Packit 1fb8d4
	if (extFlags.ServerCorrCheck)
Packit 1fb8d4
		WLog_INFO(TAG, "ServerCorrCheck, ");
Packit 1fb8d4
Packit 1fb8d4
	if (extFlags.HasNotify)
Packit 1fb8d4
		WLog_INFO(TAG, "HasNotify, ");
Packit 1fb8d4
Packit 1fb8d4
	if (extFlags.HasNotify2)
Packit 1fb8d4
		WLog_INFO(TAG, "HasNotify2, ");
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
CLIENT_CALL_RETURN NdrClientCall(PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, void** stackTop, void** fpuStack)
Packit 1fb8d4
{
Packit 1fb8d4
	RPC_MESSAGE rpcMsg;
Packit 1fb8d4
	unsigned short procNum;
Packit 1fb8d4
	unsigned short stackSize;
Packit 1fb8d4
	unsigned char numberParams;
Packit 1fb8d4
	unsigned char handleType;
Packit 1fb8d4
	MIDL_STUB_MESSAGE stubMsg;
Packit 1fb8d4
	INTERPRETER_FLAGS flags;
Packit 1fb8d4
	INTERPRETER_OPT_FLAGS optFlags;
Packit 1fb8d4
	NDR_PROC_HEADER* procHeader;
Packit 1fb8d4
	NDR_OI2_PROC_HEADER* oi2ProcHeader;
Packit 1fb8d4
	CLIENT_CALL_RETURN client_call_return;
Packit 1fb8d4
	procNum = stackSize = numberParams = 0;
Packit 1fb8d4
	procHeader = (NDR_PROC_HEADER*) &pFormat[0];
Packit 1fb8d4
	client_call_return.Pointer = NULL;
Packit 1fb8d4
	handleType = procHeader->HandleType;
Packit 1fb8d4
	flags = procHeader->OldOiFlags;
Packit 1fb8d4
	procNum = procHeader->ProcNum;
Packit 1fb8d4
	stackSize = procHeader->StackSize;
Packit 1fb8d4
	pFormat += sizeof(NDR_PROC_HEADER);
Packit 1fb8d4
	/* The Header: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378707/ */
Packit 1fb8d4
	/* Procedure Header Descriptor: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374387/ */
Packit 1fb8d4
	/* Handles: http://msdn.microsoft.com/en-us/library/windows/desktop/aa373932/ */
Packit 1fb8d4
	WLog_DBG(TAG, "Oi Header: HandleType: 0x%02X OiFlags: 0x%02X ProcNum: %hu StackSize: 0x%04X",
Packit 1fb8d4
			 handleType, *((unsigned char*) &flags),
Packit 1fb8d4
			 procNum, stackSize);
Packit 1fb8d4
Packit 1fb8d4
	if (handleType > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* implicit handle */
Packit 1fb8d4
		WLog_INFO(TAG, "Implicit Handle");
Packit 1fb8d4
		oi2ProcHeader = (NDR_OI2_PROC_HEADER*) &pFormat[0];
Packit 1fb8d4
		pFormat += sizeof(NDR_OI2_PROC_HEADER);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		/* explicit handle */
Packit 1fb8d4
		WLog_INFO(TAG, "Explicit Handle");
Packit 1fb8d4
		oi2ProcHeader = (NDR_OI2_PROC_HEADER*) &pFormat[6];
Packit 1fb8d4
		pFormat += sizeof(NDR_OI2_PROC_HEADER) + 6;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	optFlags = oi2ProcHeader->Oi2Flags;
Packit 1fb8d4
	numberParams = oi2ProcHeader->NumberParams;
Packit 1fb8d4
	WLog_DBG(TAG, "Oi2 Header: Oi2Flags: 0x%02X, NumberParams: %u ClientBufferSize: %hu ServerBufferSize: %hu",
Packit 1fb8d4
			 *((unsigned char*) &optFlags),
Packit 1fb8d4
			 numberParams,
Packit 1fb8d4
			 oi2ProcHeader->ClientBufferSize,
Packit 1fb8d4
			 oi2ProcHeader->ServerBufferSize);
Packit 1fb8d4
	WLog_INFO(TAG, "Oi2Flags: ");
Packit 1fb8d4
	NdrPrintOptFlags(optFlags);
Packit 1fb8d4
	NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDescriptor, procNum);
Packit 1fb8d4
Packit 1fb8d4
	if (optFlags.HasExtensions)
Packit 1fb8d4
	{
Packit 1fb8d4
		INTERPRETER_OPT_FLAGS2 extFlags;
Packit 1fb8d4
		NDR_PROC_HEADER_EXTS* extensions = (NDR_PROC_HEADER_EXTS*) pFormat;
Packit 1fb8d4
		pFormat += extensions->Size;
Packit 1fb8d4
		extFlags = extensions->Flags2;
Packit 1fb8d4
		WLog_DBG(TAG, "Extensions: Size: %hhu, flags2: 0x%02X",
Packit 1fb8d4
				 extensions->Size, *((unsigned char*) &extensions->Flags2));
Packit 1fb8d4
#ifdef __x86_64__
Packit 1fb8d4
Packit 1fb8d4
		if (extensions->Size > sizeof(*extensions) && fpuStack)
Packit 1fb8d4
		{
Packit 1fb8d4
			int i;
Packit 1fb8d4
			unsigned short fpuMask = *(unsigned short*)(extensions + 1);
Packit 1fb8d4
Packit 1fb8d4
			for (i = 0; i < 4; i++, fpuMask >>= 2)
Packit 1fb8d4
			{
Packit 1fb8d4
				switch (fpuMask & 3)
Packit 1fb8d4
				{
Packit 1fb8d4
					case 1:
Packit 1fb8d4
						*(float*) &stackTop[i] = *(float*) &fpuStack[i];
Packit 1fb8d4
						break;
Packit 1fb8d4
Packit 1fb8d4
					case 2:
Packit 1fb8d4
						*(double*) &stackTop[i] = *(double*) &fpuStack[i];
Packit 1fb8d4
						break;
Packit 1fb8d4
				}
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
		WLog_INFO(TAG, "ExtFlags: ");
Packit 1fb8d4
		NdrPrintExtFlags(extFlags);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	stubMsg.StackTop = (unsigned char*) stackTop;
Packit 1fb8d4
	NdrProcessParams(&stubMsg, pFormat, NDR_PHASE_SIZE, fpuStack, numberParams);
Packit 1fb8d4
	WLog_DBG(TAG, "stubMsg BufferLength: %"PRIu32"", stubMsg.BufferLength);
Packit 1fb8d4
	return client_call_return;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
CLIENT_CALL_RETURN NdrClientCall2(PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, ...)
Packit 1fb8d4
{
Packit 1fb8d4
	va_list args;
Packit 1fb8d4
	CLIENT_CALL_RETURN client_call_return;
Packit 1fb8d4
	va_start(args, pFormat);
Packit 1fb8d4
	client_call_return = NdrClientCall(pStubDescriptor, pFormat, va_arg(args, void**), NULL);
Packit 1fb8d4
	va_end(args);
Packit 1fb8d4
	return client_call_return;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#endif