FreeRDP/winpr/libwinpr/rpc/ndr_structure.c
2014-09-09 16:31:46 +02:00

290 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_private.h"
#include "ndr_pointer.h"
#include "ndr_structure.h"
#include "../log.h"
#define TAG "rpc"
/* Structures: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378695/ */
void NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
{
/**
* FC_STRUCT
* alignment<1>
* memory_size<2>
* member_layout<>
* FC_END
*/
/**
* FC_PSTRUCT
* alignment<1>
* memory_size<2>
* pointer_layout<>
* member_layout<>
* FC_END
*/
unsigned char type;
unsigned char alignment;
unsigned short memory_size;
type = pFormat[0];
alignment = pFormat[1] + 1;
memory_size = *(unsigned short *) &pFormat[2];
NdrpAlignLength(&(pStubMsg->BufferLength), alignment);
NdrpIncrementLength(&(pStubMsg->BufferLength), memory_size);
pFormat += 4;
if (*pFormat == FC_PSTRUCT)
NdrpEmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
WLog_ERR(TAG, "warning: NdrSimpleStructBufferSize unimplemented");
}
void NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
{
/**
* FC_CSTRUCT alignment<1>
* memory_size<2>
* offset_to_array_description<2>
* member_layout<>
* FC_END
*/
/**
* FC_CPSTRUCT alignment<1>
* memory_size<2>
* offset_to_array_description<2>
* pointer_layout<>
* member_layout<> FC_END
*/
WLog_ERR(TAG, "warning: NdrConformantStructBufferSize unimplemented");
}
void NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
{
/**
* FC_CVSTRUCT alignment<1>
* memory_size<2>
* offset_to_array_description<2>
* [pointer_layout<>]
* layout<>
* FC_END
*/
WLog_ERR(TAG, "warning: NdrConformantVaryingStructBufferSize unimplemented");
}
ULONG NdrComplexStructMemberSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
{
ULONG size = 0;
while (*pFormat != FC_END)
{
switch (*pFormat)
{
case FC_BYTE:
case FC_CHAR:
case FC_SMALL:
case FC_USMALL:
size += sizeof(BYTE);
break;
case FC_WCHAR:
case FC_SHORT:
case FC_USHORT:
case FC_ENUM16:
size += sizeof(USHORT);
break;
case FC_LONG:
case FC_ULONG:
case FC_ENUM32:
size += sizeof(ULONG);
break;
case FC_INT3264:
case FC_UINT3264:
size += sizeof(INT_PTR);
break;
case FC_FLOAT:
size += sizeof(FLOAT);
break;
case FC_DOUBLE:
size += sizeof(DOUBLE);
break;
case FC_HYPER:
size += sizeof(ULONGLONG);
break;
case FC_ERROR_STATUS_T:
size += sizeof(error_status_t);
break;
case FC_IGNORE:
break;
case FC_RP:
case FC_UP:
case FC_OP:
case FC_FP:
case FC_POINTER:
size += sizeof(void *);
if (*pFormat != FC_POINTER)
pFormat += 4;
break;
case FC_ALIGNM2:
NdrpAlignLength(&size, 2);
break;
case FC_ALIGNM4:
NdrpAlignLength(&size, 4);
break;
case FC_ALIGNM8:
NdrpAlignLength(&size, 8);
break;
case FC_STRUCTPAD1:
case FC_STRUCTPAD2:
case FC_STRUCTPAD3:
case FC_STRUCTPAD4:
case FC_STRUCTPAD5:
case FC_STRUCTPAD6:
case FC_STRUCTPAD7:
size += *pFormat - FC_STRUCTPAD1 + 1;
break;
case FC_PAD:
break;
case FC_EMBEDDED_COMPLEX:
WLog_ERR(TAG, "warning: NdrComplexStructMemberSize FC_EMBEDDED_COMPLEX unimplemented");
break;
default:
WLog_ERR(TAG, "warning: NdrComplexStructMemberSize 0x%02X unimplemented", *pFormat);
break;
}
pFormat++;
}
return size;
}
void NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
{
/**
* FC_BOGUS_STRUCT
* alignment<1>
* memory_size<2>
* offset_to_conformant_array_description<2>
* offset_to_pointer_layout<2>
* member_layout<>
* FC_END
* [pointer_layout<>]
*/
ULONG_PTR MaxCount;
unsigned long Offset;
unsigned long ActualCount;
unsigned char *pMemoryCopy;
unsigned char type;
unsigned char alignment;
unsigned short memory_size;
unsigned char *pointer_layout;
unsigned char *conformant_array_description;
unsigned short offset_to_pointer_layout;
unsigned short offset_to_conformant_array_description;
type = pFormat[0];
pMemoryCopy = pMemory;
pointer_layout = conformant_array_description = NULL;
if (type != FC_BOGUS_STRUCT)
{
WLog_ERR(TAG, "error: expected FC_BOGUS_STRUCT, got 0x%02X", type);
return;
}
alignment = pFormat[1] + 1;
memory_size = *(unsigned short *) &pFormat[2];
NdrpAlignLength(&(pStubMsg->BufferLength), alignment);
if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
{
unsigned long BufferLengthCopy = pStubMsg->BufferLength;
int IgnoreEmbeddedPointersCopy = pStubMsg->IgnoreEmbeddedPointers;
pStubMsg->IgnoreEmbeddedPointers = 1;
NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
pStubMsg->IgnoreEmbeddedPointers = IgnoreEmbeddedPointersCopy;
pStubMsg->PointerLength = pStubMsg->BufferLength;
pStubMsg->BufferLength = BufferLengthCopy;
}
pFormat += 4;
offset_to_conformant_array_description = *(unsigned short *) &pFormat[0];
if (offset_to_conformant_array_description)
conformant_array_description = (unsigned char *) pFormat + offset_to_conformant_array_description;
pFormat += 2;
offset_to_pointer_layout = *(unsigned short *) &pFormat[0];
if (offset_to_pointer_layout)
pointer_layout = (unsigned char *) pFormat + offset_to_pointer_layout;
pFormat += 2;
pStubMsg->Memory = pMemory;
if (conformant_array_description)
{
ULONG size;
unsigned char array_type;
array_type = conformant_array_description[0];
size = NdrComplexStructMemberSize(pStubMsg, pFormat);
WLog_ERR(TAG, "warning: NdrComplexStructBufferSize array_type: 0x%02X unimplemented", array_type);
NdrpComputeConformance(pStubMsg, pMemory + size, conformant_array_description);
NdrpComputeVariance(pStubMsg, pMemory + size, conformant_array_description);
MaxCount = pStubMsg->MaxCount;
ActualCount = pStubMsg->ActualCount;
Offset = pStubMsg->Offset;
}
if (conformant_array_description)
{
unsigned char array_type;
array_type = conformant_array_description[0];
pStubMsg->MaxCount = MaxCount;
pStubMsg->ActualCount = ActualCount;
pStubMsg->Offset = Offset;
WLog_ERR(TAG, "warning: NdrComplexStructBufferSize array_type: 0x%02X unimplemented", array_type);
}
pStubMsg->Memory = pMemoryCopy;
if (pStubMsg->PointerLength > 0)
{
pStubMsg->BufferLength = pStubMsg->PointerLength;
pStubMsg->PointerLength = 0;
}
}
#endif