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