/** * WinPR: Windows Portable Runtime * Microsoft Remote Procedure Call (MSRPC) * * Copyright 2012 Marc-Andre Moreau * * 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 #include #include #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